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

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

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

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

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

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

本帖最后由 shane007 于 2023-9-6 15:32 编辑
# u; M+ k2 h/ \7 Q
& h% n0 U- H! w* f9 E0 I以下是一个用来做参照的opengl显示字符串的代码,使用了freetype库。
$ {1 t3 n* T: [0 ~2 K1 [6 I本代码经过分析以及改写之后,将取代游戏原有的显示函数。
) P% o7 J8 ~$ p, ]% k  w5 T- [! }) @' t
代码详细说明如下# m- A+ g% ]8 G
3 O/ u6 t  l7 V* S. W
  1. 在上述 renderString 函数中,我们有以下关键部分的解释:
      Q8 B3 {: @; e4 K( }- \
  2. 8 ^7 ?7 @9 N7 H! ~0 h7 S% x
  3. glBindTexture(GL_TEXTURE_2D, fontTexture);:将字体纹理绑定到当前的OpenGL上下文。这是因为我们要使用 fontTexture 中存储的字形位图数据进行渲染。7 w! }  k4 O7 L% w  ?8 T

  4. ' b' M+ f( ~  e
  5. glEnable(GL_BLEND); 和 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);:启用混合模式以处理字符的透明度。混合模式通过 glBlendFunc 设置,这里使用了常见的源和目标因子来实现源颜色与目标颜色的混合,从而实现透明效果。
    / x. t+ n' f  i% D4 a

  6.   I; G1 W  f! [/ s
  7. glBegin(GL_QUADS); 和 glEnd();:在这两个函数之间的代码用于指定字符的四边形顶点,以便在OpenGL上下文中绘制字符。( M* ?9 ^$ x" `* q9 M* ]' @- X* N& O

  8. 0 @2 ^. Q  }" o: o$ @+ g  B  z
  9. for (const char* p = text; *p; p++) { ... }:这个循环遍历传递给函数的字符串 text 中的每个字符,然后为每个字符执行以下操作:
    & l+ b/ ^& P" @. |' X; S

  10. $ v! v2 {8 P! I* j
  11. FT_Load_Char(face, *p, FT_LOAD_RENDER);:使用FreeType加载字符的字形数据,包括轮廓和位图信息。加载后,可以从 face->glyph 中访问该字符的字形数据。/ W" A! k/ s, e0 }

  12. ' ~; r9 n: X! k0 q) O$ w
  13. 计算字符在屏幕上的位置和大小,包括 xpos(x坐标)、ypos(y坐标)、w(宽度)和 h(高度)。
      L* ?7 I4 R6 o2 b% [5 Q

  14. 1 r& A: V% g+ @( C' m# g& z6 i( K
  15. 使用 glTexCoord2f 和 glVertex2f 来指定字符的纹理坐标和顶点坐标,以创建一个四边形。这四边形将字形的位图数据绘制到屏幕上的指定位置。
    % ]; [! @; Q8 \& ]# v

  16. / l7 ?- y. N2 d8 o+ P! H
  17. x += (face->glyph->advance.x >> 6);:更新 x 坐标,以便将下一个字符紧密排列在当前字符的后面。face->glyph->advance.x 包含字符的横向位移信息,>> 6 是用来将其转换为像素单位的操作。0 S7 q3 |: W2 V1 b" S/ s' Y; \
  18. 2 O) i; F# W1 G$ S: h
  19. 最后,glDisable(GL_BLEND); 用于禁用混合模式,以免影响后续的绘制操作。
    $ P! R& ~3 L9 F5 f6 a6 n- z5 F
  20. 0 t# g  P' B  [7 e5 a$ o9 C4 R
  21. 总之,renderString 函数的作用是将传递给它的字符串中的字符一个接一个地绘制到OpenGL上下文中,使用FreeType加载的字形数据和字体纹理来实现文本渲染效果。渲染过程涉及到字符的位置计算、纹理坐标的设置以及混合模式的启用和禁用,以确保字符在屏幕上正确显示。; W4 Z' h% S; u* ?0 K3 ~
复制代码

6 n& `' ]7 |/ X
5 B. }" \9 n% S
  1. 字形数据处理的关键函数之一。以下是 FT_Load_Char 函数的详细解释:, d2 L2 I9 U1 O  \; {

  2. 3 k  a  y! J2 W' m9 \8 }, e3 L6 u. ]
  3. 参数:/ x2 ?9 z! o, s  Q

  4. 8 s: ?& R9 X, K# f/ U
  5. face:一个指向已经打开的字体文件的 FT_Face 结构体的指针。FT_Face 包含了字体的各种信息,包括字形数据。$ Y, V" [9 k4 c+ O5 x( L
  6. char_code:要加载的字符的Unicode编码值。您需要传递字符的Unicode编码作为此参数,以指定要加载的字符。4 b, P" L( E. t' f7 T( x9 T
  7. load_flags:一个用于控制字形加载选项的标志位。您可以使用这些标志位来控制加载的方式,例如是否要加载字形的轮廓数据、是否要加载字形的位图数据等。
    9 a/ v( j! G" Y8 ]
  8. 功能:- X; ^' \0 e# U1 W$ {

  9. % r9 ~, M- N) U6 b
  10. FT_Load_Char 函数的主要功能是加载指定字符的字形数据。0 E- `, M# B2 T% S& L/ o9 R
  11. 如果成功,它将在 FT_Face 结构体中的 glyph 字段中填充有关字符的字形信息。1 k6 O/ k) Z6 c0 Y" C
  12. 这包括了字符的轮廓数据、位图数据、宽度、高度、位图偏移等等,具体取决于传递给 load_flags 参数的设置。# Y3 Q; A" z1 b6 z. ~9 Q; f9 Q
  13. 使用示例:
      a4 l% k- I- T" e! i, F! g
  14. + e* D" z3 X( t2 l: t6 p
  15. c/ e) Q' n% s* f
  16. Copy code
    7 U0 g+ B$ p+ W0 P0 l' Y0 v% [
  17. FT_Load_Char(face, 'A', FT_LOAD_RENDER);
    * ]: S( z, ^3 z+ ^* [5 J/ h
  18. 这个示例会加载字体中字符 'A' 的字形数据,并将其渲染到位图中。FT_LOAD_RENDER 标志告诉FreeType要渲染字符的位图数据。加载后,您可以在 face->glyph 结构体中找到有关 'A' 字符的相关信息,包括位图数据、宽度、高度、位图偏移等等。
    . r4 L7 F5 B4 Y. x. R2 z- s

  19. . q! ?! X) C0 @( }0 w
  20. 错误处理:
    4 H6 s' L# G/ v& W( |( z4 v, R2 p

  21. + M2 A2 e, K6 C/ g& x& z- o3 q
  22. 如果加载失败,FT_Load_Char 函数可以返回错误代码。您应该检查返回值以进行错误处理,并根据需要采取适当的措施,例如跳过加载失败的字符或终止渲染过程。0 a% G$ ]4 J# t
  23. 总之,FT_Load_Char 函数是FreeType库中用于加载指定字符的字形数据的重要功能之一,它使您能够准备要渲染的字符数据,以便在文本渲染中使用。加载的数据可以包括字符的轮廓信息(矢量数据)和位图信息,具体取决于 load_flags 参数的设置。这个函数在字体渲染中起到关键作用,以便将字符正确呈现在屏幕上。
复制代码
+ a5 X& b& C2 F* E
6 o: p: D9 b# ^5 ^; J: ]
代码! V1 s: ^4 M0 c6 x) R: L

) @! A7 n9 N8 D9 V' g. A6 l
  1. 9 @# D" n# @; F7 b" N
  2. , g/ T& v- B; L( J  t, C1 N
  3. ' O  I3 s' G* K
  4. #include <stdio.h>. R9 X3 p1 I, ^
  5. #include <stdlib.h>
    9 n2 X0 c1 f+ y) n& r
  6. #include <GL/glew.h>
    & ?% h2 |7 ]9 w
  7. #include <GLFW/glfw3.h>; I5 p  {3 M6 |) D1 N. m' g
  8. #include <ft2build.h>* y" j) H" M7 b. u* h) P1 Q! K
  9. #include FT_FREETYPE_H
    9 H9 s+ A0 |2 f' q/ O
  10. 4 }. \! ?2 d: S( s
  11. // 定义字形数据的字节数组1 ^- s' g1 [6 {; ~2 F3 Q
  12. unsigned char fontData[] = {2 z5 A6 @1 \" D* U7 H# I
  13.     // 字形数据的字节表示
    8 v8 q* b  J) \
  14.     // 例如,这里可以包含字母、数字和符号的字形数据
    , r" Y! h: M# K% q" X
  15. };
    ) ?. Y  }0 T" q+ A% ]) S

  16. 8 b9 ?' ~$ p" D8 c; o0 Y# X
  17. FT_Library library;
      U* M. k  X9 u7 M0 p5 O$ f# Z
  18. FT_Face face;1 f' t% W( i1 c! y, U; t/ b
  19. GLuint fontTexture;/ n1 {( N* w: h& H1 k; K, a
  20. . f& L5 h; y' r; D) q
  21. // 初始化FreeType库和OpenGL
    8 j. ]3 t& ?0 H& g
  22. void initialize() {6 [4 [& }& M0 v) f0 |! j
  23.     if (FT_Init_FreeType(&library)) {
    . h$ e2 Z$ g/ v- e; n; b
  24.         fprintf(stderr, "Failed to initialize FreeType\n");& P. G8 w: f$ a' h+ Q
  25.         exit(EXIT_FAILURE);
    9 B) g( @3 D8 F% }& F6 K) s
  26.     }$ H. o# f- P0 r/ a7 V* U2 S4 B# b
  27. 5 e5 y7 n: F0 V
  28.     if (FT_New_Memory_Face(library, fontData, sizeof(fontData), 0, &face)) {) _2 a) x# V. a2 m; C
  29.         fprintf(stderr, "Failed to create a FreeType font face\n");
    + F! h, `4 \- z; h1 j- o
  30.         exit(EXIT_FAILURE);/ K4 Y/ D3 p# `2 E, x5 n* w. A& _/ s
  31.     }4 R8 z8 Z: O( }/ i5 U) w& R6 A
  32. . }3 O$ w5 _; w6 X7 i$ B$ h: E. Y, w0 g
  33.     if (FT_Set_Pixel_Sizes(face, 0, 48)) { // 设置字体大小
    2 {, k* e8 V' K) q& ^. n/ H( G
  34.         fprintf(stderr, "Failed to set font size\n");
    - _7 d2 R) N0 A  j) Z7 ~
  35.         exit(EXIT_FAILURE);
    0 n3 C+ ~2 t% S1 `) X5 B3 {- a
  36.     }( S2 f1 |3 G/ s

  37. . q1 D; G" C  X0 Y3 N  Z7 U2 S
  38.     glGenTextures(1, &fontTexture);' I& p; S5 @( v" `  R3 t4 m7 J# a
  39.     glBindTexture(GL_TEXTURE_2D, fontTexture);
    ) u1 o9 Z  e# G9 g  n, O, ]
  40.     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);8 i( S: ?  y- ]% v) N+ b

  41. 3 q4 {) m! M3 @+ u. b$ K
  42.     // 将字形数据传递给OpenGL纹理
    / @. D0 ~. |8 H% z$ p
  43.     for (int i = 0; i < 128; i++) {  N) N! G7 N+ U' ~) L  P3 z
  44.         if (FT_Load_Char(face, i, FT_LOAD_RENDER)) {
    ; o' o" v+ q2 s
  45.             fprintf(stderr, "Failed to load glyph for character '%c'\n", i);
    2 L1 K4 @9 F' e7 Q( z8 ^
  46.             continue;
    & y6 d! l* A. \4 l
  47.         }& F/ `- b/ C  F) [. H$ t& T# D5 I$ D
  48. ; \4 Y/ j- T  W, H4 x
  49.         glTexImage2D(
    / h' [2 ]5 [- Q& R( t8 ?9 g
  50.             GL_TEXTURE_2D,+ l* q. V. u4 U; r
  51.             0,2 {8 R  n7 }! _8 l' _, g' c
  52.             GL_RED,+ Q8 Q& V" e  U" ^
  53.             face->glyph->bitmap.width,
    ) _- |1 }+ \) d/ l. S0 |6 O
  54.             face->glyph->bitmap.rows,: o0 n# U1 o: `& Q
  55.             0,
    2 D# C3 t% m* {
  56.             GL_RED,
    9 o0 j+ y/ _' U1 u8 ], t1 f
  57.             GL_UNSIGNED_BYTE," Y7 d* S* \0 @  n( V! B4 Q6 e
  58.             face->glyph->bitmap.buffer0 I! d4 c& v  E  k4 k6 o
  59.         );
    * X4 }' n0 x% ^8 G
  60. 5 p! [1 p: B( w( B8 ?
  61.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    # t. x& I1 a$ n' [0 P
  62.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
      Z5 H/ o3 i  V5 b' j! |
  63.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);! y3 `& V% t3 G; |
  64.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    : L4 i* z0 ~" p4 @  j2 p
  65.     }
    4 h* |) d* {2 o7 h- a
  66. }: F, G! k( {; [5 a; X& @+ ?8 v
  67. 3 _8 n; L) F, F0 i* G2 F
  68. // 渲染字符串
    % N/ K) q/ ~* p2 r5 T3 U  z
  69. void renderString(const char* text, float x, float y) {4 J8 J1 d  Z/ f2 t* l
  70.     glBindTexture(GL_TEXTURE_2D, fontTexture);' _* a- }! ~  C  r4 W1 {
  71. 4 t- k" ~( ^9 Y
  72.     glEnable(GL_BLEND);
    " C- a. c! t* ?! p7 F1 |) m* i  e
  73.     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);; _# ^+ C; Y. V; z' o' I+ h

  74. / {( H% Q, a2 X+ P7 [; @3 f1 D
  75.     glBegin(GL_QUADS);
    " z7 T. z, o6 @8 z: e/ l; ?0 R! w
  76.     for (const char* p = text; *p; p++) {* P0 j; j# X1 D5 c
  77.         FT_Load_Char(face, *p, FT_LOAD_RENDER);
    3 _. ^6 ]5 d1 P" I" Q" b5 |

  78.   Y* V; D, `2 \" q( i. D9 V' F
  79.         glTexImage2D(
    5 t/ ^. a, t% X" t- i! K2 D2 U; m
  80.             GL_TEXTURE_2D," F" Y1 W! ?0 \
  81.             0,. {; L& i& F7 ~3 {5 m- L  W
  82.             GL_RED,
    : c/ H! M# X  N- X" z
  83.             face->glyph->bitmap.width,
    2 F3 R' N) r: D
  84.             face->glyph->bitmap.rows,
    , O& r* u/ V! _
  85.             0,
    2 {3 O+ \9 u, K0 z
  86.             GL_RED,. F9 d' C+ S1 \% |) C* i
  87.             GL_UNSIGNED_BYTE,+ W( B4 {/ N8 U, W5 N
  88.             face->glyph->bitmap.buffer  S$ d2 R! K8 D
  89.         );5 A5 O( Q5 Q3 [% m* N4 y. V

  90. / o# |( d2 f. {, y
  91.         float xpos = x + face->glyph->bitmap_left;
    / v4 w, V" L& ~. r9 |' u
  92.         float ypos = y - (face->glyph->bitmap.rows - face->glyph->bitmap_top);+ p, C2 E- O# W# n5 `& q9 W: o
  93. . h3 ^( C" b  a" o2 R% V, @
  94.         float w = face->glyph->bitmap.width;
    $ Z1 P- |1 W) \9 [1 D
  95.         float h = face->glyph->bitmap.rows;) _+ d+ z6 b" Y. R. ~

  96. & p5 K/ Y+ g( l! O9 D
  97.         glTexCoord2f(0, 0);2 b( F5 _3 H. M, a
  98.         glVertex2f(xpos, ypos);
    1 q1 o8 U% v1 F& b# Z
  99. 0 F+ B/ e9 S5 Y  h- i& t
  100.         glTexCoord2f(0, 1);
    8 B2 E! z: w$ ]% ^0 q: N' f2 q
  101.         glVertex2f(xpos, ypos + h);
    - g# Q1 v; P) k$ s! C

  102. ! L& M1 e# m; f& V% l7 v: S
  103.         glTexCoord2f(1, 1);
    * g# J7 v! m; ~  q7 G/ A
  104.         glVertex2f(xpos + w, ypos + h);0 e$ j5 X0 e) i: J
  105.   I, C' v& M( D2 M5 H
  106.         glTexCoord2f(1, 0);
    3 \  e( {5 Q6 g% }, j
  107.         glVertex2f(xpos + w, ypos);0 [1 a! N. ~+ N" `3 k# W  o% j

  108. 2 [$ a% ^2 ]/ c) }
  109.         x += (face->glyph->advance.x >> 6); // 字符之间的间距6 D) C5 ~8 u  N
  110.     }" {/ t; s) K7 V1 V; p3 v' P' u* r
  111.     glEnd();
    # a$ ^6 Q7 D4 T5 S7 Y" h8 p3 Y

  112. 5 h9 V0 B# s+ Y! q! |* J
  113.     glDisable(GL_BLEND);
    8 Q( `4 @" c/ j; S& f
  114. }
    4 [' n8 B7 r2 s- ^

  115. ( s0 `) }( s$ I
  116. int main() {
    8 d" F% y) N3 |( Y7 _- e% X
  117.     if (!glfwInit()) {2 ?+ j/ K9 e/ ]: U. N' M$ C4 h/ k! s, n
  118.         fprintf(stderr, "Failed to initialize GLFW\n");) m8 g3 x8 k  q
  119.         return -1;5 b  k, w+ k" i
  120.     }; [3 L! B9 n# g; p
  121. 5 B+ j" c2 T1 W9 H, Q  u
  122.     GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL Text Rendering", NULL, NULL);
    - [1 ~/ m7 @# r0 J
  123.     if (!window) {" R9 T% C( d2 D2 }" @: E6 g
  124.         fprintf(stderr, "Failed to create GLFW window\n");' r5 |! ~- l4 ]$ Y
  125.         glfwTerminate();
    ! A0 U$ Q& ?4 L* o, S2 @% p
  126.         return -1;
    , K4 u* `% s, D  h5 U
  127.     }2 [' J2 u% a: _( \  q* S

  128. ( O9 ^" i3 Q) J. Y2 V
  129.     glfwMakeContextCurrent(window);
    0 C2 x1 B- y; l6 S+ U
  130.     glewInit();+ m" A7 i# d) a2 ^+ V. b# D& F9 ?
  131. 0 t/ c2 ]* z8 ?: Y
  132.     initialize();
    . z9 h/ d+ e: Y
  133. 3 V1 L' y7 M8 C. h" D) s
  134.     while (!glfwWindowShouldClose(window)) {
    6 |. A9 r% r" h, C9 ]
  135.         glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    * u% W( t4 }4 s: M8 B5 z
  136.         glClear(GL_COLOR_BUFFER_BIT);1 B( O& O2 E& h- o2 _

  137. $ F1 H/ j! M: q/ @0 |" g3 L
  138.         glColor3f(1.0f, 1.0f, 1.0f);( z8 x& \. ?' a% ^* n9 e
  139.         renderString("Hello, OpenGL!", 100.0f, 100.0f);
    0 F2 `( m# {. M1 Z

  140.   g, N/ q7 {* [2 x/ T) t' u
  141.         glfwSwapBuffers(window);
    7 R" r% X, X4 ]; W, Q: H
  142.         glfwPollEvents();' Q  D; h- V% z
  143.     }0 g& x9 m, C, c+ `
  144. 5 N  \. b1 Y+ ~: q3 x
  145.     FT_Done_Face(face);
    ! s, M( K. A4 L4 y- C5 A
  146.     FT_Done_FreeType(library);
    * o. `4 o! Y& E3 N5 X- |) C! X

  147. ( W4 P2 w6 \$ O0 p! ^/ i. h
  148.     glfwTerminate();+ X; M( n! g( R! z9 r

  149. & @! D1 U3 L- s0 t7 q  y
  150.     return 0;% `: s( ~. z) |
  151. }
    7 U6 g) Q$ g2 b& s1 R4 w5 X8 d6 R
复制代码

0 }/ o( g1 Q" [" s
7 _8 z+ L! p' [: Q
分享到:  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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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