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

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

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

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

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

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

本帖最后由 shane007 于 2023-9-6 15:32 编辑
8 q$ Q3 B- K9 S  K$ }) Q
( n# h8 r3 S# I6 E0 [以下是一个用来做参照的opengl显示字符串的代码,使用了freetype库。
- A+ S, x  R0 u) }本代码经过分析以及改写之后,将取代游戏原有的显示函数。; O+ o9 l! p! N0 s2 k

- |! \  g/ x! L* Q: p9 n代码详细说明如下3 V2 s& d1 {* k4 O0 {( b
' @: P% s' f6 ]* ?, a
  1. 在上述 renderString 函数中,我们有以下关键部分的解释:
    0 a/ d9 A& [* Z# |
  2. 1 W4 M- Z, v, o! t! N1 |; v  I2 N
  3. glBindTexture(GL_TEXTURE_2D, fontTexture);:将字体纹理绑定到当前的OpenGL上下文。这是因为我们要使用 fontTexture 中存储的字形位图数据进行渲染。3 q0 `' N8 d. b0 \9 N

  4. 9 p0 A% D( Y- F( [: E( m
  5. glEnable(GL_BLEND); 和 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);:启用混合模式以处理字符的透明度。混合模式通过 glBlendFunc 设置,这里使用了常见的源和目标因子来实现源颜色与目标颜色的混合,从而实现透明效果。
    & c3 R0 w( y$ @, \
  6. 8 f$ _! L+ v& W  M' }
  7. glBegin(GL_QUADS); 和 glEnd();:在这两个函数之间的代码用于指定字符的四边形顶点,以便在OpenGL上下文中绘制字符。: N0 o. m+ q1 p* f) k8 m
  8. 5 R6 d0 I- K* F" L6 b" ]
  9. for (const char* p = text; *p; p++) { ... }:这个循环遍历传递给函数的字符串 text 中的每个字符,然后为每个字符执行以下操作:
    8 @7 d7 ]# z9 M
  10. 8 C+ Z# O6 e: J5 J3 z* r( h' Y3 u
  11. FT_Load_Char(face, *p, FT_LOAD_RENDER);:使用FreeType加载字符的字形数据,包括轮廓和位图信息。加载后,可以从 face->glyph 中访问该字符的字形数据。
    $ @+ e# @. |4 ?" Z' J# t4 R5 ^2 n+ s' j

  12. % u# O! H4 F* }, R
  13. 计算字符在屏幕上的位置和大小,包括 xpos(x坐标)、ypos(y坐标)、w(宽度)和 h(高度)。2 M% X* y) t& Z/ r- m8 {9 r
  14. & ?/ r% }  A  L5 O
  15. 使用 glTexCoord2f 和 glVertex2f 来指定字符的纹理坐标和顶点坐标,以创建一个四边形。这四边形将字形的位图数据绘制到屏幕上的指定位置。
    ) m) N' C/ k  ?$ e! B( w7 r

  16. ) D7 |8 ^1 i9 o' a9 Z
  17. x += (face->glyph->advance.x >> 6);:更新 x 坐标,以便将下一个字符紧密排列在当前字符的后面。face->glyph->advance.x 包含字符的横向位移信息,>> 6 是用来将其转换为像素单位的操作。
    $ |" ^) D4 r1 F$ }; W
  18. 5 E! U7 w0 r5 j, b
  19. 最后,glDisable(GL_BLEND); 用于禁用混合模式,以免影响后续的绘制操作。
    : u' L2 }; Q+ B& `& Q* P

  20. 9 D/ S: m, w7 {9 X. Z( m
  21. 总之,renderString 函数的作用是将传递给它的字符串中的字符一个接一个地绘制到OpenGL上下文中,使用FreeType加载的字形数据和字体纹理来实现文本渲染效果。渲染过程涉及到字符的位置计算、纹理坐标的设置以及混合模式的启用和禁用,以确保字符在屏幕上正确显示。! D2 D1 c3 ]# {. Y' N/ ]" \' P
复制代码

# k$ {& ]6 Z  n5 e8 B7 }( ?1 r* T# B' p1 ?3 O2 j
  1. 字形数据处理的关键函数之一。以下是 FT_Load_Char 函数的详细解释:
    8 Z( h0 w; m7 H; D

  2. / L0 ~! @3 i2 l7 D9 V5 w
  3. 参数:8 j% Z$ y2 K9 J( d5 D) u
  4. ! L+ [. a: }5 V
  5. face:一个指向已经打开的字体文件的 FT_Face 结构体的指针。FT_Face 包含了字体的各种信息,包括字形数据。
    . J5 q: y- F7 D. Y
  6. char_code:要加载的字符的Unicode编码值。您需要传递字符的Unicode编码作为此参数,以指定要加载的字符。
    7 o# q) i: v- g( c& T3 ?6 h
  7. load_flags:一个用于控制字形加载选项的标志位。您可以使用这些标志位来控制加载的方式,例如是否要加载字形的轮廓数据、是否要加载字形的位图数据等。4 C0 `; u% O" d; l
  8. 功能:0 ^% Y% o1 A% `" h- n1 W

  9. # l. B7 i, h5 _' X+ b! a' i. p9 r
  10. FT_Load_Char 函数的主要功能是加载指定字符的字形数据。
    " ^) w8 X: B, l7 d2 _
  11. 如果成功,它将在 FT_Face 结构体中的 glyph 字段中填充有关字符的字形信息。
    6 ^4 x% B- T" Q* f. }0 F
  12. 这包括了字符的轮廓数据、位图数据、宽度、高度、位图偏移等等,具体取决于传递给 load_flags 参数的设置。
    5 w5 b* l3 G( I  O
  13. 使用示例:
    : }9 f& {2 N* q' k
  14. ' A8 U! ^, z: _' X% _
  15. c# j! C- D; T. d, O" }; x0 O
  16. Copy code0 ]4 d( E3 @, c  o# v1 Q, O- o5 ?/ s
  17. FT_Load_Char(face, 'A', FT_LOAD_RENDER);% v% ~. g6 |1 b4 g! q3 f
  18. 这个示例会加载字体中字符 'A' 的字形数据,并将其渲染到位图中。FT_LOAD_RENDER 标志告诉FreeType要渲染字符的位图数据。加载后,您可以在 face->glyph 结构体中找到有关 'A' 字符的相关信息,包括位图数据、宽度、高度、位图偏移等等。
    0 I# ?6 c7 |4 C8 K3 c4 O, r1 [; X
  19. % S" [. W+ ]; i8 f! g
  20. 错误处理:" I! N. [4 P7 Y  M

  21. ! l. q! A( J7 `9 G! o5 ?" L
  22. 如果加载失败,FT_Load_Char 函数可以返回错误代码。您应该检查返回值以进行错误处理,并根据需要采取适当的措施,例如跳过加载失败的字符或终止渲染过程。
    & v) o/ S+ I5 S
  23. 总之,FT_Load_Char 函数是FreeType库中用于加载指定字符的字形数据的重要功能之一,它使您能够准备要渲染的字符数据,以便在文本渲染中使用。加载的数据可以包括字符的轮廓信息(矢量数据)和位图信息,具体取决于 load_flags 参数的设置。这个函数在字体渲染中起到关键作用,以便将字符正确呈现在屏幕上。
复制代码

3 K# O! Y% ~$ X4 Z/ p) s2 v3 M& d* m! J- B
代码' k4 ^& N/ Y2 o4 @7 t; O
0 i# k8 _/ P% P! Q3 Y

  1. 7 @0 v! y! a3 p5 Z
  2. ' P8 C' D* |, L" \
  3. ; F$ S$ I2 ]8 V* Q- [7 m- ]+ o7 Z, l
  4. #include <stdio.h>) `0 w- f1 G  t" s9 {8 R, `
  5. #include <stdlib.h>* \1 X7 Y# R& m4 ~
  6. #include <GL/glew.h>
    & f, K' W3 K: U/ [0 c
  7. #include <GLFW/glfw3.h>
    1 s; V0 i+ {6 V4 }- ?. h
  8. #include <ft2build.h>
    / l9 ~' [  m9 X/ y$ H+ M3 n
  9. #include FT_FREETYPE_H
    2 ]5 f9 a1 b  |

  10. * `  w# z" m/ W; }2 Q
  11. // 定义字形数据的字节数组) w* `9 i  m( F# }$ j0 H$ M! \
  12. unsigned char fontData[] = {+ }: R6 _; {  m1 F4 _. Y1 p' g
  13.     // 字形数据的字节表示
    " s. O; e9 y% d3 ~4 Q
  14.     // 例如,这里可以包含字母、数字和符号的字形数据
    5 D7 Y  E0 ~1 t6 E) d
  15. };
    1 A: [5 T6 t6 v+ n  q+ }
  16. $ L! }8 ?8 K3 F8 I  _# o
  17. FT_Library library;1 D' l4 l* k" F( n; A/ q
  18. FT_Face face;
    & @5 n, c0 S8 g8 y% r" F
  19. GLuint fontTexture;
    0 Y  u9 m+ v) c3 D+ M/ _9 c

  20. ( v; u9 R/ w, E) i% ?2 A9 L' N: [( ~
  21. // 初始化FreeType库和OpenGL! E3 `% U4 q$ k& X4 L( x) @
  22. void initialize() {: E+ E9 c0 [! |9 f: a, {7 f5 @1 F
  23.     if (FT_Init_FreeType(&library)) {$ @  W) I0 Y; `" {0 ^4 V6 A
  24.         fprintf(stderr, "Failed to initialize FreeType\n");0 @3 w2 n2 P+ I
  25.         exit(EXIT_FAILURE);; B: S$ ?5 G" g1 Q( s# L% }; @
  26.     }7 r$ V  Q0 l. ?$ l
  27. / W6 K$ z& c6 `' N$ u/ D; p
  28.     if (FT_New_Memory_Face(library, fontData, sizeof(fontData), 0, &face)) {
    - h: b  B9 z8 I1 B! }; a
  29.         fprintf(stderr, "Failed to create a FreeType font face\n");# C/ Q( V# w: |$ T/ T% q5 `, t: ~  ^
  30.         exit(EXIT_FAILURE);
    & ^# |: a5 p1 J" n
  31.     }
    * v5 a6 ^3 z' ?; I( R
  32. * ~; l+ @* H1 M1 I3 U+ R
  33.     if (FT_Set_Pixel_Sizes(face, 0, 48)) { // 设置字体大小
    , Y7 V: J6 b& b, U& R
  34.         fprintf(stderr, "Failed to set font size\n");6 e* Q  [- q+ c" J' |3 @
  35.         exit(EXIT_FAILURE);
    6 M% g& x, z9 a& v  E
  36.     }
    $ V4 `, s; M" n9 ^7 S  p

  37. ( }9 ]9 f- u, ]* F. B. i
  38.     glGenTextures(1, &fontTexture);- X5 I, |# \7 u% ~6 V2 L+ G
  39.     glBindTexture(GL_TEXTURE_2D, fontTexture);( j0 b. p2 N/ P: p, o6 q
  40.     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);( A/ A: U  `& s3 L; K
  41. 9 u0 p& F& A' G: M) y
  42.     // 将字形数据传递给OpenGL纹理0 P+ J4 q3 ]- e5 @3 t. K! H
  43.     for (int i = 0; i < 128; i++) {
    8 I8 |0 U  |6 g: T! B. e4 A
  44.         if (FT_Load_Char(face, i, FT_LOAD_RENDER)) {
    0 n1 o2 k5 y) S9 Q1 _, j! n" O0 n
  45.             fprintf(stderr, "Failed to load glyph for character '%c'\n", i);
    3 ]9 e3 e) r7 h+ o# y
  46.             continue;7 d, H0 P+ |! a0 j5 m& M: A: `3 A
  47.         }% j6 D# k6 J- ~& z" K3 _
  48. 4 q; |' d% w! _; I) T
  49.         glTexImage2D(/ y. k2 v9 s. i
  50.             GL_TEXTURE_2D,2 z! r; Y0 U+ a
  51.             0,
    4 x) z5 q' f% e
  52.             GL_RED,# m, H$ {8 @' a/ Z3 {
  53.             face->glyph->bitmap.width,
    2 i: P( w& a- [5 c
  54.             face->glyph->bitmap.rows," D. q% q9 r4 h5 t* f, p, ~  p
  55.             0,% z; ^! ^( x4 {. _4 T
  56.             GL_RED,
    ' Q" E6 `- I" p6 V# w- [
  57.             GL_UNSIGNED_BYTE,! A' L" g; d. N
  58.             face->glyph->bitmap.buffer/ e2 |3 k/ r% ], ^- Z% X8 [
  59.         );! |! Q8 y6 W! C+ y# N
  60. 6 T9 y2 R2 \( V4 X+ N
  61.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    # D# N# b, `# T; q
  62.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);/ Z; m0 K; W8 J4 \; O$ c
  63.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);& N' o- N/ T% ^* W9 g& v2 b
  64.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);- J- J1 y9 M+ q( T6 g% P+ I8 `
  65.     }) e6 P" A8 F2 N7 O' y
  66. }
    6 [' o* O6 \# B; p7 b! D# a( x

  67. 8 u4 ]9 r) ^, d- k( W% I. O% V, D
  68. // 渲染字符串, e' f2 _6 m7 s2 y. i
  69. void renderString(const char* text, float x, float y) {
    0 v7 A6 @) ~2 W
  70.     glBindTexture(GL_TEXTURE_2D, fontTexture);
    % p3 f& x7 L+ u! H! a  i* P  E
  71. ! S8 W4 x/ r( I$ z5 Y/ m$ B2 A
  72.     glEnable(GL_BLEND);
    ) L; f( m: B5 K) ?, H% a8 k
  73.     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);8 J+ f& O6 z$ S; \1 ~
  74. 1 a$ H( r; d& O7 G. I
  75.     glBegin(GL_QUADS);; {0 H- B9 _9 v8 {; C& n6 [
  76.     for (const char* p = text; *p; p++) {
    5 q- r% F* ~7 u
  77.         FT_Load_Char(face, *p, FT_LOAD_RENDER);
    * E& g% [/ X, _4 b
  78. . @. ?: i8 g3 A# e' x4 I/ q
  79.         glTexImage2D(
    ) V) t( l) T2 \: I' o( p  f
  80.             GL_TEXTURE_2D,. w+ u  K( Z2 z! c9 o. N, h
  81.             0,
    0 F) P; {3 k& t
  82.             GL_RED,
    - z2 b# A) [  ^- o8 O" f
  83.             face->glyph->bitmap.width,2 {0 `* d: D# [# T
  84.             face->glyph->bitmap.rows,
    # ]: k' c( I1 @' m! p) g/ B) M9 \
  85.             0,0 A. ?" D: n1 [
  86.             GL_RED,/ f4 {) N" b- ]: V' t
  87.             GL_UNSIGNED_BYTE,5 j" ^$ g9 O9 L4 v  L& N
  88.             face->glyph->bitmap.buffer
    / _8 P8 ]% \- \* _! d8 v
  89.         );
    3 d7 }3 x6 M) E: o3 |: P! Z
  90. ! _  Y! g' ?% P1 Q2 y  l& i
  91.         float xpos = x + face->glyph->bitmap_left;+ \' W. O. f5 p, M+ q; R* @; ]- ?
  92.         float ypos = y - (face->glyph->bitmap.rows - face->glyph->bitmap_top);
    / R; G; G8 p7 F/ N- P
  93. 7 @6 e( v4 P- L+ ]
  94.         float w = face->glyph->bitmap.width;
    9 {) r( t8 {- L  _: N
  95.         float h = face->glyph->bitmap.rows;8 u8 i: |* a- M9 {
  96. / I& O) w7 y( U7 A, v
  97.         glTexCoord2f(0, 0);
    3 r. q9 D" A8 h4 u8 F1 d
  98.         glVertex2f(xpos, ypos);  }$ t% D* c6 B6 m6 I7 \; C9 C
  99. 6 J1 N; U3 }8 m" g: M8 p
  100.         glTexCoord2f(0, 1);; x! C% t0 H$ K! x, V( i0 S
  101.         glVertex2f(xpos, ypos + h);+ A% v! x' J7 w% X: Z

  102. , z: o) E% u0 u2 w! \' s" r
  103.         glTexCoord2f(1, 1);
    3 U1 q5 R1 Q6 \9 a2 k, j9 f
  104.         glVertex2f(xpos + w, ypos + h);
    ; _8 b" n" Z3 ?$ @- C* ?( O3 [7 T
  105. / n' r5 z5 d5 W
  106.         glTexCoord2f(1, 0);% P( u! P% ?, z' K4 g. B5 J' |
  107.         glVertex2f(xpos + w, ypos);
    : k- }) ^* S; {8 n

  108. 7 ?0 f  p; S9 |5 j, q& f
  109.         x += (face->glyph->advance.x >> 6); // 字符之间的间距
    : }+ i% ]* C2 L& G
  110.     }7 {9 d0 s6 w7 A2 y' E" C$ a  p
  111.     glEnd();7 l+ q: x/ L3 V6 a" y$ U

  112. 3 K2 z5 I' p) e
  113.     glDisable(GL_BLEND);" F5 D" L1 Z; }) J
  114. }
    2 r, f. {+ O. v, o5 H7 g

  115. ( Y9 U. f$ X. X# L. G' A! D
  116. int main() {! h4 R% c( @( ~% Q
  117.     if (!glfwInit()) {- A* Y: F/ \* R5 s
  118.         fprintf(stderr, "Failed to initialize GLFW\n");; C5 c) D  c, W0 U
  119.         return -1;
    % l) X% r/ _6 y; H# {% f$ K
  120.     }
    , p. N; V; x: {( M! [
  121. ' N# }/ A% n7 v( V8 N" E6 \; s
  122.     GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL Text Rendering", NULL, NULL);
    + ^# A" J6 _7 X) @8 P, ^6 }
  123.     if (!window) {
    . j# N8 L  h/ y+ Q. p2 a
  124.         fprintf(stderr, "Failed to create GLFW window\n");. ?# J% M/ ?, n' O7 \+ s/ o2 D) r
  125.         glfwTerminate();- [# c( W) x; h
  126.         return -1;: t( x; G# U2 D! a% r
  127.     }
    + k* x0 c' b% ~( J3 v* u! K: @

  128. + T. r4 e' s- H4 U8 \5 x
  129.     glfwMakeContextCurrent(window);3 L$ s& {2 F' r7 D
  130.     glewInit();
    1 t2 n$ F5 }. ]" B' w: G- f

  131. : C- ~3 F1 t/ [
  132.     initialize();
    2 {7 ~/ A& {2 {  @, Y% L
  133. & s$ K! _5 v+ m: J  K
  134.     while (!glfwWindowShouldClose(window)) {- `# w5 E4 F8 z5 A% i7 ?
  135.         glClearColor(0.0f, 0.0f, 0.0f, 1.0f);9 n0 F* c: u1 a. t
  136.         glClear(GL_COLOR_BUFFER_BIT);4 `4 u8 H1 G! A1 l* j' N7 n& W
  137. 8 w! e! S! V6 R  @* I, j: S
  138.         glColor3f(1.0f, 1.0f, 1.0f);
    " f& T7 z8 {$ D( Y8 @6 i
  139.         renderString("Hello, OpenGL!", 100.0f, 100.0f);3 v, k, X/ D# B6 e

  140. + ^) k, D  S& o/ b3 {
  141.         glfwSwapBuffers(window);# Y* b3 E6 C$ W  y5 e
  142.         glfwPollEvents();2 d- @, b' ~# Q% b! G
  143.     }8 y( X1 _' ^4 q3 {* a
  144.   V# K  y! e& Q% W3 i% P
  145.     FT_Done_Face(face);
    ! }1 i5 b; |' B8 N8 N
  146.     FT_Done_FreeType(library);
    ) y% d; \9 t: r- m4 `( p

  147. 6 s0 t8 i: v4 l6 s; f8 W+ V8 W/ @
  148.     glfwTerminate();5 p6 F" K( x# d) {) f. c

  149. 5 a" [9 u) e% T, }2 O8 Z, t5 m
  150.     return 0;
    % u" }2 ]9 P4 r/ V
  151. }  k! M% H. U4 w
复制代码

6 S1 [* a3 u( z' _0 K9 x% T/ m4 M% n& d
分享到:  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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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