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

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

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

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

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

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

本帖最后由 shane007 于 2023-9-6 15:32 编辑
7 i5 ]- t* E( j9 k6 [. ^# c, h2 F1 o/ ]; D% F/ u: G
以下是一个用来做参照的opengl显示字符串的代码,使用了freetype库。* U/ O( R( Q- X; w! W2 i3 ^
本代码经过分析以及改写之后,将取代游戏原有的显示函数。
4 [. e; h. n+ S: t# R! m" w* e. m  ?2 a% v/ G/ ]! N
代码详细说明如下
" {$ e1 i# t2 D# M$ U2 J+ G
, e( O- T. K, m4 k' U
  1. 在上述 renderString 函数中,我们有以下关键部分的解释:
    . x8 m" \! M" A7 ^
  2. . L% [. m: R( I0 _9 B0 q: x
  3. glBindTexture(GL_TEXTURE_2D, fontTexture);:将字体纹理绑定到当前的OpenGL上下文。这是因为我们要使用 fontTexture 中存储的字形位图数据进行渲染。
    5 U+ E0 h' }+ \# P8 K

  4. 5 x5 I7 i2 s. \- ^
  5. glEnable(GL_BLEND); 和 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);:启用混合模式以处理字符的透明度。混合模式通过 glBlendFunc 设置,这里使用了常见的源和目标因子来实现源颜色与目标颜色的混合,从而实现透明效果。
    9 R' R" U4 O) u# r  w  Z
  6. # f2 e; o, ~$ L
  7. glBegin(GL_QUADS); 和 glEnd();:在这两个函数之间的代码用于指定字符的四边形顶点,以便在OpenGL上下文中绘制字符。
    7 x7 t) V1 x; f. s* i; Q

  8. ; e8 u# Q) ]! T: l6 r. M
  9. for (const char* p = text; *p; p++) { ... }:这个循环遍历传递给函数的字符串 text 中的每个字符,然后为每个字符执行以下操作:( c! x- V; e  G1 S4 @! P
  10. ; Z0 C1 i' l' ^4 q
  11. FT_Load_Char(face, *p, FT_LOAD_RENDER);:使用FreeType加载字符的字形数据,包括轮廓和位图信息。加载后,可以从 face->glyph 中访问该字符的字形数据。% i) A: d  Q- j0 ~3 E# ?9 P

  12. 1 R5 ^( q/ j, g( h3 u5 D" ?
  13. 计算字符在屏幕上的位置和大小,包括 xpos(x坐标)、ypos(y坐标)、w(宽度)和 h(高度)。
    # |; i; o+ X8 r$ K

  14. , a! f7 Q' ?" V/ Y' Y+ Q. _7 i0 |
  15. 使用 glTexCoord2f 和 glVertex2f 来指定字符的纹理坐标和顶点坐标,以创建一个四边形。这四边形将字形的位图数据绘制到屏幕上的指定位置。
    5 d4 d0 e) ~1 {) Y
  16. . S( t1 t+ M# I6 j
  17. x += (face->glyph->advance.x >> 6);:更新 x 坐标,以便将下一个字符紧密排列在当前字符的后面。face->glyph->advance.x 包含字符的横向位移信息,>> 6 是用来将其转换为像素单位的操作。( J) S" ^; a( A/ J; t* E

  18. & g* C3 [" I2 ?
  19. 最后,glDisable(GL_BLEND); 用于禁用混合模式,以免影响后续的绘制操作。
    $ t' ~2 i! p& O6 O

  20. : l# j0 i/ x' o+ V$ e. \3 G" q1 G
  21. 总之,renderString 函数的作用是将传递给它的字符串中的字符一个接一个地绘制到OpenGL上下文中,使用FreeType加载的字形数据和字体纹理来实现文本渲染效果。渲染过程涉及到字符的位置计算、纹理坐标的设置以及混合模式的启用和禁用,以确保字符在屏幕上正确显示。8 b& b4 X& ]2 H; Y
复制代码
9 }+ j( F% u& b

$ |' Z( f0 ]8 E( n% w; U5 `8 U
  1. 字形数据处理的关键函数之一。以下是 FT_Load_Char 函数的详细解释:1 n6 X& n4 t4 b  p; b9 O- Q: R( y' j2 }

  2. & r" J4 |1 @2 j' R; |. _3 ~& K
  3. 参数:
    1 n$ U$ V0 C0 J: _. W

  4. * I. _* V9 ^/ u+ x7 i4 Z' M
  5. face:一个指向已经打开的字体文件的 FT_Face 结构体的指针。FT_Face 包含了字体的各种信息,包括字形数据。' ]: x6 r( k- e/ t4 B/ D" p
  6. char_code:要加载的字符的Unicode编码值。您需要传递字符的Unicode编码作为此参数,以指定要加载的字符。
    ! I  \0 a# w7 H! K3 G5 P
  7. load_flags:一个用于控制字形加载选项的标志位。您可以使用这些标志位来控制加载的方式,例如是否要加载字形的轮廓数据、是否要加载字形的位图数据等。' r) C0 a$ M- S5 X$ x5 Q% v
  8. 功能:: [7 m2 L* J" H8 ~- h3 \
  9. 9 [$ A& |; v+ y, G4 I% j3 I
  10. FT_Load_Char 函数的主要功能是加载指定字符的字形数据。3 a7 p/ ]$ |! X. R
  11. 如果成功,它将在 FT_Face 结构体中的 glyph 字段中填充有关字符的字形信息。5 K+ B: v, @8 o- D' I1 B- e$ X
  12. 这包括了字符的轮廓数据、位图数据、宽度、高度、位图偏移等等,具体取决于传递给 load_flags 参数的设置。9 n; t  Z$ d1 M9 O
  13. 使用示例:
    7 L6 {, d3 n1 _9 V3 _

  14. / c5 P# T2 L0 e8 m+ H
  15. c+ V' t  q7 K) ?4 o. R
  16. Copy code1 W2 }+ D- j+ P; Q% R
  17. FT_Load_Char(face, 'A', FT_LOAD_RENDER);. r6 [- g% ^' I6 W  ]; |
  18. 这个示例会加载字体中字符 'A' 的字形数据,并将其渲染到位图中。FT_LOAD_RENDER 标志告诉FreeType要渲染字符的位图数据。加载后,您可以在 face->glyph 结构体中找到有关 'A' 字符的相关信息,包括位图数据、宽度、高度、位图偏移等等。0 I, N, S0 F, a* ?0 ~+ B
  19. : _1 E4 W4 [' T3 L
  20. 错误处理:7 J! K* P4 P4 Y  Z

  21. 1 S9 s' e% k% J& P+ B4 r
  22. 如果加载失败,FT_Load_Char 函数可以返回错误代码。您应该检查返回值以进行错误处理,并根据需要采取适当的措施,例如跳过加载失败的字符或终止渲染过程。
    2 L: U# K1 T; l6 i3 i3 R
  23. 总之,FT_Load_Char 函数是FreeType库中用于加载指定字符的字形数据的重要功能之一,它使您能够准备要渲染的字符数据,以便在文本渲染中使用。加载的数据可以包括字符的轮廓信息(矢量数据)和位图信息,具体取决于 load_flags 参数的设置。这个函数在字体渲染中起到关键作用,以便将字符正确呈现在屏幕上。
复制代码
5 E& D$ A+ V9 ^) N
% }* F/ n6 P) ^$ J# J
代码4 D- o; c( \0 B( {

# B, S; v6 S  D% u/ r( x2 a

  1. : V1 i/ D7 ~, s, d8 V: L+ d  \

  2. - W6 J9 K- E, s
  3. 9 S  R8 u! }, }
  4. #include <stdio.h>
    + {, G% z1 K0 q/ j+ u; z4 y
  5. #include <stdlib.h>
    # b2 h$ }0 ~* v" j1 v! D
  6. #include <GL/glew.h>
    ! `8 C! t! p8 H. j; N
  7. #include <GLFW/glfw3.h>+ H* \# |4 E  m0 a, j% N
  8. #include <ft2build.h>
    + P: ?6 a/ C5 a4 Z0 K
  9. #include FT_FREETYPE_H
    8 _& v) m  u/ H7 Y9 b4 V$ @( {7 P

  10. 6 v  j2 u" F" p1 F3 e
  11. // 定义字形数据的字节数组- q  N: s' ~. d& |
  12. unsigned char fontData[] = {
    ' @8 H) c* i8 L5 q# H. d6 p' E
  13.     // 字形数据的字节表示; _: R# L2 u/ }; ]6 k2 T1 ^# O
  14.     // 例如,这里可以包含字母、数字和符号的字形数据; u0 q& `! ^, F8 ?. c$ I) y4 Z
  15. };8 ~+ Q5 }, J' z# Z+ e/ C

  16. % H  w3 |' H- \5 b1 d
  17. FT_Library library;; V4 R6 E% i* E: p0 ]$ t# n: G3 `
  18. FT_Face face;6 X4 _# `$ X8 e1 Q5 b& ^( m5 o
  19. GLuint fontTexture;
    0 w$ o7 C; [- M1 \% @5 z
  20. , R$ D, n5 U+ U: \$ f: U/ \
  21. // 初始化FreeType库和OpenGL
    7 P/ C- t. I6 p+ o2 M: k5 |
  22. void initialize() {
    * S* R( S( F' J3 C; C# l0 z
  23.     if (FT_Init_FreeType(&library)) {
    ; a7 Q% z. Z0 n
  24.         fprintf(stderr, "Failed to initialize FreeType\n");: U$ `# _, u& q8 `3 B9 L$ G& G8 O
  25.         exit(EXIT_FAILURE);. o$ Z0 ]( m) h  M
  26.     }
    : b/ R. D5 H$ r6 K" Z

  27. 1 \; L& m6 B0 k
  28.     if (FT_New_Memory_Face(library, fontData, sizeof(fontData), 0, &face)) {
    " G3 z2 W) z: _/ o& _
  29.         fprintf(stderr, "Failed to create a FreeType font face\n");1 t$ ^; [+ L7 s& y/ Q5 L
  30.         exit(EXIT_FAILURE);
    . Z( d; o  N& o, @
  31.     }9 Z9 l  \$ A4 I7 T
  32. , X) w2 u8 h+ j0 S$ q
  33.     if (FT_Set_Pixel_Sizes(face, 0, 48)) { // 设置字体大小( P9 L$ L1 J+ a; f% h( K
  34.         fprintf(stderr, "Failed to set font size\n");
    5 _! O0 E7 V! \  W& f6 M3 z
  35.         exit(EXIT_FAILURE);
    ) x! e6 f5 @( b' @! k
  36.     }$ k) i, ], e! q/ P3 p/ H) [( }+ l! M
  37.   ~/ H& T! d1 e8 T5 U
  38.     glGenTextures(1, &fontTexture);
    ' f) `4 `4 f! Z4 I3 v$ B% M+ C
  39.     glBindTexture(GL_TEXTURE_2D, fontTexture);; C# m. m( C& q/ ?& T$ s& F
  40.     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    9 |! I( k: a/ p( s% a3 r
  41. ( K3 ]* D% S8 Q+ P! c* O* a
  42.     // 将字形数据传递给OpenGL纹理, S6 H; V% [1 ~
  43.     for (int i = 0; i < 128; i++) {/ D4 H  w0 S8 g+ ?! e9 O
  44.         if (FT_Load_Char(face, i, FT_LOAD_RENDER)) {6 O6 q2 p- S0 w* s
  45.             fprintf(stderr, "Failed to load glyph for character '%c'\n", i);
    : j5 W  A! `* D: @7 y" m
  46.             continue;9 K( v7 }5 O/ H  s, a+ y  ^
  47.         }8 T+ _* ?( h- \) }$ P
  48. ) w4 L7 q( h9 t/ O- G7 \. V
  49.         glTexImage2D(
    ! a/ Y" F1 G# W5 C, y( S( {5 }
  50.             GL_TEXTURE_2D,
    ; x4 t. C9 u: B- |* \
  51.             0,  }4 k0 s0 b9 W" i9 x& ^- k
  52.             GL_RED,
    ( Z3 o: R+ j& _0 u5 A# M( U$ G$ l
  53.             face->glyph->bitmap.width,; U! W, W  `4 B. y& q
  54.             face->glyph->bitmap.rows,, z3 W9 O6 P9 f( V4 e
  55.             0,1 \; G+ o2 u8 N% {
  56.             GL_RED,- w: L4 Q3 S  ?0 K
  57.             GL_UNSIGNED_BYTE,. |; h- N+ z* P$ k9 K/ a: {
  58.             face->glyph->bitmap.buffer
    0 ]1 j6 g" k( ^% c- B% W, {6 t
  59.         );" [1 k2 \3 n# U3 z
  60. ' ^( h$ B& b9 h4 ^
  61.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    0 R9 \) X- R" P1 B8 z; t8 o  G7 ?& ]& K
  62.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);7 T. k6 `- f0 }2 {4 h6 g- ^5 v5 C
  63.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);4 T3 E3 q& p: F: J
  64.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    2 D' Z% U- u- Q) c
  65.     }: l7 M  q/ h$ B$ g+ u5 J( F
  66. }; }0 n' S2 m, `# k8 u

  67. 6 N: s* J8 t0 J
  68. // 渲染字符串
    " P6 ~' {) A$ _8 w) v5 P6 I0 u) e3 G
  69. void renderString(const char* text, float x, float y) {% L9 ?5 {3 ~! p- D, A
  70.     glBindTexture(GL_TEXTURE_2D, fontTexture);
    , \- b8 m5 ]( y
  71. 0 |0 q# U7 M  a6 [3 W6 ?! z; R5 ^# B
  72.     glEnable(GL_BLEND);' E$ Q$ x) ]4 M7 H
  73.     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    * c: ]4 Z0 L: x2 ^& l

  74. * K% m% m  B! W! L* N3 Q2 a
  75.     glBegin(GL_QUADS);# P5 v' s  H. L5 \" c1 u! V
  76.     for (const char* p = text; *p; p++) {
    . c! H9 D( l) m: C; s; R8 P9 l
  77.         FT_Load_Char(face, *p, FT_LOAD_RENDER);2 a8 b7 g* |. |& M
  78. % H  L: |* \# {2 {* e! D# y. }
  79.         glTexImage2D(7 h" t- y0 q1 T8 \
  80.             GL_TEXTURE_2D,# G! P8 F) h0 z1 E! l
  81.             0,
    * t+ e% A( k" Y* k% b
  82.             GL_RED,
    $ o) h+ k$ \* Z! N  V: V
  83.             face->glyph->bitmap.width,
    . _" V! s* M9 R4 j" f+ R8 c
  84.             face->glyph->bitmap.rows,
    0 P6 X5 @1 k& |/ @6 L5 V
  85.             0,
    , M* [0 K* q  z; D, s4 |
  86.             GL_RED,! T: v" `6 O& u' C
  87.             GL_UNSIGNED_BYTE,
    0 N7 ]- U) @' E4 i  q  k# `
  88.             face->glyph->bitmap.buffer
    0 d( s3 Z7 k  A0 K8 `
  89.         );) C  B$ M' C. K4 @- x4 @
  90. 0 U; V% A" [3 {4 p: z' {
  91.         float xpos = x + face->glyph->bitmap_left;
    / K3 i# U/ V- c( `( E
  92.         float ypos = y - (face->glyph->bitmap.rows - face->glyph->bitmap_top);9 j! m2 o1 F. j- g1 z

  93. ! I% {. j, X! N
  94.         float w = face->glyph->bitmap.width;
    ) `/ ~5 z, Y$ f
  95.         float h = face->glyph->bitmap.rows;
    $ N7 z+ T6 i+ O1 \) V

  96. & t1 ?5 ~0 Y3 i* |( k' t$ z: j9 V
  97.         glTexCoord2f(0, 0);4 {+ X6 j8 Q- K% R
  98.         glVertex2f(xpos, ypos);" y8 x1 r- }; g; D' Z8 a

  99. 0 F4 R2 m1 @2 V/ d8 L
  100.         glTexCoord2f(0, 1);
    ' L& A$ e/ N" E& Y2 A0 ^# j6 F
  101.         glVertex2f(xpos, ypos + h);$ b. C6 v: H: A. a; U8 @0 H$ h
  102. - X, L  D, n4 A" U
  103.         glTexCoord2f(1, 1);; w# y+ {( _& i+ J7 O3 D% h
  104.         glVertex2f(xpos + w, ypos + h);; ^) S+ L+ y' B' v  G
  105. # Y, T. g5 c' f- O' u
  106.         glTexCoord2f(1, 0);& v3 r7 l6 A4 y" i' {
  107.         glVertex2f(xpos + w, ypos);; ]7 v5 `1 G; W8 O. _4 f1 `3 t+ n
  108. & n# q7 }9 R# T/ W$ \3 n/ N4 K
  109.         x += (face->glyph->advance.x >> 6); // 字符之间的间距
    2 M( M! {6 M% o/ p) P: e1 z; `
  110.     }8 Y8 M3 Z( K: W0 }" |* k7 C2 }
  111.     glEnd();8 Q, t, h# j: f& h) b' A# H
  112. % x, P% K( w/ C8 w9 s7 M
  113.     glDisable(GL_BLEND);' E: o) ]' o! j4 J0 A
  114. }
    " t0 B, e# F; Y8 L, ^5 I

  115. ; n, `( h/ _% y- `) I
  116. int main() {
    6 e9 j% M& a% M: {5 Q( C& t/ X
  117.     if (!glfwInit()) {) e+ f( s7 O  K) q: i7 |* d
  118.         fprintf(stderr, "Failed to initialize GLFW\n");
    1 Q- P, B: y+ i$ @$ e& X% ~
  119.         return -1;, x) @0 c0 D4 @! M  ^2 {# R- D+ I
  120.     }
    ' {: ]* f; C0 c
  121. , u" K& g& M! p! M# O* [0 \6 F
  122.     GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL Text Rendering", NULL, NULL);
    * T3 U1 B3 K, T- d7 `
  123.     if (!window) {
    * Q8 T9 Q  p0 t8 N1 z: G& \
  124.         fprintf(stderr, "Failed to create GLFW window\n");- _% y& }1 R+ ~* V2 q$ D; l
  125.         glfwTerminate();, e  q+ p1 f' H5 X. b
  126.         return -1;
    / s+ c& R5 g8 f3 h0 D. i
  127.     }
    : L1 `) {- |, `- ]$ c2 Q, b1 S

  128. 4 J  k) G/ m, |# x$ c9 Z( y8 Y( O0 _
  129.     glfwMakeContextCurrent(window);' ^8 [$ `& Q5 }! I9 N, R$ a
  130.     glewInit();
    $ w9 S  E3 H2 t, t( K. C( I3 @& q

  131. " i4 ~4 J1 W, J0 y+ c7 C
  132.     initialize();0 ~3 L0 b0 I, V/ ^. k+ C% C9 F

  133. 5 c: k7 \5 g( l6 Q* X& Y! h
  134.     while (!glfwWindowShouldClose(window)) {/ Z( v2 M4 s) H' o$ }- q/ }
  135.         glClearColor(0.0f, 0.0f, 0.0f, 1.0f);% x5 Q4 \; o$ w( @6 Y
  136.         glClear(GL_COLOR_BUFFER_BIT);
    3 |9 K5 F. X: I7 M% `
  137. ) D8 h& V/ i, a4 T$ H% ?& U' ~, m0 i' B
  138.         glColor3f(1.0f, 1.0f, 1.0f);
    " Q& b6 H. [4 F! a8 K2 g- @
  139.         renderString("Hello, OpenGL!", 100.0f, 100.0f);+ _! H2 x- X4 g- E: n* ?8 B& k

  140. & m% a; G- [+ Z. q0 _' `
  141.         glfwSwapBuffers(window);
    0 y3 Y/ l5 y+ X+ E7 T5 M  E4 \. D! F
  142.         glfwPollEvents();9 l& N! m; y1 j6 u! ~5 e
  143.     }
    - {7 {$ f9 g9 T3 ?1 z! Z! B( j

  144. ' B  m3 `! d% H* H; W- {3 \
  145.     FT_Done_Face(face);2 n* l0 A( G! _* k
  146.     FT_Done_FreeType(library);3 L! [/ O! P$ e4 A$ m- [

  147.   ~# F2 g: b4 S5 ^
  148.     glfwTerminate();
    & ]( \8 R. g2 S: W* J/ R
  149.   R, w/ R0 T2 G1 ]; K) U
  150.     return 0;0 Z) i* ]& ]3 H3 ~5 C. {
  151. }
    + D2 _/ y  E  A
复制代码
  ~8 Z8 d- I2 ~) R; F+ }

8 i5 H$ ^. ?9 J$ K( j
分享到:  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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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