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

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

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

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

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

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

本帖最后由 shane007 于 2023-9-6 15:32 编辑
/ \& V0 U/ Y+ h% L. `, ~8 |$ d8 t& I( I6 R
以下是一个用来做参照的opengl显示字符串的代码,使用了freetype库。
; ?( g" s$ ]# i9 ]2 g' g5 v. s本代码经过分析以及改写之后,将取代游戏原有的显示函数。
4 P% H/ @# |$ |( K3 A- R, ~' K8 H, M
代码详细说明如下
& u+ j* X2 S0 U; [0 X- {/ O# K. Q  @6 }4 ?9 n; @& k
  1. 在上述 renderString 函数中,我们有以下关键部分的解释:, t  s0 }5 I: |7 e; {! Q

  2. ; C; y2 k. C: L, y0 q+ v
  3. glBindTexture(GL_TEXTURE_2D, fontTexture);:将字体纹理绑定到当前的OpenGL上下文。这是因为我们要使用 fontTexture 中存储的字形位图数据进行渲染。3 e" o: I; [! G/ @4 F- }

  4. $ r: G* f3 ~. b* }) `% O; u$ Q* T/ y
  5. glEnable(GL_BLEND); 和 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);:启用混合模式以处理字符的透明度。混合模式通过 glBlendFunc 设置,这里使用了常见的源和目标因子来实现源颜色与目标颜色的混合,从而实现透明效果。2 U" U, F0 u2 l+ w" {: P

  6. ! t) T$ K; P; K$ D
  7. glBegin(GL_QUADS); 和 glEnd();:在这两个函数之间的代码用于指定字符的四边形顶点,以便在OpenGL上下文中绘制字符。
      U5 Q& m- l4 ?! a

  8. 5 Y6 L  a7 K$ [
  9. for (const char* p = text; *p; p++) { ... }:这个循环遍历传递给函数的字符串 text 中的每个字符,然后为每个字符执行以下操作:* R! B  p$ h6 ~( J$ y$ Y  d2 l

  10. ( H. @  [1 ]- Z7 ]
  11. FT_Load_Char(face, *p, FT_LOAD_RENDER);:使用FreeType加载字符的字形数据,包括轮廓和位图信息。加载后,可以从 face->glyph 中访问该字符的字形数据。
    ' w) E2 N0 f; X& I( Z4 T4 k7 }

  12. $ J# J. _$ l$ i9 w# ~9 {
  13. 计算字符在屏幕上的位置和大小,包括 xpos(x坐标)、ypos(y坐标)、w(宽度)和 h(高度)。% w3 k& B( v( Q+ ]4 i% v) b% a4 q

  14. 0 b+ _. l4 L" D% p9 u
  15. 使用 glTexCoord2f 和 glVertex2f 来指定字符的纹理坐标和顶点坐标,以创建一个四边形。这四边形将字形的位图数据绘制到屏幕上的指定位置。; M- [$ ~: n: T: X# c5 o* _4 x

  16. ) B5 Z! P7 f) b8 D
  17. x += (face->glyph->advance.x >> 6);:更新 x 坐标,以便将下一个字符紧密排列在当前字符的后面。face->glyph->advance.x 包含字符的横向位移信息,>> 6 是用来将其转换为像素单位的操作。$ W4 ?9 q* n; D: h
  18. 4 Q2 Q$ V# W: D! |7 i7 P
  19. 最后,glDisable(GL_BLEND); 用于禁用混合模式,以免影响后续的绘制操作。
    . e5 y( K% P3 u4 n' g( k

  20. # u6 m4 j8 [' {3 k/ e: g0 ~7 M0 F
  21. 总之,renderString 函数的作用是将传递给它的字符串中的字符一个接一个地绘制到OpenGL上下文中,使用FreeType加载的字形数据和字体纹理来实现文本渲染效果。渲染过程涉及到字符的位置计算、纹理坐标的设置以及混合模式的启用和禁用,以确保字符在屏幕上正确显示。
    % Y' |* d5 `% S$ z, L, Z# {3 w/ \
复制代码

$ T/ l8 v5 R" I* O0 j; T- ?5 ~3 x0 L: B- L4 l; P3 f
  1. 字形数据处理的关键函数之一。以下是 FT_Load_Char 函数的详细解释:
    ' o, y9 K5 V0 J/ m  P6 f( }

  2. - A# H9 f/ z  b, m5 Z0 X0 q8 X
  3. 参数:+ i: a/ S4 D" b' W' R
  4. & _+ `% K/ Y3 Z
  5. face:一个指向已经打开的字体文件的 FT_Face 结构体的指针。FT_Face 包含了字体的各种信息,包括字形数据。8 E' V8 \  K; c( T$ q  w
  6. char_code:要加载的字符的Unicode编码值。您需要传递字符的Unicode编码作为此参数,以指定要加载的字符。
    0 E: g2 ]6 p2 U' b. ~( f, ]; X: G! m
  7. load_flags:一个用于控制字形加载选项的标志位。您可以使用这些标志位来控制加载的方式,例如是否要加载字形的轮廓数据、是否要加载字形的位图数据等。% S" [: m+ o, g8 Q% f
  8. 功能:
    ; R! I2 J. F1 l$ b2 o/ r2 f+ K

  9. 3 S+ U3 {& W/ u# ^; [2 w% C3 J
  10. FT_Load_Char 函数的主要功能是加载指定字符的字形数据。
    & X$ a# H! w. ?* j3 J! |
  11. 如果成功,它将在 FT_Face 结构体中的 glyph 字段中填充有关字符的字形信息。. \: W) Q9 T. I! w% {( c7 x
  12. 这包括了字符的轮廓数据、位图数据、宽度、高度、位图偏移等等,具体取决于传递给 load_flags 参数的设置。: v, v2 i2 e3 J2 s% u2 P7 o) F
  13. 使用示例:
    : t6 t7 u/ I% n
  14. - u  D3 o( L7 M! q
  15. c
    . Y+ D0 V/ C. t
  16. Copy code" b+ x+ S; m+ p1 |: D0 v" B# b
  17. FT_Load_Char(face, 'A', FT_LOAD_RENDER);& y' w1 u3 |0 `/ [
  18. 这个示例会加载字体中字符 'A' 的字形数据,并将其渲染到位图中。FT_LOAD_RENDER 标志告诉FreeType要渲染字符的位图数据。加载后,您可以在 face->glyph 结构体中找到有关 'A' 字符的相关信息,包括位图数据、宽度、高度、位图偏移等等。
    / I6 B& m6 q% H, _! ^+ H" \

  19. 9 f- C5 k; L  l. v1 ~- V  q
  20. 错误处理:  ~' f) a" R; J7 ?

  21.   Q" I" P* x; ^; X; n# c
  22. 如果加载失败,FT_Load_Char 函数可以返回错误代码。您应该检查返回值以进行错误处理,并根据需要采取适当的措施,例如跳过加载失败的字符或终止渲染过程。, }: \) t" i7 s& ~% ~
  23. 总之,FT_Load_Char 函数是FreeType库中用于加载指定字符的字形数据的重要功能之一,它使您能够准备要渲染的字符数据,以便在文本渲染中使用。加载的数据可以包括字符的轮廓信息(矢量数据)和位图信息,具体取决于 load_flags 参数的设置。这个函数在字体渲染中起到关键作用,以便将字符正确呈现在屏幕上。
复制代码

3 g( B/ W2 I3 S8 x' [% H- [& C6 p8 I1 K# J9 X7 Q- J! x1 [
代码
" O; _" h4 l+ p1 d# @! {* s5 x1 O$ n
  1. , q7 O. \* r6 F6 [' n- z

  2. : {- {% Q+ C  f. Q8 g( B

  3.   Y* U% |$ R, T0 f
  4. #include <stdio.h>
    % @4 |0 h$ u  \, a
  5. #include <stdlib.h>
    1 D5 `" {' h# `
  6. #include <GL/glew.h>
    ) |; C; O% s1 V. U/ u
  7. #include <GLFW/glfw3.h>1 L, z  p" r( }& g- ?, v& _
  8. #include <ft2build.h>
    3 K! c# y  D! e) W7 r, ^& U
  9. #include FT_FREETYPE_H
    8 h! K, k: e' k+ k

  10. ! D6 i% m7 N4 r9 `
  11. // 定义字形数据的字节数组, n1 K2 \2 ~5 A# R$ F
  12. unsigned char fontData[] = {
    ! G  L7 c& E0 J8 S/ S0 q
  13.     // 字形数据的字节表示, D/ h# p' l$ Q0 H  D( d: N7 A2 {5 r* ~
  14.     // 例如,这里可以包含字母、数字和符号的字形数据
    0 m5 s7 M( E3 A) q  B' R
  15. };0 @: i, b* K5 t+ {
  16. 0 e+ P6 Y; |" W7 Y8 a' k* u
  17. FT_Library library;
    5 T( d4 d5 S, |7 p
  18. FT_Face face;9 x% g( h7 S& b* n) n/ _
  19. GLuint fontTexture;' U" T; z( d! v: ]! H" b
  20. & E& F8 [% j* E* ?2 f# d. `
  21. // 初始化FreeType库和OpenGL
    % _, s( W' v- m7 R$ V5 x
  22. void initialize() {; O2 ]+ W- B0 k! R" \
  23.     if (FT_Init_FreeType(&library)) {
    + Z, r" j' q. U3 M/ N( g
  24.         fprintf(stderr, "Failed to initialize FreeType\n");
    4 X) F6 d) V2 L8 m! E6 @
  25.         exit(EXIT_FAILURE);
    3 k: J0 b/ c! {0 [* Y
  26.     }
    4 @% T6 s: `$ q& y
  27.   p1 V% C4 O9 S
  28.     if (FT_New_Memory_Face(library, fontData, sizeof(fontData), 0, &face)) {
    * x# y2 D+ |* H
  29.         fprintf(stderr, "Failed to create a FreeType font face\n");4 |1 c5 o. H) p' n5 k
  30.         exit(EXIT_FAILURE);# b5 S! t* Y6 g5 a* Q
  31.     }
    9 y$ m' W6 _, r9 G* }" T! m) O: c
  32. ( ]3 U$ ~! o1 w- ~7 r1 {7 _, D
  33.     if (FT_Set_Pixel_Sizes(face, 0, 48)) { // 设置字体大小
    & c$ b8 e; w! N2 P
  34.         fprintf(stderr, "Failed to set font size\n");  i# v+ z8 `6 m/ z& E  j# W
  35.         exit(EXIT_FAILURE);
    6 O  J/ R9 k' q: _1 }; X8 N
  36.     }; t0 }6 }* W1 J. u$ h  F

  37. 7 L; B) C& b* N2 }8 i7 {
  38.     glGenTextures(1, &fontTexture);
    ! d! b' w' X" L) j0 r
  39.     glBindTexture(GL_TEXTURE_2D, fontTexture);- w! t5 _- t" ?( {
  40.     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    # \0 _/ F4 g1 H, T7 P; i7 o( ]

  41. / Q! A) S2 z$ Z
  42.     // 将字形数据传递给OpenGL纹理
    . i3 H/ D8 P7 g/ b+ \
  43.     for (int i = 0; i < 128; i++) {  k# K3 h3 J( E( x6 D
  44.         if (FT_Load_Char(face, i, FT_LOAD_RENDER)) {3 d" K6 H0 i! |, _  X& }% \2 ]
  45.             fprintf(stderr, "Failed to load glyph for character '%c'\n", i);! I: Z8 F4 r: W8 u$ Q
  46.             continue;
    * R% ?* B& F) [4 I
  47.         }2 d' ~% n8 e1 I+ l/ I$ p4 ~8 c* x
  48. + [* Q* I0 }0 V% T$ B
  49.         glTexImage2D($ j' ~$ h+ O; k
  50.             GL_TEXTURE_2D,% a. p8 O. }( a- i8 ?+ l
  51.             0,
    * @% W) S& v, s$ m* t, n+ x; E
  52.             GL_RED,5 d7 T3 K3 m5 w( S
  53.             face->glyph->bitmap.width,
    . L0 q% ~0 Y+ f2 q9 h7 D
  54.             face->glyph->bitmap.rows,
    : b9 j7 W% W% f/ j' Y
  55.             0,6 h. F$ E. Q& j  X, X. `% M
  56.             GL_RED,
    9 A7 d# j. q7 Y$ v/ A0 h
  57.             GL_UNSIGNED_BYTE,; \) p2 b. P1 \( U. h& f
  58.             face->glyph->bitmap.buffer, l$ B$ F; m+ `: v& X6 ~$ ?
  59.         );
    0 B1 R8 X$ `' x; C; u

  60.   t' i$ C  I5 N7 N, \5 X
  61.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);& C4 r  K$ H+ _, a( T3 e) H
  62.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    & @! m' m3 V3 i2 p5 y
  63.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    * y/ w& @7 a" X- h, J9 |
  64.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);: v6 i- ?' |  G2 _3 o/ ^# S* X* g
  65.     }
    : i2 q* i: ]; W- n  p7 I
  66. }
    + }( z6 N, o0 C* u3 p0 ?  ]& W
  67. $ M. n2 E& z/ g- Y! p# h
  68. // 渲染字符串' z# x5 B, ^% f9 i; ]- z4 f
  69. void renderString(const char* text, float x, float y) {
      d& P9 o8 F% o0 o) P0 l; z
  70.     glBindTexture(GL_TEXTURE_2D, fontTexture);! C; e2 q$ r9 g0 [: m

  71. 8 a! e3 a% z4 C5 I
  72.     glEnable(GL_BLEND);6 z" |. b+ \1 D! H
  73.     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    & c# V) S7 E: ~- R! w: k3 T7 f

  74.   E; {' Z: F- n# d; w
  75.     glBegin(GL_QUADS);
    3 I- A# k8 L0 w; F+ p" d0 ]
  76.     for (const char* p = text; *p; p++) {: O" }+ `; r9 T- i: F! L/ }
  77.         FT_Load_Char(face, *p, FT_LOAD_RENDER);  r- \9 M4 z8 V+ d( h

  78. & T! A4 `0 R- S$ X% U7 o
  79.         glTexImage2D(
    : ?9 T/ E8 M1 l7 K
  80.             GL_TEXTURE_2D,
    7 g0 {# L3 e1 w& r( `/ E9 P
  81.             0,- O2 P6 `2 ~* e, Q: q8 ]1 f& k
  82.             GL_RED,
    % H. T) u, q5 t0 h& w3 z* C' Y) h
  83.             face->glyph->bitmap.width,
    3 e1 o# X2 n" c/ e
  84.             face->glyph->bitmap.rows,
    , Y: X7 B, q% i7 d
  85.             0,
    & c& _7 a- N2 P2 J. w! S
  86.             GL_RED,2 K0 @. i0 w) Q) v! Q
  87.             GL_UNSIGNED_BYTE,; D& U! W5 z# Z5 }2 A
  88.             face->glyph->bitmap.buffer
    % \( A6 g+ t  b- J6 c" l5 c
  89.         );
    3 S* S! i% q3 i( a( U6 ~

  90. - J9 w: O( G( T  L) k/ m+ I- G
  91.         float xpos = x + face->glyph->bitmap_left;# O  p0 n& o' |) x  Q0 E
  92.         float ypos = y - (face->glyph->bitmap.rows - face->glyph->bitmap_top);0 E/ l! r. N$ C6 F9 J
  93. / U" v6 Z9 w0 D
  94.         float w = face->glyph->bitmap.width;
    3 O7 |9 N- K3 `8 t0 E  t# j
  95.         float h = face->glyph->bitmap.rows;( m# @  ?2 J- M" ^! z

  96. ; G: ]+ {0 x, [7 m- ^" Y
  97.         glTexCoord2f(0, 0);3 K# k% z+ k) I1 m. l. i
  98.         glVertex2f(xpos, ypos);' n' i) Q) c: |7 P5 z0 R; E
  99. + n( U9 b0 O% F# P4 @  m/ p3 d
  100.         glTexCoord2f(0, 1);* v+ |8 W$ c. q9 V" X
  101.         glVertex2f(xpos, ypos + h);( Z! }& @  S( B7 |0 `* Y" R) u

  102. - e! W5 R2 A3 {: f$ P* u) e
  103.         glTexCoord2f(1, 1);% A% k2 [+ Q, {2 J6 [* y( c
  104.         glVertex2f(xpos + w, ypos + h);/ w& ]8 o4 F: t
  105. 9 _, @# E2 K: g3 O, K
  106.         glTexCoord2f(1, 0);
    0 G$ N  o! `9 V1 L3 }
  107.         glVertex2f(xpos + w, ypos);
    + ~1 m9 h) f8 c* d

  108. # v& p  G0 n" s$ l8 V' h+ A' S( k
  109.         x += (face->glyph->advance.x >> 6); // 字符之间的间距
    2 \! u* t9 V9 p  V# S
  110.     }- j# ~, U" _/ d4 U
  111.     glEnd();3 k3 [, s1 m$ h* f0 p% n& h) W
  112. 1 L3 G5 ~* m% `" Q8 d
  113.     glDisable(GL_BLEND);8 I- c+ Z9 i7 e, ]
  114. }: z+ f1 g% H  M5 p0 t) y
  115. % @/ E: n2 K  N, u2 A1 _
  116. int main() {
    ' r" z; i& C1 L. O  h! K/ `  k
  117.     if (!glfwInit()) {
    6 E& n  \+ K& q' F# Z+ x
  118.         fprintf(stderr, "Failed to initialize GLFW\n");
    . }# M" t$ W% [2 o& {; G+ K/ U
  119.         return -1;" T' H/ P9 z+ q
  120.     }% X; y3 l- ?4 O8 r. h, s9 T

  121. * [& R5 E( |$ }0 l
  122.     GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL Text Rendering", NULL, NULL);' V7 K$ H0 o! ~- J* a, B4 E) z
  123.     if (!window) {, f! X- l9 m0 v4 X
  124.         fprintf(stderr, "Failed to create GLFW window\n");3 R# |" p! N: g! X9 ?2 Z
  125.         glfwTerminate();
    0 C* k0 \1 H- Z* E# d2 V; K  @
  126.         return -1;* p6 d5 T) ~, ?' F( C7 ~; Y3 {8 g2 }
  127.     }. F0 W$ t: n6 \/ I; Z: u

  128. 7 I) Y7 R, z  ~2 k# m1 I5 T
  129.     glfwMakeContextCurrent(window);
    ; D/ E5 i: n' _9 S; E2 ^
  130.     glewInit();; d) P' U; y2 n: D; f/ T
  131. ; S8 t; `  o% r4 x
  132.     initialize();  V8 [8 ?6 k  n. ?4 q
  133. $ V& b1 v: K+ q0 P8 r# G2 u; O4 v
  134.     while (!glfwWindowShouldClose(window)) {
    ; k/ m3 F( L# N; q
  135.         glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    9 e8 u6 a8 D/ ?" i* I7 }
  136.         glClear(GL_COLOR_BUFFER_BIT);' r) J' f2 V0 Z# I# f' f

  137. ' i' R8 k; c% W0 |) U0 N! X; \* z! w
  138.         glColor3f(1.0f, 1.0f, 1.0f);
      E4 E( q4 N2 Q0 P& H5 u
  139.         renderString("Hello, OpenGL!", 100.0f, 100.0f);9 Q. a* r! g' }# j' F( ]+ l' w

  140. : S! p6 \/ ~: B) S
  141.         glfwSwapBuffers(window);
    , l. x. U0 ^  W* K& x  o3 A
  142.         glfwPollEvents();
    4 t1 A8 B2 e+ B9 {# X
  143.     }. T; X( J0 M; t  }" a

  144. + X( P& X+ g( w4 M
  145.     FT_Done_Face(face);7 f: h8 f- x# G9 W% X! F) Q
  146.     FT_Done_FreeType(library);' [+ E0 r; G2 @) E% J8 H) Z; x

  147. 4 \* T' K6 G8 n# ]; d/ ]
  148.     glfwTerminate();$ F& S8 y: I  H' Q: X1 ~
  149. 4 C/ Q% R) D6 Z( Z& q5 {, F( B
  150.     return 0;5 T' R: n+ U( |& `
  151. }
    : Q/ [1 z0 I* v4 J
复制代码

, Q. i! u) u8 U1 X& a6 Y. w
  D: X  s& v$ k% K3 i
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 很美好很美好1 很差劲很差劲
回复

使用道具 举报

沙发
发表于 2025-4-12 16:41 | 只看该作者
学习学习一下
回复 支持 反对

使用道具 举报

高级模式
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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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