设为首页收藏本站官方微博

建议 【Opengl游戏汉化 #5】 尼比鲁:秘密年代 (NiBiRu)字幕显示函数修改2

[复制链接]
查看: 338|回复: 0
打印 上一主题 下一主题

[建议] 【Opengl游戏汉化 #5】 尼比鲁:秘密年代 (NiBiRu)字幕显示函数修改2

跳转到指定楼层
楼主
发表于 2023-9-6 15:25 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

【Opengl游戏汉化 #5】 尼比鲁:秘密年代 (NiBiRu)字幕显示函数修改2

本帖最后由 shane007 于 2023-9-6 15:32 编辑 # f* [3 b5 g' K* E

& p) j' L! M. Z# h5 T以下是一个用来做参照的opengl显示字符串的代码,使用了freetype库。& l( R2 V6 @' x9 Z; Q1 }4 v
本代码经过分析以及改写之后,将取代游戏原有的显示函数。
- m" ?; o  m7 f5 W; d) x
" x1 e3 R; R* c* s* k8 }' j& r, {5 F代码详细说明如下+ v. [4 t. ]* e! s# q
' h2 L  G9 p. j+ \
  1. 在上述 renderString 函数中,我们有以下关键部分的解释:: \9 j3 ~7 ?) o) T

  2. 2 F  O' m! y1 ]0 T3 G
  3. glBindTexture(GL_TEXTURE_2D, fontTexture);:将字体纹理绑定到当前的OpenGL上下文。这是因为我们要使用 fontTexture 中存储的字形位图数据进行渲染。
    ; |( |! M7 L$ k
  4. : x, m4 u0 e8 L( B7 _1 G
  5. glEnable(GL_BLEND); 和 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);:启用混合模式以处理字符的透明度。混合模式通过 glBlendFunc 设置,这里使用了常见的源和目标因子来实现源颜色与目标颜色的混合,从而实现透明效果。
    $ @" }4 j4 Z% U8 h: m
  6. 2 l; N" [& T% R: ?
  7. glBegin(GL_QUADS); 和 glEnd();:在这两个函数之间的代码用于指定字符的四边形顶点,以便在OpenGL上下文中绘制字符。
    1 m- S7 j- {2 \! D5 Z" @* Z
  8. 7 ?) k  T" J' t( k
  9. for (const char* p = text; *p; p++) { ... }:这个循环遍历传递给函数的字符串 text 中的每个字符,然后为每个字符执行以下操作:
    ! j7 q4 K( r1 X% A: ?3 y7 i2 M  @
  10. $ V$ F' p. p: T, C2 d* L# F2 G" [  k/ q
  11. FT_Load_Char(face, *p, FT_LOAD_RENDER);:使用FreeType加载字符的字形数据,包括轮廓和位图信息。加载后,可以从 face->glyph 中访问该字符的字形数据。1 g0 ]- K4 ^0 z1 T4 J

  12. 4 y- U# z7 Y0 U
  13. 计算字符在屏幕上的位置和大小,包括 xpos(x坐标)、ypos(y坐标)、w(宽度)和 h(高度)。
    / p5 F# r7 L0 r: _5 t, G
  14.   ~4 B8 L. T% i
  15. 使用 glTexCoord2f 和 glVertex2f 来指定字符的纹理坐标和顶点坐标,以创建一个四边形。这四边形将字形的位图数据绘制到屏幕上的指定位置。9 U* M* Q& c0 D, Q  g# t
  16. 6 m" Y/ V" q4 H( E$ `- a9 Z
  17. x += (face->glyph->advance.x >> 6);:更新 x 坐标,以便将下一个字符紧密排列在当前字符的后面。face->glyph->advance.x 包含字符的横向位移信息,>> 6 是用来将其转换为像素单位的操作。$ T6 O+ B$ _) K
  18. , I' P* v* B2 \2 z4 a& Y2 Y
  19. 最后,glDisable(GL_BLEND); 用于禁用混合模式,以免影响后续的绘制操作。3 y/ w  W3 J( \% K$ D% w
  20. / e: W4 x: `; S$ j
  21. 总之,renderString 函数的作用是将传递给它的字符串中的字符一个接一个地绘制到OpenGL上下文中,使用FreeType加载的字形数据和字体纹理来实现文本渲染效果。渲染过程涉及到字符的位置计算、纹理坐标的设置以及混合模式的启用和禁用,以确保字符在屏幕上正确显示。
    / g8 t. z3 O" ~. e
复制代码
" Y; m) W' A4 C4 p) @9 \+ S- A

# G6 _- e1 g- m. q# B( i
  1. 字形数据处理的关键函数之一。以下是 FT_Load_Char 函数的详细解释:( |; N/ |: C) |( H; d2 }5 S

  2. 1 N! ]6 R4 e$ S1 B. X8 L& @: U
  3. 参数:( j* n& t# R2 w# U& o; K5 M" t+ V
  4. ; m& Z$ p% G4 ]2 `
  5. face:一个指向已经打开的字体文件的 FT_Face 结构体的指针。FT_Face 包含了字体的各种信息,包括字形数据。
    % n8 x2 N* d+ K9 x
  6. char_code:要加载的字符的Unicode编码值。您需要传递字符的Unicode编码作为此参数,以指定要加载的字符。' p* ~- K+ m- C" V0 x# `8 T0 U
  7. load_flags:一个用于控制字形加载选项的标志位。您可以使用这些标志位来控制加载的方式,例如是否要加载字形的轮廓数据、是否要加载字形的位图数据等。
    9 I# J; O6 v1 S' o. N
  8. 功能:
    8 G1 m& _6 G+ s/ ^. d
  9. 1 ]& u! K( L8 x4 n, V/ b
  10. FT_Load_Char 函数的主要功能是加载指定字符的字形数据。, f2 G; ^2 f" t' W5 c+ y
  11. 如果成功,它将在 FT_Face 结构体中的 glyph 字段中填充有关字符的字形信息。
    ' K7 S7 p5 z0 S1 V: d! D, y; v" b
  12. 这包括了字符的轮廓数据、位图数据、宽度、高度、位图偏移等等,具体取决于传递给 load_flags 参数的设置。
    " ~5 j  I3 S& U, C+ f3 }
  13. 使用示例:$ b$ }; u8 W9 }' d. Y& T) X2 W
  14. 3 D9 y: Q3 q. O9 k2 L) v0 b
  15. c/ a7 |3 k: H1 ^: s! J! S
  16. Copy code
    & h6 q. N. |" x
  17. FT_Load_Char(face, 'A', FT_LOAD_RENDER);
    * u& b' |) i+ j0 n
  18. 这个示例会加载字体中字符 'A' 的字形数据,并将其渲染到位图中。FT_LOAD_RENDER 标志告诉FreeType要渲染字符的位图数据。加载后,您可以在 face->glyph 结构体中找到有关 'A' 字符的相关信息,包括位图数据、宽度、高度、位图偏移等等。
    8 q' J$ C$ C, V" s4 K5 o* E7 R+ B
  19. ) H2 h; y, W/ |4 P* G: a- @
  20. 错误处理:
    / ?5 j* S8 J/ Z0 G! f* S& O
  21. / j, ^& N% i" N  S2 m
  22. 如果加载失败,FT_Load_Char 函数可以返回错误代码。您应该检查返回值以进行错误处理,并根据需要采取适当的措施,例如跳过加载失败的字符或终止渲染过程。/ q2 j# m( T1 o+ v; k9 ~
  23. 总之,FT_Load_Char 函数是FreeType库中用于加载指定字符的字形数据的重要功能之一,它使您能够准备要渲染的字符数据,以便在文本渲染中使用。加载的数据可以包括字符的轮廓信息(矢量数据)和位图信息,具体取决于 load_flags 参数的设置。这个函数在字体渲染中起到关键作用,以便将字符正确呈现在屏幕上。
复制代码
* }4 r1 Z, Q+ H2 T8 f' X( c' f

6 Z. [8 [) F6 D8 r代码
4 U! Y- k1 z9 S
( l6 H0 S) F  N0 ?$ w

  1. & R' Z% \  Y4 _3 a  N& Z9 i6 F& b. }9 B
  2. ; w) ~$ _# o: V- `0 N8 i

  3. , l- l  ~! H# p: V' p# H; s4 L
  4. #include <stdio.h>
    8 ^. U' l5 C$ r. G8 O
  5. #include <stdlib.h>7 M4 P9 U+ L( j& A# M
  6. #include <GL/glew.h>) `! C6 Q/ z. P" a/ Z
  7. #include <GLFW/glfw3.h>2 o2 h4 {+ B$ x6 U1 g: ~
  8. #include <ft2build.h>/ a# V: W/ B( i# H
  9. #include FT_FREETYPE_H7 b9 f. j+ {& }9 m9 F, y
  10. ; D2 a* Q: _2 o) N; J# i7 N
  11. // 定义字形数据的字节数组' ?( Q8 I; D6 z. Q5 C
  12. unsigned char fontData[] = {
    . z# q6 V1 i. ]3 D* k8 L8 A; k
  13.     // 字形数据的字节表示
    ' g& p$ P; B/ g. m8 a
  14.     // 例如,这里可以包含字母、数字和符号的字形数据
    1 Z6 N; q* N0 g+ b, Y7 Z
  15. };
    / z: A% T$ {- G5 b- T% s0 K+ V! q" G
  16. ' N$ H: o( }! u/ P* P9 |2 v
  17. FT_Library library;
      k- l& D7 W4 m
  18. FT_Face face;
    2 ~9 r2 Y0 [, k& x/ k$ W! n* H
  19. GLuint fontTexture;7 a9 a& C- n' c! b0 P7 Y
  20. 4 d; g; N0 i6 J% U
  21. // 初始化FreeType库和OpenGL
    7 T6 G% N9 U3 G3 C9 g+ i" @* ]9 L) }5 a
  22. void initialize() {
    . M  S- h8 r" c2 g, K( _
  23.     if (FT_Init_FreeType(&library)) {  {/ _3 y7 h6 V
  24.         fprintf(stderr, "Failed to initialize FreeType\n");
    " F  U3 G0 \, z
  25.         exit(EXIT_FAILURE);
      K( s- }# k+ ]' J5 k
  26.     }
    . g4 ]( W! {* x, w9 ^  l
  27. 7 A; h3 H) g1 z# y$ ]
  28.     if (FT_New_Memory_Face(library, fontData, sizeof(fontData), 0, &face)) {# y( L3 X3 w# d
  29.         fprintf(stderr, "Failed to create a FreeType font face\n");7 y! B2 ?: I  {, ?  j8 ~% [
  30.         exit(EXIT_FAILURE);
    ! a& r, W* U/ u! ^
  31.     }
    . d' @% N! \1 V% m0 q) v" j

  32.   C: e, ]# U9 Z! a- g. V2 i
  33.     if (FT_Set_Pixel_Sizes(face, 0, 48)) { // 设置字体大小
    ; f( `4 }# T7 o, f
  34.         fprintf(stderr, "Failed to set font size\n");/ h: a. `! }# i; R( l7 Y
  35.         exit(EXIT_FAILURE);
    - c$ E; W$ M3 Y7 I2 r" H8 R* j
  36.     }
    ' g; I* k- @" z
  37. 4 m  h" G3 P' s
  38.     glGenTextures(1, &fontTexture);
    4 m* l) J, Q) ~7 s' j4 b
  39.     glBindTexture(GL_TEXTURE_2D, fontTexture);
    ! o# R8 {& z5 f2 L3 E" X
  40.     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    $ K7 I8 F' J! c% L* P

  41. " i2 l1 m) \) u2 a- D; \
  42.     // 将字形数据传递给OpenGL纹理5 f2 S. w# `9 ]6 s: ?
  43.     for (int i = 0; i < 128; i++) {
    3 _& V3 k. A3 I( ]! y
  44.         if (FT_Load_Char(face, i, FT_LOAD_RENDER)) {
    ) ]! j! J. T" i! o6 g; k7 Z% e
  45.             fprintf(stderr, "Failed to load glyph for character '%c'\n", i);
    / |* s( f5 m% V; t5 o* l
  46.             continue;
    ; d$ k) ^6 k# W/ \  M
  47.         }
    & s7 M2 d+ A7 k2 E9 O

  48. 4 g: R6 ]# Q7 c& H: m- G3 A( X
  49.         glTexImage2D(* N, ?! j5 w- _8 I( A" S
  50.             GL_TEXTURE_2D,
    ( G. }3 `1 h& h( k2 K" I+ f
  51.             0,
    % [1 n% R/ ~8 l  k1 ~
  52.             GL_RED,* }, o. T& W' J; G: J
  53.             face->glyph->bitmap.width,. u$ ?7 E2 k& t7 I
  54.             face->glyph->bitmap.rows,- {/ d4 e- ?# u3 l
  55.             0,6 d# T/ I. B6 U- o. A1 K/ b( I7 D
  56.             GL_RED,
    / d1 j) j! Z9 @( E5 A. L
  57.             GL_UNSIGNED_BYTE,
    6 F3 x" B. k5 I2 D1 M4 |
  58.             face->glyph->bitmap.buffer
    ) p5 [0 o( }# a  j1 O( s) k
  59.         );' G; a- w$ I: h2 m9 O( L0 E! {
  60. $ E) Q  z% k+ }: ~7 z, E2 b  r
  61.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    9 g1 }1 s" l7 a$ n
  62.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);7 m. E; G; W3 j+ o3 f0 m
  63.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);/ @& t" A0 u% H. ], A7 T/ ^6 }
  64.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);, X9 x; B: [0 u
  65.     }0 _5 d9 b( N) C# j7 d: p
  66. }/ s5 J- y8 C; ]; Z

  67. 0 |3 ?5 ^1 C$ K& v6 s/ c+ z; E9 ]* A
  68. // 渲染字符串/ K' R& d6 i6 T5 [+ d* \6 r) L# a* z
  69. void renderString(const char* text, float x, float y) {5 R; r2 `- c3 w; j
  70.     glBindTexture(GL_TEXTURE_2D, fontTexture);8 T2 t( K! v/ g$ a" \* _4 F
  71. 4 Y- H# v( a) j5 N5 u
  72.     glEnable(GL_BLEND);% P/ X: C$ i% l5 x3 |( C
  73.     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);9 H2 R6 O( K( Z! X( h) r

  74. 9 i3 Z$ X3 S2 |# {2 x' I6 v: s
  75.     glBegin(GL_QUADS);
    . O( O  x1 {8 a8 j4 T: H$ l
  76.     for (const char* p = text; *p; p++) {/ R( Z8 f7 _- e% W# D' V* P
  77.         FT_Load_Char(face, *p, FT_LOAD_RENDER);2 J% y/ @0 N5 _. m) ~
  78. ( O" X9 p: D3 A: f; s4 `& N
  79.         glTexImage2D(
    ! h6 ]4 I" F7 C
  80.             GL_TEXTURE_2D,5 F5 a2 i' `9 K5 H) X( K( X3 Y
  81.             0,/ ^1 k: ~2 E' [/ k1 N; v# O* X
  82.             GL_RED,) f" ]% o' S8 _& @' j6 j2 N
  83.             face->glyph->bitmap.width,
    + z& M3 {+ U$ Q- {3 C
  84.             face->glyph->bitmap.rows,
    0 H* q) D3 B% n/ S8 j9 u" o0 ^/ [
  85.             0,
    3 T" `2 b* b( k" o& V. [5 ^  x" l- ?
  86.             GL_RED,
    4 [7 v( P: \9 Z( C9 D9 a& y) V
  87.             GL_UNSIGNED_BYTE,
    4 `0 s, l2 s% Z" _' e
  88.             face->glyph->bitmap.buffer, F* ]6 O4 R1 B" y! h* {
  89.         );
    / e% E* g3 b' K( f

  90. 6 g& V4 S9 R# g8 Y8 f$ l) Q
  91.         float xpos = x + face->glyph->bitmap_left;
    , H; X% d' l: x' ]
  92.         float ypos = y - (face->glyph->bitmap.rows - face->glyph->bitmap_top);
    9 W" w2 [% l2 O

  93. & G6 H  ^) N" N
  94.         float w = face->glyph->bitmap.width;9 N% k7 a& e* D- a
  95.         float h = face->glyph->bitmap.rows;# W3 t' t6 o" h2 `0 ^+ h
  96. # ^& S) @: E' G$ E0 J2 J! {' v5 h& Q
  97.         glTexCoord2f(0, 0);
    8 }# q# r! X8 E  a. ^7 d6 k
  98.         glVertex2f(xpos, ypos);
    ' l) j( e1 _  L2 J3 m6 W4 ~' n

  99. , E! J5 e2 A* [+ m( f
  100.         glTexCoord2f(0, 1);
    $ \2 v1 h& l. l, u
  101.         glVertex2f(xpos, ypos + h);
    : D& k* |) O3 k5 U) W# M
  102. 9 Q- u- s+ P0 q8 R% s% H3 P) w5 `
  103.         glTexCoord2f(1, 1);+ G# M7 D& I# \$ g, k1 l4 R; @# w
  104.         glVertex2f(xpos + w, ypos + h);3 t3 ]( V$ i" _0 x6 K; S) f4 G

  105. # j3 }6 b. Z- ^
  106.         glTexCoord2f(1, 0);
    ! W9 ]4 K9 R. o; C1 N
  107.         glVertex2f(xpos + w, ypos);
    * t  F! k* t6 ^; ?1 O$ F1 O

  108. 0 d& A+ o1 J$ r7 F  x) V* p& o
  109.         x += (face->glyph->advance.x >> 6); // 字符之间的间距
    0 X2 @& U* _4 A& u4 [
  110.     }: M% {- O( j$ B" i/ ]9 z! _7 `
  111.     glEnd();3 \/ i, L) Y1 L8 T1 P
  112. 1 Y$ G. i4 s. z* U8 U* I4 y
  113.     glDisable(GL_BLEND);5 g  y( P" v/ k' M3 C' {7 p3 T7 G
  114. }6 g4 c% a6 N$ ^# r  o

  115. 5 Z8 O. @$ N: W2 r, ~0 I% B
  116. int main() {% ^/ E4 S# W; e8 m
  117.     if (!glfwInit()) {3 K' \( z$ w; _2 ~' t5 t) @$ |6 J8 |
  118.         fprintf(stderr, "Failed to initialize GLFW\n");7 [. x5 L) i1 @& f  G% K
  119.         return -1;
    ! c( E: o! X6 @8 h: {& S  k
  120.     }
    % T' L% R* }# j  @# F; h% v3 X8 F

  121. ; Y5 \5 ^8 Y3 ^; `& {# E
  122.     GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL Text Rendering", NULL, NULL);/ g! }1 z6 W5 c: ^* p
  123.     if (!window) {3 P3 R8 N1 B% q' _
  124.         fprintf(stderr, "Failed to create GLFW window\n");3 y: x) z; u: f/ ~8 Q; u
  125.         glfwTerminate();1 }6 A2 `" }. B5 X" Z
  126.         return -1;
      l8 {% e9 \3 {2 ?% ~$ t9 D
  127.     }, |1 }' U+ O. y9 {( D1 O% `

  128.   W/ N% y5 i2 w( |( ^9 {
  129.     glfwMakeContextCurrent(window);; N1 H. n0 b9 v- k; h
  130.     glewInit();  S6 b2 ?& r! x) t$ h  P% R
  131. ' E; u) W- V/ L6 T( }2 \
  132.     initialize();
    # b6 ]# O: F3 e/ S
  133. 9 |2 r4 J" @2 q8 _; Z
  134.     while (!glfwWindowShouldClose(window)) {
    8 @8 l  t$ @5 @/ |
  135.         glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    9 g# @5 s% t+ l
  136.         glClear(GL_COLOR_BUFFER_BIT);9 t  y$ c8 ?$ H3 b

  137. / M3 y% q, {+ B: ]
  138.         glColor3f(1.0f, 1.0f, 1.0f);
    1 X9 }$ p% y* H  T/ o3 B
  139.         renderString("Hello, OpenGL!", 100.0f, 100.0f);
    ! ?2 ?* H9 W& z8 D

  140.   [+ x" N3 G& c6 M. ?" c. \
  141.         glfwSwapBuffers(window);$ c% W  L; J" p) x& t  Y3 Q
  142.         glfwPollEvents();
    ( o; _& m- {/ c
  143.     }' r# H1 ^( i% @, U
  144. 7 S1 ~/ M& U/ |) ?
  145.     FT_Done_Face(face);
    0 j+ H6 T0 o1 e5 O5 r- R/ T
  146.     FT_Done_FreeType(library);: Z6 A0 t: D9 i/ p) X5 N

  147. ( T1 ~- d  C# B4 q$ ]
  148.     glfwTerminate();
    3 a; [; P* W) z
  149. 4 g1 e  `0 ]6 ^+ H% k
  150.     return 0;
    ' Y0 |  v  h# x% o
  151. }' i/ s/ H. W! q" E& `& R0 }
复制代码

  k+ e! K% c* k
3 O8 }3 ]3 p# U. G4 N( d3 F1 Z4 L
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 很美好很美好 很差劲很差劲
回复

使用道具 举报

高级模式
B Color Image Link Quote Code Smilies

本版积分规则

冒险解谜游戏中文网 ChinaAVG

官方微博官方微信号小黑屋 微信玩家群  

(C) ChinaAVG 2004 - 2019 All Right Reserved. Powered by Discuz! X3.2
辽ICP备11008827号 | 桂公网安备 45010702000051号

冒险,与你同在。 冒险解谜游戏中文网ChinaAVG诞生于2004年9月9日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

快速回复 返回顶部 返回列表