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

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

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

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

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

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

本帖最后由 shane007 于 2023-9-6 15:32 编辑 # k, U* J( i/ j1 x, d% i; ^
, S/ P: ^. ?, F* V3 m
以下是一个用来做参照的opengl显示字符串的代码,使用了freetype库。
) L. j: Z/ r: ^# R. {本代码经过分析以及改写之后,将取代游戏原有的显示函数。% Q. @" d- a8 n! Y. Z

* K! I( C5 S: ?. M* _2 G代码详细说明如下
0 Q1 b  h( z8 g1 c$ a; l3 B  J* g& O: Z
4 s& J8 D; P3 W% W) T" |( q* L# S
  1. 在上述 renderString 函数中,我们有以下关键部分的解释:
    : M5 P8 @! `% f* }: R' V; p( e
  2. ( t  J" g( m+ ~+ t
  3. glBindTexture(GL_TEXTURE_2D, fontTexture);:将字体纹理绑定到当前的OpenGL上下文。这是因为我们要使用 fontTexture 中存储的字形位图数据进行渲染。
    . E5 j; k% V3 K: R) l8 j( u& q# Y

  4. , I& |, K3 \- y1 p$ }# w+ N, K
  5. glEnable(GL_BLEND); 和 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);:启用混合模式以处理字符的透明度。混合模式通过 glBlendFunc 设置,这里使用了常见的源和目标因子来实现源颜色与目标颜色的混合,从而实现透明效果。4 i9 l. d- ~8 o* L

  6. 0 S9 O  [" C0 ^; a9 D+ U/ U: H
  7. glBegin(GL_QUADS); 和 glEnd();:在这两个函数之间的代码用于指定字符的四边形顶点,以便在OpenGL上下文中绘制字符。" Y, n3 k  X7 a1 S2 O; r& w
  8. 9 M! h3 Q- B+ C9 b; s" M
  9. for (const char* p = text; *p; p++) { ... }:这个循环遍历传递给函数的字符串 text 中的每个字符,然后为每个字符执行以下操作:
    : ?" p: n) P" j3 T; R
  10. - G: k5 R  i' m2 M$ Y8 `9 b
  11. FT_Load_Char(face, *p, FT_LOAD_RENDER);:使用FreeType加载字符的字形数据,包括轮廓和位图信息。加载后,可以从 face->glyph 中访问该字符的字形数据。2 R& d2 q9 c% P6 k- \2 _/ u( ~
  12. 8 l7 V, K0 S% i! f
  13. 计算字符在屏幕上的位置和大小,包括 xpos(x坐标)、ypos(y坐标)、w(宽度)和 h(高度)。4 R8 l! b1 G" b0 C
  14. & [1 i5 J9 J/ m) g
  15. 使用 glTexCoord2f 和 glVertex2f 来指定字符的纹理坐标和顶点坐标,以创建一个四边形。这四边形将字形的位图数据绘制到屏幕上的指定位置。8 i+ e9 c, {$ U" W% i% R4 _8 t
  16. * n  d" Q) V7 b& E8 A. I$ m6 b( A
  17. x += (face->glyph->advance.x >> 6);:更新 x 坐标,以便将下一个字符紧密排列在当前字符的后面。face->glyph->advance.x 包含字符的横向位移信息,>> 6 是用来将其转换为像素单位的操作。
    - [* U, A* H" q( t0 z( d
  18. $ K( v& q. n* \' q2 Z
  19. 最后,glDisable(GL_BLEND); 用于禁用混合模式,以免影响后续的绘制操作。
    . p1 ]' ~/ n& o8 P
  20. " a) p3 j. l* `+ Y/ e! O$ v
  21. 总之,renderString 函数的作用是将传递给它的字符串中的字符一个接一个地绘制到OpenGL上下文中,使用FreeType加载的字形数据和字体纹理来实现文本渲染效果。渲染过程涉及到字符的位置计算、纹理坐标的设置以及混合模式的启用和禁用,以确保字符在屏幕上正确显示。( u. a( S5 V% W
复制代码

8 E2 Y4 t3 }6 c- E5 V; V0 f0 _1 x5 ^. j/ u. ~
  1. 字形数据处理的关键函数之一。以下是 FT_Load_Char 函数的详细解释:  K4 q3 A8 _& A  ^
  2. ; D" d7 L* h2 d' a6 [  ^7 @1 Y
  3. 参数:" A( H) u8 K5 |$ V" a2 S
  4. ! G1 U" f& e1 Q* f( s5 [: a
  5. face:一个指向已经打开的字体文件的 FT_Face 结构体的指针。FT_Face 包含了字体的各种信息,包括字形数据。3 ?5 h/ x! W3 `8 b
  6. char_code:要加载的字符的Unicode编码值。您需要传递字符的Unicode编码作为此参数,以指定要加载的字符。
    2 K$ L$ H5 P% k
  7. load_flags:一个用于控制字形加载选项的标志位。您可以使用这些标志位来控制加载的方式,例如是否要加载字形的轮廓数据、是否要加载字形的位图数据等。; {% D9 P0 {7 m; e/ ^- D( x* c+ V
  8. 功能:
    ( D% c7 r/ c& b

  9. 8 w% g2 s$ a$ ^+ p/ @2 O3 x+ M
  10. FT_Load_Char 函数的主要功能是加载指定字符的字形数据。0 A( S4 ^$ p9 D- _( L5 c
  11. 如果成功,它将在 FT_Face 结构体中的 glyph 字段中填充有关字符的字形信息。
    + D5 e  ^3 k9 X9 y
  12. 这包括了字符的轮廓数据、位图数据、宽度、高度、位图偏移等等,具体取决于传递给 load_flags 参数的设置。
    3 W' Q: w4 \$ v( d! }9 p6 y/ C4 N
  13. 使用示例:) h2 b# w3 G" U1 i- G) j1 P3 k: ^. [, [

  14. # q8 L) l: j2 w/ }
  15. c: f; D+ t* }/ @% X& o0 L
  16. Copy code, w* V2 V! l8 Q, G1 r. V+ Q* g2 w
  17. FT_Load_Char(face, 'A', FT_LOAD_RENDER);
    : D+ z, W7 q. g" n2 U8 v
  18. 这个示例会加载字体中字符 'A' 的字形数据,并将其渲染到位图中。FT_LOAD_RENDER 标志告诉FreeType要渲染字符的位图数据。加载后,您可以在 face->glyph 结构体中找到有关 'A' 字符的相关信息,包括位图数据、宽度、高度、位图偏移等等。  x" x0 v5 C- H. }6 |! G

  19. 2 R, @: F! I4 _* |5 o" A- T! n, s( I0 V
  20. 错误处理:
    ; P# q5 ~3 u1 B
  21. 3 E/ r1 n: Y; g) l! V
  22. 如果加载失败,FT_Load_Char 函数可以返回错误代码。您应该检查返回值以进行错误处理,并根据需要采取适当的措施,例如跳过加载失败的字符或终止渲染过程。0 h5 T! g7 L0 c' }
  23. 总之,FT_Load_Char 函数是FreeType库中用于加载指定字符的字形数据的重要功能之一,它使您能够准备要渲染的字符数据,以便在文本渲染中使用。加载的数据可以包括字符的轮廓信息(矢量数据)和位图信息,具体取决于 load_flags 参数的设置。这个函数在字体渲染中起到关键作用,以便将字符正确呈现在屏幕上。
复制代码
8 ]: P: `1 D6 H3 O  R( L: r

9 X7 Z7 e, y. \+ J$ s代码
; q. \  f7 G: E! h0 g4 S. [/ k+ e1 I. M  ?: f! H
  1. ; p' r9 m" \9 z, a

  2. / f: e! [/ |" b  k

  3. 5 B! V7 ?! K3 e
  4. #include <stdio.h># B# w/ u2 i# T. Z& l
  5. #include <stdlib.h>3 {: g( y; _( X
  6. #include <GL/glew.h>. s# G* S# f9 ~  h
  7. #include <GLFW/glfw3.h>5 \' k5 K2 i$ u$ j
  8. #include <ft2build.h>
    7 y9 D  R+ Z. }" Y; d
  9. #include FT_FREETYPE_H
    ! j- B/ ?+ r" V) n$ Z+ u
  10. # {" S+ g/ S  a
  11. // 定义字形数据的字节数组, {% l0 q) U4 b
  12. unsigned char fontData[] = {
    " B) ^: F: s: P. w9 e
  13.     // 字形数据的字节表示
    - b( f4 Z- \; l  o/ j
  14.     // 例如,这里可以包含字母、数字和符号的字形数据3 H$ V% r0 @; d1 I
  15. };& X7 J6 p9 y7 n

  16. ) l! b: J' j' Y# }; g1 _$ ~: f
  17. FT_Library library;
    - E) e4 x5 P# d) W
  18. FT_Face face;
    ( B3 G8 c4 O8 r
  19. GLuint fontTexture;
    + q/ u7 x' |) j9 D( L3 f& l' {
  20. ( i' X4 c7 k8 v6 U7 O# ^7 T. S4 y
  21. // 初始化FreeType库和OpenGL
    6 p6 `/ O1 y  O/ i  ~& i' u: S7 Z
  22. void initialize() {$ E- {2 f* V4 S- |8 j
  23.     if (FT_Init_FreeType(&library)) {0 F2 h5 ~7 j& n8 I
  24.         fprintf(stderr, "Failed to initialize FreeType\n");. l; \# G8 o( m5 Y  O5 T8 C
  25.         exit(EXIT_FAILURE);
    8 A$ M6 ?% c( w3 h7 u
  26.     }
    5 J8 X9 u4 j, {

  27. ' C: h9 G; q6 f# O- C1 }
  28.     if (FT_New_Memory_Face(library, fontData, sizeof(fontData), 0, &face)) {) f: b, C3 H' G
  29.         fprintf(stderr, "Failed to create a FreeType font face\n");
    ; k$ h$ ?+ ]1 A3 v- F
  30.         exit(EXIT_FAILURE);* x2 `- f  P1 m4 I: v! f% H" X
  31.     }. E8 ?% D- _" O8 @. d; z9 T, a

  32. 8 _* E5 x" K, Y& q4 n$ W0 z
  33.     if (FT_Set_Pixel_Sizes(face, 0, 48)) { // 设置字体大小
    ; s- I! i  }% c' ~2 m
  34.         fprintf(stderr, "Failed to set font size\n");! R* J9 F; n+ F. B! g5 ~3 H
  35.         exit(EXIT_FAILURE);
    , k8 {; E9 h, z5 L
  36.     }
    % F/ Q6 N* E8 \& s7 Q

  37. ' A& K- ^0 O$ l* N
  38.     glGenTextures(1, &fontTexture);
    6 k3 v! j# U* S) ~0 r
  39.     glBindTexture(GL_TEXTURE_2D, fontTexture);
    * i- L3 y1 {2 \+ i7 u/ w  L; J0 L! \
  40.     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);- Z1 {# X1 Z. W6 d1 h

  41. * J  [/ H; A$ a0 G" ^0 T
  42.     // 将字形数据传递给OpenGL纹理' ~" l) ~$ D% [
  43.     for (int i = 0; i < 128; i++) {
      q- p+ @( \/ {6 |4 l
  44.         if (FT_Load_Char(face, i, FT_LOAD_RENDER)) {3 n* |2 h! h4 S. X+ t* }/ y
  45.             fprintf(stderr, "Failed to load glyph for character '%c'\n", i);2 ~" c3 N- K4 ^* v* f
  46.             continue;4 r, Q: e$ |4 V# I
  47.         }
    ( c$ X: o. s( t7 ]
  48. 1 A% T; ^2 r: z  U% ~% T
  49.         glTexImage2D(6 s2 L- N, X  Y# M
  50.             GL_TEXTURE_2D,
    % u: p6 O: G( t* d5 T
  51.             0,
    2 R, {6 [4 l- u3 X' j0 a& n4 \
  52.             GL_RED,
    ; _3 f) _# @6 {% N, I  B
  53.             face->glyph->bitmap.width,
    2 A  c4 ]% t  A: a$ i& t& a
  54.             face->glyph->bitmap.rows,0 f3 U3 I( K# b/ n" E+ J( r
  55.             0,
    9 ^9 |8 h8 B. w+ E1 v0 V
  56.             GL_RED,1 S9 r/ z9 [" ?  V3 F; `+ h7 h9 D/ P% B/ e
  57.             GL_UNSIGNED_BYTE,- `' I0 @3 S3 f0 D/ ?9 I
  58.             face->glyph->bitmap.buffer
    # a- \4 Y: Z/ Y
  59.         );
    , x* ^- y& U. X2 m1 r
  60. " H, X( _0 r: m* ~- Q" c% V9 ~
  61.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);2 [, B: v- ^6 i" c1 k3 M$ o
  62.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    ; F/ ~  l& Q5 ^8 G: P' f! y
  63.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);: a6 |. ?# V; R0 o0 ?- {& ~& G! k' s
  64.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);8 M3 ~& P" `1 N
  65.     }8 b! q0 {: H+ G& \5 [2 `, W# j5 G
  66. }
    7 W  ]$ d) z# G4 A) O% K

  67. : m! ~8 @% c. b
  68. // 渲染字符串- N6 H3 n' y- \/ S5 Q. J
  69. void renderString(const char* text, float x, float y) {1 A& k3 H  P) Q; @
  70.     glBindTexture(GL_TEXTURE_2D, fontTexture);
    . b( q( A7 A# R4 T# r

  71. - d% u# D  U6 J  u
  72.     glEnable(GL_BLEND);
    - `- R9 N1 L& e) X( ]# x9 S
  73.     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);0 ^3 s( t" |: @/ c" I; h8 F3 M
  74. $ _) E* k8 V4 i* t
  75.     glBegin(GL_QUADS);
    . R$ }7 y( W6 i+ \4 F% D* t
  76.     for (const char* p = text; *p; p++) {
    6 m0 y4 Q+ b" }" Y9 U$ W
  77.         FT_Load_Char(face, *p, FT_LOAD_RENDER);
      d: {2 D) W# V! V  t8 L/ z

  78. , u7 b2 V! B% C) |: o- g; O: A+ J
  79.         glTexImage2D(
    5 R: W% W9 Y& ^
  80.             GL_TEXTURE_2D,
    5 @& D; ]$ ]* i9 j; y) |# s- g6 g
  81.             0,* A4 s, g6 `$ M7 ?8 f1 o
  82.             GL_RED,; b8 [6 t4 W/ s% q
  83.             face->glyph->bitmap.width,
    # e$ q0 [+ S5 k2 O$ g
  84.             face->glyph->bitmap.rows,
    + `" R6 r9 G9 S& Z7 \
  85.             0,
    4 Y$ D  n! ^& e/ P1 p
  86.             GL_RED,6 C: O9 g* b; W/ H
  87.             GL_UNSIGNED_BYTE,
    + K6 R& m8 K3 h, r+ S
  88.             face->glyph->bitmap.buffer
    6 w( f' e1 ?$ N7 [9 @# _
  89.         );
    * M4 M! h& @$ Q3 N+ K- g0 u
  90. & s+ g* o# x& y& a$ v
  91.         float xpos = x + face->glyph->bitmap_left;- T0 R) `# W) ]% }6 Q
  92.         float ypos = y - (face->glyph->bitmap.rows - face->glyph->bitmap_top);
    " d* o! \: k9 T) k0 F& q9 [

  93. # g1 T' x$ a+ C
  94.         float w = face->glyph->bitmap.width;. ^4 r7 K! N* X: z7 F
  95.         float h = face->glyph->bitmap.rows;  p8 E. L% ^$ ~5 p# o0 {* }( G) I
  96. : a& g/ u0 o1 B% n' n* _( |
  97.         glTexCoord2f(0, 0);
    ! M% f3 s  b: z/ O2 y
  98.         glVertex2f(xpos, ypos);
    2 ]% X7 N" \# k* _

  99. , U) r" _$ J* c. X
  100.         glTexCoord2f(0, 1);
    ' P  h: s, p$ d) p( v
  101.         glVertex2f(xpos, ypos + h);
    4 c4 s* p. [; N

  102. 7 x2 D4 ?' g& M! l7 z# z; {
  103.         glTexCoord2f(1, 1);
    : w+ [. ]6 j# g% u' E
  104.         glVertex2f(xpos + w, ypos + h);  V/ y' [8 r3 h6 g( w

  105. 5 ~3 Z7 ~" v8 w
  106.         glTexCoord2f(1, 0);
    2 f; |8 X5 ]/ p
  107.         glVertex2f(xpos + w, ypos);
    ( o: l- T3 X0 ~9 @: V4 V0 J

  108. ( g, a: ^2 u( I% c) u! B5 a
  109.         x += (face->glyph->advance.x >> 6); // 字符之间的间距: R% z: y' E  T2 B1 w) z
  110.     }
    8 N0 C% a: d& O  T
  111.     glEnd();
    2 B5 R' }6 l6 K1 s1 U! y
  112. % `. l( B& M7 C% K  {
  113.     glDisable(GL_BLEND);* V3 H) @$ B5 _/ A0 g1 @: v  y
  114. }
    4 F5 {" T- V/ f1 H$ h# X
  115.   D6 J; k' A" L. a1 @
  116. int main() {
    3 r! X6 \  t8 d* `
  117.     if (!glfwInit()) {
    / E6 i3 y1 F6 _; n
  118.         fprintf(stderr, "Failed to initialize GLFW\n");
    ! ^0 W+ B/ |1 c! @3 d
  119.         return -1;
    5 J. S- {, w/ N9 O6 r
  120.     }/ {/ t" W- X- B6 k7 [( l. {

  121. % [2 y' R! `5 t9 u) _! b
  122.     GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL Text Rendering", NULL, NULL);
    ' U" R7 g( @/ B/ r' ~3 x
  123.     if (!window) {
    5 K5 E$ I: E; `/ ]! Q
  124.         fprintf(stderr, "Failed to create GLFW window\n");% Q2 _# i2 n! X# \4 @: g
  125.         glfwTerminate();4 P; [, i1 Y3 k$ [) C9 f
  126.         return -1;. f8 Q" ~! Q% I" [4 w3 Y
  127.     }
    " f% m; y$ @& |  u) c# |+ a+ c

  128. : r) S# n8 M3 Y1 @  E4 ~
  129.     glfwMakeContextCurrent(window);
    ' g8 a2 f; L; o& T
  130.     glewInit();' H9 o' q3 a! L, s

  131. " J0 x% A) i1 D5 o1 u6 a# B
  132.     initialize();, I0 |& ?* Z9 y; A$ M

  133. 3 \; G6 D1 t% ^* f& m  }
  134.     while (!glfwWindowShouldClose(window)) {
    ! d3 h- a4 |- U8 Y" r1 H4 m
  135.         glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    3 j4 H& A3 g( u6 u' I+ w
  136.         glClear(GL_COLOR_BUFFER_BIT);: n$ r. b$ g2 b/ o/ ]
  137. 0 t, w1 D+ Q; d; O0 F$ X
  138.         glColor3f(1.0f, 1.0f, 1.0f);, \1 S- P2 M2 D) ]& I1 D, z* Q! l, h
  139.         renderString("Hello, OpenGL!", 100.0f, 100.0f);
    ; l* M1 l2 h7 r
  140. ! J7 c  g2 Z% I! A4 p/ k
  141.         glfwSwapBuffers(window);
    ' j0 J# g4 s$ E2 I+ V2 ]4 h! L2 @
  142.         glfwPollEvents();+ m' X: b) {( n& F
  143.     }
    9 O9 p+ J/ I; a- G2 s7 k% _/ a

  144. ' K4 f' W0 x! O/ l' T
  145.     FT_Done_Face(face);4 u# g0 v/ u6 k' _
  146.     FT_Done_FreeType(library);
    5 c( ?9 s( t" N3 W/ g* X
  147. $ I$ W" N0 m3 ?* z4 B5 ^' i$ w
  148.     glfwTerminate();# s; ^2 A  y0 Q6 Y' E+ l( t" @; g

  149. / ]  r/ `. R1 x: n+ T
  150.     return 0;
    2 G; a6 j! ]; i
  151. }  O1 D) ]( Z, }( o! Z0 ?& c
复制代码
& ?% d" C1 R& d8 W( q0 O

9 C) t- r- _. W% o- T7 V  O, c0 r
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 很美好很美好1 很差劲很差劲
回复

使用道具 举报

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

使用道具 举报

板凳
发表于 2026-4-13 19:23 | 只看该作者
向技术大佬学习
回复 支持 反对

使用道具 举报

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

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