冒险解谜游戏中文网 ChinaAVG

标题: 【Opengl游戏汉化 #5】 尼比鲁:秘密年代 (NiBiRu)字幕显示函数修改2 [打印本页]

作者: shane007    时间: 2023-9-6 15:25
标题: 【Opengl游戏汉化 #5】 尼比鲁:秘密年代 (NiBiRu)字幕显示函数修改2
本帖最后由 shane007 于 2023-9-6 15:32 编辑 3 Z) M$ p. K; U3 C

# |" e4 E$ L6 D以下是一个用来做参照的opengl显示字符串的代码,使用了freetype库。
8 c/ j4 X9 ]" `本代码经过分析以及改写之后,将取代游戏原有的显示函数。
, c, \7 \$ |% w, D7 M4 T$ O/ ]
  K8 |" i$ S( Z代码详细说明如下/ ]- \) U/ |+ D, Q1 h) i$ e- }! Z
0 V8 ~7 E% l' J+ c7 l! B: h0 F: B4 W
  1. 在上述 renderString 函数中,我们有以下关键部分的解释:, A! g: S7 }: c% E  T0 |; S7 ^

  2. % j! K3 W3 a' v# p( r
  3. glBindTexture(GL_TEXTURE_2D, fontTexture);:将字体纹理绑定到当前的OpenGL上下文。这是因为我们要使用 fontTexture 中存储的字形位图数据进行渲染。
    8 \5 J9 R: m4 a2 n8 N7 }

  4. - ]# L; E6 `6 ~8 V
  5. glEnable(GL_BLEND); 和 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);:启用混合模式以处理字符的透明度。混合模式通过 glBlendFunc 设置,这里使用了常见的源和目标因子来实现源颜色与目标颜色的混合,从而实现透明效果。- E& N# \; h, X0 D7 H

  6. + m5 N+ B% f8 E& ~
  7. glBegin(GL_QUADS); 和 glEnd();:在这两个函数之间的代码用于指定字符的四边形顶点,以便在OpenGL上下文中绘制字符。6 C) t- {( U+ @( f* \% `

  8. + d1 _- X. J  Y+ U' p! d7 |  ~1 C
  9. for (const char* p = text; *p; p++) { ... }:这个循环遍历传递给函数的字符串 text 中的每个字符,然后为每个字符执行以下操作:0 w9 ~! A9 T: C* ?

  10. ' b: L8 Q! Q) H0 ?1 k, o: m; R
  11. FT_Load_Char(face, *p, FT_LOAD_RENDER);:使用FreeType加载字符的字形数据,包括轮廓和位图信息。加载后,可以从 face->glyph 中访问该字符的字形数据。5 y" e8 ~7 @% `! F; T; O
  12. , \7 w! }$ |$ K9 y
  13. 计算字符在屏幕上的位置和大小,包括 xpos(x坐标)、ypos(y坐标)、w(宽度)和 h(高度)。
    ; K! p4 }3 M8 d2 s5 a

  14. 5 z( C! v6 ?9 ^* F
  15. 使用 glTexCoord2f 和 glVertex2f 来指定字符的纹理坐标和顶点坐标,以创建一个四边形。这四边形将字形的位图数据绘制到屏幕上的指定位置。$ @; Z4 `: g( i7 o' n, A0 Q, z: {

  16. ' |9 v7 e& p( N
  17. x += (face->glyph->advance.x >> 6);:更新 x 坐标,以便将下一个字符紧密排列在当前字符的后面。face->glyph->advance.x 包含字符的横向位移信息,>> 6 是用来将其转换为像素单位的操作。4 ~) v" p: _( ^; `1 Z; {

  18. ; ?% ?* r0 W5 x4 K% H
  19. 最后,glDisable(GL_BLEND); 用于禁用混合模式,以免影响后续的绘制操作。0 L0 Y+ \9 R! c: V0 a* t
  20. 2 U: a4 p1 K  ~% ~$ Z/ M
  21. 总之,renderString 函数的作用是将传递给它的字符串中的字符一个接一个地绘制到OpenGL上下文中,使用FreeType加载的字形数据和字体纹理来实现文本渲染效果。渲染过程涉及到字符的位置计算、纹理坐标的设置以及混合模式的启用和禁用,以确保字符在屏幕上正确显示。% a9 J1 B# y/ x8 P
复制代码

: C1 Q6 N" n5 R# }
  p3 W+ d: ~1 h4 t  N, M
  1. 字形数据处理的关键函数之一。以下是 FT_Load_Char 函数的详细解释:; l- t& G" U, O% ^

  2. ( O* K0 M; b/ Q5 j2 p/ t1 W
  3. 参数:( o( \' v4 {1 k% X" R; r3 E$ \
  4. 0 p! z6 p) u/ I4 a* c( K/ S
  5. face:一个指向已经打开的字体文件的 FT_Face 结构体的指针。FT_Face 包含了字体的各种信息,包括字形数据。) Y3 X5 Z/ j, E  q, `% M5 w
  6. char_code:要加载的字符的Unicode编码值。您需要传递字符的Unicode编码作为此参数,以指定要加载的字符。
    8 n. ~* j9 g  j
  7. load_flags:一个用于控制字形加载选项的标志位。您可以使用这些标志位来控制加载的方式,例如是否要加载字形的轮廓数据、是否要加载字形的位图数据等。
    # D1 L9 m4 a+ ^$ S- F, M1 d
  8. 功能:  r6 E$ X* m( H7 b) g+ g  w
  9. . W% S. g4 Y; [+ D2 E/ m
  10. FT_Load_Char 函数的主要功能是加载指定字符的字形数据。+ k' b( K4 Q: y0 X& p4 X
  11. 如果成功,它将在 FT_Face 结构体中的 glyph 字段中填充有关字符的字形信息。# d: Y/ F9 k5 i  K4 u$ J
  12. 这包括了字符的轮廓数据、位图数据、宽度、高度、位图偏移等等,具体取决于传递给 load_flags 参数的设置。4 y: {4 w9 ^3 k* I. ]; `
  13. 使用示例:
    : k9 b) V0 ]2 z5 e4 v' z

  14. ' }1 l; P2 Y# d& H4 f" e" `
  15. c2 b7 m1 E3 e( P* X" v
  16. Copy code" \, K& p, b+ `. X; V. g8 Q
  17. FT_Load_Char(face, 'A', FT_LOAD_RENDER);
    , r! c& L4 c$ x  p
  18. 这个示例会加载字体中字符 'A' 的字形数据,并将其渲染到位图中。FT_LOAD_RENDER 标志告诉FreeType要渲染字符的位图数据。加载后,您可以在 face->glyph 结构体中找到有关 'A' 字符的相关信息,包括位图数据、宽度、高度、位图偏移等等。& T/ ]$ d4 W+ K
  19. 8 F1 Y; K/ c# D% Z9 b: r
  20. 错误处理:" x, d$ ]8 q+ P% i3 q/ C: t

  21. 3 e4 [( c8 r2 ~( j& M
  22. 如果加载失败,FT_Load_Char 函数可以返回错误代码。您应该检查返回值以进行错误处理,并根据需要采取适当的措施,例如跳过加载失败的字符或终止渲染过程。
    8 _4 c  o7 H4 v, x" c
  23. 总之,FT_Load_Char 函数是FreeType库中用于加载指定字符的字形数据的重要功能之一,它使您能够准备要渲染的字符数据,以便在文本渲染中使用。加载的数据可以包括字符的轮廓信息(矢量数据)和位图信息,具体取决于 load_flags 参数的设置。这个函数在字体渲染中起到关键作用,以便将字符正确呈现在屏幕上。
复制代码
8 O( i5 r" K; {. ~9 O  T

- d! j8 \+ Z% ~( e7 Y5 X7 O代码" w! P  X; h: _, x" a8 J6 X# O: Q

% C: m9 D1 r* y
  1. 4 _  B' [' u" p5 L& T# t

  2. 4 Z0 B2 {9 C' @1 Q) B; G( l& N
  3. 3 f+ v) `5 G1 B  i
  4. #include <stdio.h>
    ( ?$ p9 R% [5 i! C; O" q  [- D
  5. #include <stdlib.h>4 O& L( V# C: a- s
  6. #include <GL/glew.h>
    ; |# Y/ A5 T3 c$ G
  7. #include <GLFW/glfw3.h>) I3 N" P* ]3 l$ k: y
  8. #include <ft2build.h>  A/ B* ]6 H8 l% S7 D
  9. #include FT_FREETYPE_H
    + o/ |/ M7 M4 r3 |" U4 o
  10. * s& f  [5 N6 _" B0 s+ @4 E$ o
  11. // 定义字形数据的字节数组0 b9 e8 T' A& |
  12. unsigned char fontData[] = {  [3 L9 U+ A2 L' f
  13.     // 字形数据的字节表示
    5 `6 h4 c' \' b7 |& r
  14.     // 例如,这里可以包含字母、数字和符号的字形数据3 g+ v' J: t# B, a6 l& R& l
  15. };# v: T( |* v+ C: Q* J7 G8 {7 }% J& U& \

  16. 6 Z) e$ W* U2 b6 x) |. L
  17. FT_Library library;
    ' i  j8 I$ j$ [( V" W
  18. FT_Face face;
    5 d! n4 s- ?1 o9 v% t, R
  19. GLuint fontTexture;0 k9 K7 D0 v+ a9 F

  20. : J! P2 o3 p5 I9 Y+ O
  21. // 初始化FreeType库和OpenGL
    ; ^+ B6 q' d5 M; `
  22. void initialize() {
    0 P& c- ?) h) I! O* b3 o
  23.     if (FT_Init_FreeType(&library)) {: Q) F; `  h0 @! w2 G
  24.         fprintf(stderr, "Failed to initialize FreeType\n");* P9 d6 b' g; o" d4 W
  25.         exit(EXIT_FAILURE);
    2 h, b* a4 h  e  |. b! V7 w
  26.     }) k+ P" N, y. n+ Y
  27. ( R0 `2 B5 W7 c
  28.     if (FT_New_Memory_Face(library, fontData, sizeof(fontData), 0, &face)) {
    5 r& x) s, D8 j4 [% k
  29.         fprintf(stderr, "Failed to create a FreeType font face\n");
    ) L; J/ m- m  g
  30.         exit(EXIT_FAILURE);  h8 I  @! l; V
  31.     }
      @0 Q* [. Q" E: Z
  32. & B! U% k& ]' Z6 Y
  33.     if (FT_Set_Pixel_Sizes(face, 0, 48)) { // 设置字体大小
    $ S. a6 Y% a( K
  34.         fprintf(stderr, "Failed to set font size\n");
    ! t, H+ N( H" C2 a  j( H
  35.         exit(EXIT_FAILURE);
    # ?: }( V( |# M% x( d$ P; a- }7 m
  36.     }
      e3 L& a$ r0 x, D" b
  37. 4 w) K) d" M5 k2 m! G( _9 l8 @& l: e
  38.     glGenTextures(1, &fontTexture);
    9 L2 C; }4 a5 x  w$ `) q0 t
  39.     glBindTexture(GL_TEXTURE_2D, fontTexture);
    3 B* `4 h# `2 F2 R5 P' V+ n/ N
  40.     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    % M, y5 _; ?: B2 F
  41. / F: R8 _& f4 {0 u
  42.     // 将字形数据传递给OpenGL纹理
    ) Q4 w6 x! W$ P5 H& b6 d
  43.     for (int i = 0; i < 128; i++) {! K$ B4 J! k) b9 x, U% x: y5 M# O
  44.         if (FT_Load_Char(face, i, FT_LOAD_RENDER)) {
    - N4 S7 ?2 v3 B4 K
  45.             fprintf(stderr, "Failed to load glyph for character '%c'\n", i);' u; U* ?- n! X3 e: P. Z4 X  H  I$ w
  46.             continue;- [  @* W9 r  U
  47.         }
    " I0 B; b" Q# l: P

  48. * m* X. v) p/ B$ c, g, g
  49.         glTexImage2D(, q% X" g3 |7 l  u4 D
  50.             GL_TEXTURE_2D,- k1 B- X2 D/ s6 H+ U$ t
  51.             0,
    ( A# ]& ^; F: @( f
  52.             GL_RED,
    / G2 u! K( T$ P+ G2 i; }4 w
  53.             face->glyph->bitmap.width,
    - ~, V: d0 P. _. K6 o
  54.             face->glyph->bitmap.rows,
    : U2 q8 X" {+ x  A5 E
  55.             0,$ v) F* R6 t# M) W1 B& a
  56.             GL_RED,
    3 P) p& J  ]7 ]) \
  57.             GL_UNSIGNED_BYTE,
    3 o( ~0 \8 v/ ?! X& T
  58.             face->glyph->bitmap.buffer
    + U, f: a$ X* o
  59.         );
    * s. i; W1 V4 f" m3 m

  60. : J( M$ @; k2 l, E" Q
  61.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);0 H# t3 {: |( w4 T
  62.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    0 e: G  ~/ P8 r, `5 ^, D
  63.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);  y: l$ X0 ~- F  G6 Y
  64.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    2 W( t7 n$ H7 `4 r
  65.     }; u. i4 m2 P. g4 g
  66. }
    % I8 c' K) i# f% H* i

  67. # X3 C; |, O* P: W( K
  68. // 渲染字符串' }" C, s* x$ {! [6 v
  69. void renderString(const char* text, float x, float y) {
    ( @- s1 x: q3 _. h
  70.     glBindTexture(GL_TEXTURE_2D, fontTexture);: t. N9 Q: i2 M0 s

  71. ! b7 ~, D! V( c+ r, F/ R$ {
  72.     glEnable(GL_BLEND);
    - n- R' i4 ~7 ^* B
  73.     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    7 m$ I: q, B+ Y/ I

  74. 0 p+ H- F# S4 k7 ]8 T3 B& P2 a# c
  75.     glBegin(GL_QUADS);" k; w% f; g% q0 H  V
  76.     for (const char* p = text; *p; p++) {
    8 g" A+ N' N% F0 e
  77.         FT_Load_Char(face, *p, FT_LOAD_RENDER);
    5 q! w0 d( i) ^) N  m/ R7 m- F- N, A3 [
  78. 2 l  ~& o% s1 `- p2 V; V( E
  79.         glTexImage2D(( X, h. i% k' u1 B. E8 [7 c( w
  80.             GL_TEXTURE_2D,
    : k% h* l. }+ w8 n7 A: W8 I7 k
  81.             0,
    # k7 b; ]' @7 f
  82.             GL_RED,& N$ ?" r4 {" y9 b
  83.             face->glyph->bitmap.width,
    : g2 Z$ T- ], ^3 r2 `- C
  84.             face->glyph->bitmap.rows,' ]. T- ~1 d3 p2 i$ l0 N! x
  85.             0,
    # x9 ^4 ], P% X' s8 ~
  86.             GL_RED,# p: ^7 F: S1 |* M7 x0 f" F
  87.             GL_UNSIGNED_BYTE,
    ( F! w5 X0 f: [& `+ A! G. H/ s( K
  88.             face->glyph->bitmap.buffer! c! k0 g7 S5 I# O: l
  89.         );
    0 U/ N/ L- \/ j0 r  H8 P! s' V
  90. - A- m! P7 L- g$ a. Y& U1 K* S
  91.         float xpos = x + face->glyph->bitmap_left;
    2 A# ]  o6 U& t1 ~. ?+ \
  92.         float ypos = y - (face->glyph->bitmap.rows - face->glyph->bitmap_top);9 x. h+ B# z* z+ h, y1 i; e

  93. 6 i" }' h/ y7 b7 L7 q
  94.         float w = face->glyph->bitmap.width;4 u# V, f' d8 b( S
  95.         float h = face->glyph->bitmap.rows;, K( V$ Y- A9 O1 E! p' l
  96. & [3 W& h0 X/ S: S) v, i: M
  97.         glTexCoord2f(0, 0);7 k7 x: x7 e! J0 M8 I
  98.         glVertex2f(xpos, ypos);
    * ?9 v/ n7 n, Q3 S( Z( f

  99. , R8 q) k& P+ d
  100.         glTexCoord2f(0, 1);
    ( S3 J& F; m( b! u( M  _& W
  101.         glVertex2f(xpos, ypos + h);: U* y% ?- S& {5 q; F5 g

  102. 8 Z: {3 p$ ^* f5 V
  103.         glTexCoord2f(1, 1);
    ) H1 R, p& K( p" r
  104.         glVertex2f(xpos + w, ypos + h);
    + u  \! f1 T+ V- F
  105. : v1 K. p: g8 g
  106.         glTexCoord2f(1, 0);% ~5 j% N$ L* y5 Z4 U+ P' [1 B* l
  107.         glVertex2f(xpos + w, ypos);& h- N% A' Y8 H
  108. 5 {2 L* q6 @4 |& L$ P% ~
  109.         x += (face->glyph->advance.x >> 6); // 字符之间的间距/ \- {+ @  [# G" s  B+ z
  110.     }9 Y' A% U9 a8 e- C. ^7 j: U
  111.     glEnd();
    - r9 M$ u6 l# p) [' H* }8 c
  112. 7 Q( P9 I8 [% `2 c. a
  113.     glDisable(GL_BLEND);
    . v# O$ H) c5 M
  114. }
    6 p& T- X. _. A; F
  115. # m1 K! R& M" b
  116. int main() {
    , i8 X$ J  f$ O' f$ I
  117.     if (!glfwInit()) {
    ! |7 U& w2 K7 e  V5 k
  118.         fprintf(stderr, "Failed to initialize GLFW\n");
    ( h& }" h$ W3 `4 J6 ^
  119.         return -1;! H% J0 L8 d. i3 X! Z4 l
  120.     }
    1 w( t8 U: J; R+ ^2 c7 w4 e

  121. 1 b! g5 H* G# g, O* ^) D& B
  122.     GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL Text Rendering", NULL, NULL);
    ) E6 r- h1 J' e9 a2 S
  123.     if (!window) {1 M- X9 h7 g5 I& |! |4 T; v
  124.         fprintf(stderr, "Failed to create GLFW window\n");$ u( ]/ [5 T9 S5 f& Y  B: u
  125.         glfwTerminate();
    6 B/ ?% B' k4 V! @1 v2 ]! ?6 v
  126.         return -1;
    5 T2 B1 Q; e! a( s; n
  127.     }: o+ J' I- }/ G3 q' [$ d
  128. : d  I/ w" F. ]9 l% [8 d3 l
  129.     glfwMakeContextCurrent(window);
    ' P  {. D, y. l( }; A
  130.     glewInit();1 K  I! T$ B& M9 B, K4 c1 p! q

  131. . `' ]% y7 e5 Y# p  h& N
  132.     initialize();
      V0 o8 @$ x$ p9 c0 M/ o
  133. 7 u; w. p4 U6 f# m
  134.     while (!glfwWindowShouldClose(window)) {% u) u/ a3 q3 j! r" Z5 F
  135.         glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    3 b1 J( B' y2 X1 G
  136.         glClear(GL_COLOR_BUFFER_BIT);' ^6 E; T" M2 z/ _

  137. , o+ ^5 V0 w# g2 X
  138.         glColor3f(1.0f, 1.0f, 1.0f);1 k9 A  u) N' j
  139.         renderString("Hello, OpenGL!", 100.0f, 100.0f);# \% ]2 B% C+ }. H7 D2 ~

  140. - r% m7 [6 w( F  M, \
  141.         glfwSwapBuffers(window);% @" s4 E& T( O2 [% s% i* \' j6 ~
  142.         glfwPollEvents();
    ; Y& U$ K3 M3 [. y; v1 m" f, b! H* s
  143.     }
    6 u0 n' s8 o* N4 ]

  144. 9 H9 R# c. L% @4 ~# w  q; O
  145.     FT_Done_Face(face);: T. q" ?% R" c; L& r& S; K
  146.     FT_Done_FreeType(library);
    : _7 {4 ?4 J& W. b  Q& T
  147. $ A. w1 t% a$ ], [) m9 K
  148.     glfwTerminate();9 i: f  u5 y' B8 Z3 G# \
  149. ; A! ^! G  i( W) {' W+ {
  150.     return 0;8 \# f+ ?8 f0 t' ], }8 M9 k
  151. }& h' ]6 }2 c; E) D% Y
复制代码
" `" r4 y+ F; C

' j9 h5 [  Z* ~% Q$ g5 l! e




欢迎光临 冒险解谜游戏中文网 ChinaAVG (https://chinaavg.com/) Powered by Discuz! X3.2