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

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

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

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

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

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

本帖最后由 shane007 于 2023-9-6 15:32 编辑
5 D' C, q( S' @" k( S2 b# R; ~4 _5 a5 u2 W
以下是一个用来做参照的opengl显示字符串的代码,使用了freetype库。  _3 o$ M, a5 k! s, J5 i) F
本代码经过分析以及改写之后,将取代游戏原有的显示函数。
/ K9 d* Y: |6 l! }% ?# x" c) f! g, U7 S! a
代码详细说明如下; c2 @3 P" U3 {6 s

1 f! b* N8 {+ ~/ V
  1. 在上述 renderString 函数中,我们有以下关键部分的解释:+ `! K* w8 n$ l% P0 q
  2. 8 _- U3 k( V) k9 A" h
  3. glBindTexture(GL_TEXTURE_2D, fontTexture);:将字体纹理绑定到当前的OpenGL上下文。这是因为我们要使用 fontTexture 中存储的字形位图数据进行渲染。/ w! m' U/ y" a. ?: m. z% q

  4. ' G0 Q7 R9 C! u, j, @" n0 y
  5. glEnable(GL_BLEND); 和 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);:启用混合模式以处理字符的透明度。混合模式通过 glBlendFunc 设置,这里使用了常见的源和目标因子来实现源颜色与目标颜色的混合,从而实现透明效果。
    8 h+ F! m) x2 \% L8 Z: d
  6. 1 C" A2 N7 P+ q% X8 `$ F
  7. glBegin(GL_QUADS); 和 glEnd();:在这两个函数之间的代码用于指定字符的四边形顶点,以便在OpenGL上下文中绘制字符。8 j3 g( \! r& e* u' {" p7 ^
  8. $ S$ p8 D/ B& p2 S, V- [( s
  9. for (const char* p = text; *p; p++) { ... }:这个循环遍历传递给函数的字符串 text 中的每个字符,然后为每个字符执行以下操作:0 q/ b6 k6 `, m. d! r# T9 n
  10. 2 d1 z0 L% p+ \; ]" Q! S
  11. FT_Load_Char(face, *p, FT_LOAD_RENDER);:使用FreeType加载字符的字形数据,包括轮廓和位图信息。加载后,可以从 face->glyph 中访问该字符的字形数据。( x4 p2 N) O- Z* f( I4 l

  12. 2 J+ e. R0 }( u3 X" j; F* p
  13. 计算字符在屏幕上的位置和大小,包括 xpos(x坐标)、ypos(y坐标)、w(宽度)和 h(高度)。  z0 d8 Q5 k) _6 U
  14. - ~, @# M0 k; M; P2 X
  15. 使用 glTexCoord2f 和 glVertex2f 来指定字符的纹理坐标和顶点坐标,以创建一个四边形。这四边形将字形的位图数据绘制到屏幕上的指定位置。
    * z1 w# w+ x$ [
  16. 5 o( J0 |# }, K! n
  17. x += (face->glyph->advance.x >> 6);:更新 x 坐标,以便将下一个字符紧密排列在当前字符的后面。face->glyph->advance.x 包含字符的横向位移信息,>> 6 是用来将其转换为像素单位的操作。, w9 }+ H& x, N/ J
  18. % Q9 F6 ^) [6 V/ F% s3 C* T
  19. 最后,glDisable(GL_BLEND); 用于禁用混合模式,以免影响后续的绘制操作。- M4 I% q; \# A
  20. 8 l; U( U- o# o
  21. 总之,renderString 函数的作用是将传递给它的字符串中的字符一个接一个地绘制到OpenGL上下文中,使用FreeType加载的字形数据和字体纹理来实现文本渲染效果。渲染过程涉及到字符的位置计算、纹理坐标的设置以及混合模式的启用和禁用,以确保字符在屏幕上正确显示。
    # ]* ^* b% c, c1 \* L: U
复制代码

0 }( I/ R! n5 A1 S( P+ Q" ~  z& C& n% |) H: n# C8 F% x- y
  1. 字形数据处理的关键函数之一。以下是 FT_Load_Char 函数的详细解释:
      K+ ^; G+ L! t
  2. 4 ^& O" ]: ?1 z+ Q+ _( F4 F0 U. D5 p
  3. 参数:
    ) A- u4 z$ ^4 Y  |3 j" A  v

  4. * r5 U% w! o8 C1 v7 k) F+ @
  5. face:一个指向已经打开的字体文件的 FT_Face 结构体的指针。FT_Face 包含了字体的各种信息,包括字形数据。$ w  _8 p+ Y2 U5 N" b; v* m* I  S
  6. char_code:要加载的字符的Unicode编码值。您需要传递字符的Unicode编码作为此参数,以指定要加载的字符。
    + _$ X% Q$ l- T- A/ T
  7. load_flags:一个用于控制字形加载选项的标志位。您可以使用这些标志位来控制加载的方式,例如是否要加载字形的轮廓数据、是否要加载字形的位图数据等。* O% y$ a- J2 R8 e/ E
  8. 功能:/ r8 {) I" Z* B- P* M3 ]7 p7 `
  9. , z, y8 H5 Z9 ^+ T  R" D3 k$ l. ]: t
  10. FT_Load_Char 函数的主要功能是加载指定字符的字形数据。
    5 `- l9 ~' a7 g$ ~
  11. 如果成功,它将在 FT_Face 结构体中的 glyph 字段中填充有关字符的字形信息。
    ; R% {& i6 ?/ E+ Z4 v
  12. 这包括了字符的轮廓数据、位图数据、宽度、高度、位图偏移等等,具体取决于传递给 load_flags 参数的设置。
    5 q$ J- `9 P4 {/ t6 N
  13. 使用示例:
    : Q% f9 b& \5 [2 s# \5 P, c
  14. 9 U% j$ L7 K/ p3 p6 T6 W
  15. c7 ^0 w' Y: P3 y$ w2 }% h
  16. Copy code
    ) h" z+ |! L  ~
  17. FT_Load_Char(face, 'A', FT_LOAD_RENDER);
    / A, I; l0 I' J
  18. 这个示例会加载字体中字符 'A' 的字形数据,并将其渲染到位图中。FT_LOAD_RENDER 标志告诉FreeType要渲染字符的位图数据。加载后,您可以在 face->glyph 结构体中找到有关 'A' 字符的相关信息,包括位图数据、宽度、高度、位图偏移等等。
    , W2 j& ^4 p7 M( g6 O  S6 a
  19. # J4 T! Z& k# @7 F, ]/ k1 z1 ^
  20. 错误处理:
    ) I* w; o5 l; ~) C, R0 U; N. X; V

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

# t& @7 \( f1 y% ?& K- J; d
" C; q- E- T0 @; D( r代码
8 }$ R5 E  D, j' v
  g/ V; |- `! [. C# w, v6 E, P+ u9 G
  1. 3 G+ ]/ q1 a) s
  2. 7 d5 Q7 B4 h# a( ]

  3. : w: G! V- G3 Y- E: G! f+ j
  4. #include <stdio.h>
    ! F1 b. b( h3 G3 O' X1 }6 g
  5. #include <stdlib.h>
    " f& P5 _  |+ D; e
  6. #include <GL/glew.h>0 W1 {- N* l* e$ x" k6 F
  7. #include <GLFW/glfw3.h>* t% ?' `! {: e1 b
  8. #include <ft2build.h>
    $ X9 W+ R9 i; L8 _
  9. #include FT_FREETYPE_H$ }. Z2 R, H& ~( K) l& \
  10. * V% }1 {; M  _) @# K
  11. // 定义字形数据的字节数组
    - E; z0 x  d* E' e
  12. unsigned char fontData[] = {
    8 i5 s" J, A/ r
  13.     // 字形数据的字节表示
    , ]5 `4 y2 a1 T) ?
  14.     // 例如,这里可以包含字母、数字和符号的字形数据
    ! r4 G4 V* L2 p" h9 {  N2 Z0 ^
  15. };
    # ]" s# _$ q! s( I: L
  16. ' S% O% w( n3 h" W& V1 c- M
  17. FT_Library library;
    ( Y; g( v2 W% n3 a
  18. FT_Face face;' E9 u- [# Q" T8 L
  19. GLuint fontTexture;  U; M( f* p0 }1 Q# X' o- P4 ^1 \

  20. , h, R. i4 ?7 \
  21. // 初始化FreeType库和OpenGL1 p0 w, c' u( G; |% ~8 Y6 J1 l
  22. void initialize() {4 Q5 }% f. x$ a, F
  23.     if (FT_Init_FreeType(&library)) {
    / X& A& L1 Z, A" l
  24.         fprintf(stderr, "Failed to initialize FreeType\n");
    / B" ]  u$ N8 S. J. z) L
  25.         exit(EXIT_FAILURE);. D/ X2 n3 Y2 ~) j" U
  26.     }
    $ i( X( E9 ^9 S: v

  27. ) j- z4 }8 @" |# w9 }0 B. r# T
  28.     if (FT_New_Memory_Face(library, fontData, sizeof(fontData), 0, &face)) {
    . e' {. b$ b, C1 c0 h
  29.         fprintf(stderr, "Failed to create a FreeType font face\n");+ C+ q6 s- S4 H! W" A2 I9 R$ A
  30.         exit(EXIT_FAILURE);
    / C0 n. v# s( C- k- N# u9 J
  31.     }
    # r3 @7 z6 Z/ T! h. V
  32. ( B$ n0 J6 w, b: R
  33.     if (FT_Set_Pixel_Sizes(face, 0, 48)) { // 设置字体大小
    + A; g5 z/ ~  N9 [+ B
  34.         fprintf(stderr, "Failed to set font size\n");; O& p" S- ^  U6 t% p
  35.         exit(EXIT_FAILURE);
    , _4 c* Q% u0 u+ t* O& @4 d' H+ F
  36.     }+ ?3 V1 [$ _, o) G
  37. $ d( t/ Z9 }. F) P1 L2 s
  38.     glGenTextures(1, &fontTexture);
    % L" b, c4 f7 V4 t& \
  39.     glBindTexture(GL_TEXTURE_2D, fontTexture);
    ' L) p/ N3 A# L' t# h2 [' v" C
  40.     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    3 `5 b7 R$ `+ s

  41. " {+ Y) c, `& ]! l
  42.     // 将字形数据传递给OpenGL纹理
    ) x+ b4 R) m+ S! |
  43.     for (int i = 0; i < 128; i++) {- P  `+ E; \. D0 v
  44.         if (FT_Load_Char(face, i, FT_LOAD_RENDER)) {
    # H, |& D+ A' z8 _' z5 Q* r
  45.             fprintf(stderr, "Failed to load glyph for character '%c'\n", i);
    6 ]. q* f% s. e1 T: j
  46.             continue;) s4 U. O) d( J# o& I4 ]3 S- G6 x
  47.         }
    ( ^* a& R( K# n( t5 `2 v
  48. 9 h0 v6 W6 \7 n) C8 D
  49.         glTexImage2D(
    7 i$ ]. t) o7 @. |! X6 Z& J
  50.             GL_TEXTURE_2D,9 Z; }8 X& o; l
  51.             0,
    : u& r+ _" I! ^; F8 ~
  52.             GL_RED,
    - `  ]* o1 z1 `. d
  53.             face->glyph->bitmap.width,
    8 P; P* d1 U" e& E/ L
  54.             face->glyph->bitmap.rows,
    " {9 l7 H* M* n$ X
  55.             0,
    6 ?- n; _2 a' b( {9 ]" d; t
  56.             GL_RED,: G, W0 o0 i/ A3 |: s. m. @
  57.             GL_UNSIGNED_BYTE,# v% S" G' I) K0 M/ |
  58.             face->glyph->bitmap.buffer$ a9 O* ^9 ^$ K) V" v# v- k" c6 m2 J
  59.         );
    % @, p6 Z# `; R5 J2 J* E1 `# L

  60. ' i0 m/ n! t" n% A- l2 S
  61.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);. w4 O9 h4 V7 ]/ {
  62.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    7 J( x0 r  [5 A, X# }4 [
  63.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    7 e4 A+ T+ S/ m" X
  64.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);5 {' c8 J/ Z5 @& m) e2 ?! n
  65.     }8 @2 W% P0 Z  d0 y) k
  66. }% O' ~! Q3 N( _/ j0 _

  67. / O+ N+ ]$ \3 g/ h7 t" [# e
  68. // 渲染字符串
    # H- }. O: R; W+ ^9 {
  69. void renderString(const char* text, float x, float y) {
    3 Z$ P% r4 V5 _; y8 }7 f/ d$ }
  70.     glBindTexture(GL_TEXTURE_2D, fontTexture);
    * f, U5 k  n- v3 X6 e" r
  71. 9 M. {$ k& n% t6 u; Q
  72.     glEnable(GL_BLEND);
    ( f+ s* ~, t- }9 {, E9 k
  73.     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    6 V' Y- T* L* {' g) P5 X7 u

  74. 0 i, d  Y4 U; {( z2 Z/ \% u: ^# q
  75.     glBegin(GL_QUADS);
    0 G8 u. `, t% d  S
  76.     for (const char* p = text; *p; p++) {
    ' o: m+ a# D* T# }( q4 |
  77.         FT_Load_Char(face, *p, FT_LOAD_RENDER);
    * q3 I1 S; |0 d: V. M
  78. ) l& W1 x* x2 c1 w, f7 V
  79.         glTexImage2D(# x& b% b0 A8 v: \3 k, q& u
  80.             GL_TEXTURE_2D,/ {$ R8 q  ~% s9 d% G5 j# k. T+ ]
  81.             0,- B- {9 z3 A. f5 @4 t& u, r9 b
  82.             GL_RED,; K9 e/ ^% W% P3 D2 L
  83.             face->glyph->bitmap.width,* l% Y) f: F  v  F- D
  84.             face->glyph->bitmap.rows,
    1 ~& e3 |+ D, z& z" N& b. G8 r
  85.             0,
    ) t& X) s/ C$ Y( ~4 |8 k
  86.             GL_RED,6 l6 x3 w: X4 j$ I0 Z$ x
  87.             GL_UNSIGNED_BYTE,
    7 i0 s) L, q  h- ~/ C1 L5 B6 G9 q  `) Z0 q
  88.             face->glyph->bitmap.buffer' e6 f* I) p3 f6 t6 @( M
  89.         );- ?9 y5 I% \* R' y0 i% y; C

  90. ( u  e' T. D5 Y3 p" X6 q
  91.         float xpos = x + face->glyph->bitmap_left;
    + W6 H+ T* d0 c  ^6 S! d. k$ b7 Z
  92.         float ypos = y - (face->glyph->bitmap.rows - face->glyph->bitmap_top);
    & p. D) r* Z1 J; W* D3 N7 j& G, s

  93. $ @+ b6 W" c! S8 r: j2 H$ |2 K
  94.         float w = face->glyph->bitmap.width;
    ) v% G+ b; n& L3 y, J& e
  95.         float h = face->glyph->bitmap.rows;' q1 n3 ~7 i0 t( r
  96. ' k4 \' o, Z6 v, I
  97.         glTexCoord2f(0, 0);7 M( S( T" C8 T6 ]/ s
  98.         glVertex2f(xpos, ypos);5 b9 x2 |; r6 Z6 h7 x' ]% @

  99. 1 w; M( L+ E( u4 s
  100.         glTexCoord2f(0, 1);
    0 Z8 e' L! |! Z* h0 j( F. O+ b
  101.         glVertex2f(xpos, ypos + h);6 [, R7 A) C% z4 ~$ h% q

  102. 5 j' z- M% F7 t6 m% T
  103.         glTexCoord2f(1, 1);
      V+ h" E2 G1 W$ n  t. v2 p
  104.         glVertex2f(xpos + w, ypos + h);
    & E' T# j" y* q6 {4 s
  105. # v! N9 Y9 ~+ `3 f, o
  106.         glTexCoord2f(1, 0);
      x4 @) |) }2 y) I8 W6 i
  107.         glVertex2f(xpos + w, ypos);  w: u2 ~6 ?- n2 ?+ o( t1 c1 M& }9 i
  108. " \% K( G* x; B, b; |5 O
  109.         x += (face->glyph->advance.x >> 6); // 字符之间的间距6 }3 w  m" N5 V' N6 E- n  @
  110.     }, H/ E4 L# K0 {! H8 ]9 _/ b
  111.     glEnd();1 @. p  H8 c# D7 z$ w

  112. 9 w! T" d% E+ \4 y* S. z  Y8 J
  113.     glDisable(GL_BLEND);
    % W# H! }( _: d7 T$ P: p% @
  114. }
    ( _! d1 m& d( `. h$ B4 }
  115. $ M8 _" O+ Y: ~+ L
  116. int main() {
    4 \4 E6 ~' ?) U' y8 k4 T
  117.     if (!glfwInit()) {" Q& z5 e6 M6 ?" i" }) G; s8 W
  118.         fprintf(stderr, "Failed to initialize GLFW\n");# Q2 V; `0 u. o9 V5 x' D8 Z
  119.         return -1;
    5 u; R0 [  `* ^/ Z" C
  120.     }9 D0 V1 _6 U, p/ K: @- L

  121. : q0 w, S8 j* o! n
  122.     GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL Text Rendering", NULL, NULL);
    - L& s) {% D- [, ]; N* s. j
  123.     if (!window) {* N# i- u! _3 L
  124.         fprintf(stderr, "Failed to create GLFW window\n");2 T$ `( H/ q1 @. v2 M8 ^- I
  125.         glfwTerminate();
    ( H! A6 v; F0 Z- v
  126.         return -1;" x5 x: j8 u+ W# I) x
  127.     }
    : o6 H! b' O* y4 W' g/ N
  128. / d. \8 L, d0 l+ j- f; T) t
  129.     glfwMakeContextCurrent(window);9 E! \2 t% `& \4 y
  130.     glewInit();
    $ S8 [1 Y7 W2 n) W9 b5 b
  131. 2 X  u% F0 Q* Y7 C. I0 [! f- v
  132.     initialize();
    $ K, ^+ \. t1 H9 n2 w

  133. & E& W+ y3 W1 Y
  134.     while (!glfwWindowShouldClose(window)) {1 \5 L3 F" h. O$ K# H
  135.         glClearColor(0.0f, 0.0f, 0.0f, 1.0f);& {' I$ q0 `' [
  136.         glClear(GL_COLOR_BUFFER_BIT);1 s6 o; q. }9 T: Q3 }9 E

  137. ' k" [5 T: m8 l* x  d
  138.         glColor3f(1.0f, 1.0f, 1.0f);
    ) j, h0 L- E+ p, R7 k
  139.         renderString("Hello, OpenGL!", 100.0f, 100.0f);% Q9 x0 d  I0 a" h- h% o
  140. * e2 T6 g  d* H3 `) k* I
  141.         glfwSwapBuffers(window);
    " i& r. I! e( C
  142.         glfwPollEvents();9 W  j# e. U4 J/ ?6 g2 p9 F
  143.     }
    4 J8 w9 F) f7 p% ^, M8 F

  144. , `# _! L' h$ a. P1 ^# k4 t4 D3 O
  145.     FT_Done_Face(face);, v5 z/ ^+ `6 b/ a
  146.     FT_Done_FreeType(library);
    9 I$ ~2 ]: O& C5 }, W& y7 z6 [

  147. ) b: }! r4 K' y
  148.     glfwTerminate();
    6 ?3 [* C' E8 X3 Z2 ]* `" G

  149. + C. v  H( p; T0 c$ C% ^
  150.     return 0;5 z, x4 f: \' ~0 _
  151. }7 T) `! L5 K% Q6 ?7 R% l& q' j
复制代码

# ]: N$ n! b& n/ f
) u/ B- T1 r3 z5 Y9 g
分享到:  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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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