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

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

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

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

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

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

本帖最后由 shane007 于 2023-9-6 15:32 编辑 % V& B( f2 c0 p8 I/ \6 r/ F

* C+ S7 q. M7 U7 h: k- D6 e以下是一个用来做参照的opengl显示字符串的代码,使用了freetype库。' K+ Q5 j( e0 I8 `1 e" }
本代码经过分析以及改写之后,将取代游戏原有的显示函数。$ q5 V) r& B: L& x- }
1 l' R8 M' r% I
代码详细说明如下$ @6 ?3 i) M# k! W5 D
% n" s0 f+ ^* Y* H6 q$ i
  1. 在上述 renderString 函数中,我们有以下关键部分的解释:
    + g) v0 z0 r5 }( P
  2. 3 b" b. c* d8 _4 B  l  @
  3. glBindTexture(GL_TEXTURE_2D, fontTexture);:将字体纹理绑定到当前的OpenGL上下文。这是因为我们要使用 fontTexture 中存储的字形位图数据进行渲染。6 r, L# M  d' x6 L: A) i6 p: H
  4. % U) m8 N; u! B
  5. glEnable(GL_BLEND); 和 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);:启用混合模式以处理字符的透明度。混合模式通过 glBlendFunc 设置,这里使用了常见的源和目标因子来实现源颜色与目标颜色的混合,从而实现透明效果。
    . m7 q% C- b8 J# C; c5 `' W5 r8 z
  6. 0 ?$ |/ c% m1 e! o9 K+ D3 x
  7. glBegin(GL_QUADS); 和 glEnd();:在这两个函数之间的代码用于指定字符的四边形顶点,以便在OpenGL上下文中绘制字符。/ ^5 P% P. `  `
  8. # `, ?9 [' \  O- a! w* j) L( K
  9. for (const char* p = text; *p; p++) { ... }:这个循环遍历传递给函数的字符串 text 中的每个字符,然后为每个字符执行以下操作:) i! G+ D) e, X- E( h1 V' z

  10. : V7 z0 Q7 g" L2 t! a. B
  11. FT_Load_Char(face, *p, FT_LOAD_RENDER);:使用FreeType加载字符的字形数据,包括轮廓和位图信息。加载后,可以从 face->glyph 中访问该字符的字形数据。/ R2 X, N; \& n. |$ ?

  12. ) j2 P" s$ x7 K. _
  13. 计算字符在屏幕上的位置和大小,包括 xpos(x坐标)、ypos(y坐标)、w(宽度)和 h(高度)。
    " ^4 U/ P$ }6 ~* k. a
  14. 1 l* Z5 ~: `# w  A1 p
  15. 使用 glTexCoord2f 和 glVertex2f 来指定字符的纹理坐标和顶点坐标,以创建一个四边形。这四边形将字形的位图数据绘制到屏幕上的指定位置。$ h+ U, L: h, T( o
  16. * ]( t) I  ^1 C! f$ J9 n
  17. x += (face->glyph->advance.x >> 6);:更新 x 坐标,以便将下一个字符紧密排列在当前字符的后面。face->glyph->advance.x 包含字符的横向位移信息,>> 6 是用来将其转换为像素单位的操作。; O5 m7 J+ q5 G/ \# {' d
  18. ) R. k- o; c* e
  19. 最后,glDisable(GL_BLEND); 用于禁用混合模式,以免影响后续的绘制操作。
    % ?$ E( R- U7 K

  20. 1 a/ K/ I9 z5 m; R, Q# r( j
  21. 总之,renderString 函数的作用是将传递给它的字符串中的字符一个接一个地绘制到OpenGL上下文中,使用FreeType加载的字形数据和字体纹理来实现文本渲染效果。渲染过程涉及到字符的位置计算、纹理坐标的设置以及混合模式的启用和禁用,以确保字符在屏幕上正确显示。
    ( {" b) R; k$ y, i
复制代码
  a& M) i; b  k
& O$ \, s( R: r$ I- p8 l5 G4 ?
  1. 字形数据处理的关键函数之一。以下是 FT_Load_Char 函数的详细解释:
    1 w- s& H9 `' p* R3 Y
  2. / W5 t$ w9 V+ ]) H* ~; b" P
  3. 参数:1 s% S. i9 b# k

  4. / C- |5 C6 z  G9 B
  5. face:一个指向已经打开的字体文件的 FT_Face 结构体的指针。FT_Face 包含了字体的各种信息,包括字形数据。
    2 C- O: g* w0 |! s% U2 e
  6. char_code:要加载的字符的Unicode编码值。您需要传递字符的Unicode编码作为此参数,以指定要加载的字符。- P6 L6 E8 c; _( Z5 o' `9 n
  7. load_flags:一个用于控制字形加载选项的标志位。您可以使用这些标志位来控制加载的方式,例如是否要加载字形的轮廓数据、是否要加载字形的位图数据等。
    # d! h- ?! k) G; I/ [( I
  8. 功能:; ~/ p3 K' r/ a6 F# e) X, ^6 n% Z
  9. 7 t6 B3 B$ m1 O1 }
  10. FT_Load_Char 函数的主要功能是加载指定字符的字形数据。4 U4 {/ D. p& D% F3 y4 c; }6 p+ z
  11. 如果成功,它将在 FT_Face 结构体中的 glyph 字段中填充有关字符的字形信息。1 g7 o3 @# w* Z
  12. 这包括了字符的轮廓数据、位图数据、宽度、高度、位图偏移等等,具体取决于传递给 load_flags 参数的设置。
    ' K. r! u  Q- D9 `7 N$ U$ z
  13. 使用示例:
    7 X& O& q+ D* R* J* r

  14.   J& Q" C; ?0 h: ?' c
  15. c' W$ ^; F2 j7 F/ d3 q" e% v3 k* r
  16. Copy code' [$ `6 @3 [5 y- G
  17. FT_Load_Char(face, 'A', FT_LOAD_RENDER);
    . p$ R& @7 `' f4 s. T
  18. 这个示例会加载字体中字符 'A' 的字形数据,并将其渲染到位图中。FT_LOAD_RENDER 标志告诉FreeType要渲染字符的位图数据。加载后,您可以在 face->glyph 结构体中找到有关 'A' 字符的相关信息,包括位图数据、宽度、高度、位图偏移等等。
      e) G$ c4 Q: `6 X3 Q3 I6 ?; K

  19. ) Z' y& D+ C& b, j5 C8 E: X* W4 A
  20. 错误处理:9 j+ V" y, s  Y' V

  21. - g# M$ z/ \; \( a1 r3 U
  22. 如果加载失败,FT_Load_Char 函数可以返回错误代码。您应该检查返回值以进行错误处理,并根据需要采取适当的措施,例如跳过加载失败的字符或终止渲染过程。
    3 O/ ^8 M" L; M# O- a& M
  23. 总之,FT_Load_Char 函数是FreeType库中用于加载指定字符的字形数据的重要功能之一,它使您能够准备要渲染的字符数据,以便在文本渲染中使用。加载的数据可以包括字符的轮廓信息(矢量数据)和位图信息,具体取决于 load_flags 参数的设置。这个函数在字体渲染中起到关键作用,以便将字符正确呈现在屏幕上。
复制代码
( L% g% U6 D0 b' x) S2 L

3 L$ V! w0 s: I: T3 `* \1 H代码/ V9 U" N5 l# M& D

9 G4 ?+ n/ {/ a, P4 Z4 H

  1. & n6 D1 H- K# o+ F, ~% t

  2. 3 X/ k1 p. y% g5 p
  3. ! G0 w  z, j% f  T
  4. #include <stdio.h>* y3 K$ o5 _9 }* ~# C  j
  5. #include <stdlib.h>
    5 C4 d: m: G0 @* L% H
  6. #include <GL/glew.h>
    ) F) s5 v  f+ G  S5 q0 e2 \( B2 G
  7. #include <GLFW/glfw3.h>
    * N' \/ T! O5 t4 |5 x) N+ v
  8. #include <ft2build.h>% K8 U9 h0 b1 `# Z; L
  9. #include FT_FREETYPE_H0 ?, I0 N' w8 R
  10. # Y0 i$ }" I, _' m) b* d' i, y
  11. // 定义字形数据的字节数组
    : j- U8 a5 @; q& A( ~- i$ f$ o
  12. unsigned char fontData[] = {
    & y4 u4 ]6 w7 ~$ Q+ r
  13.     // 字形数据的字节表示
    8 k0 }0 g8 n/ x% }
  14.     // 例如,这里可以包含字母、数字和符号的字形数据. Z# a- F/ F6 E# O7 M; S" c
  15. };
    9 E3 s8 q) b/ A
  16. / y' O( w7 e* K- D
  17. FT_Library library;8 i, ]9 z& e9 E1 C  ?5 \7 V3 |
  18. FT_Face face;
    2 r. K2 Y, b8 C4 N8 G: S
  19. GLuint fontTexture;
    0 w1 ]8 h6 z0 h: o4 x" @7 D' c' z
  20. 5 G* k, h/ M4 B9 J- p$ O
  21. // 初始化FreeType库和OpenGL
    9 w7 o, U: q+ p' H0 j& O  G+ R
  22. void initialize() {
    + ^: R9 U1 k- ^( t( t
  23.     if (FT_Init_FreeType(&library)) {
    & Y# A0 s0 a  C: E9 y
  24.         fprintf(stderr, "Failed to initialize FreeType\n");0 Y* d- Z% P9 _1 O4 V* b! J! C% R+ K
  25.         exit(EXIT_FAILURE);
    9 ~6 Y# f) j+ ?# Q3 B4 ?/ E
  26.     }
    / ?5 q. i- f, n2 c! j% O2 Z

  27. 2 P: O9 T; o& m+ J. K" c, i( Z/ P
  28.     if (FT_New_Memory_Face(library, fontData, sizeof(fontData), 0, &face)) {
    4 A: |% p) D: b8 S( n/ v
  29.         fprintf(stderr, "Failed to create a FreeType font face\n");# U& A  C# ~5 c- R! l+ M
  30.         exit(EXIT_FAILURE);; ?+ }* x; c5 X2 h, ?
  31.     }2 F, s* l/ O% m! U0 U0 U

  32. 6 s- ]8 G! |8 |) P4 y! K  A. i5 H
  33.     if (FT_Set_Pixel_Sizes(face, 0, 48)) { // 设置字体大小
    ! i2 w3 s) Z) \3 Q9 g. A/ Y! W7 N
  34.         fprintf(stderr, "Failed to set font size\n");5 e- T* w/ Q2 k. ^$ }
  35.         exit(EXIT_FAILURE);5 m' [7 e& r5 w
  36.     }' g$ D' _% h& L" {& L

  37. $ H! d8 T4 g: r8 L5 \  R
  38.     glGenTextures(1, &fontTexture);! i/ U% H7 F; D
  39.     glBindTexture(GL_TEXTURE_2D, fontTexture);" N- T- S! i6 t3 I" m
  40.     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);7 P: r) l7 W4 Y
  41. 7 O1 ^1 X6 T( u$ w( B- ^
  42.     // 将字形数据传递给OpenGL纹理( l- u8 H# W4 q
  43.     for (int i = 0; i < 128; i++) {
    - P) a$ W8 f" i* p' c
  44.         if (FT_Load_Char(face, i, FT_LOAD_RENDER)) {* T. ?' Q; y* g) |6 j/ H2 e
  45.             fprintf(stderr, "Failed to load glyph for character '%c'\n", i);3 L2 a* o9 r/ G; p
  46.             continue;& f  C5 w; D4 y1 Z" a- `! X/ t
  47.         }: o; Q) L& }  g0 E

  48. & |4 @* K& M  d0 D, e$ K
  49.         glTexImage2D(
    8 `) i" I" ^) b& \
  50.             GL_TEXTURE_2D,3 \6 u8 u' C9 z. C, r6 K
  51.             0,
    ; S7 C6 n  H6 ?  c; i# m
  52.             GL_RED,
    / h/ l4 {( ?( f; J, D% v
  53.             face->glyph->bitmap.width,* p5 M  }% E1 U2 _, }# p3 a8 O
  54.             face->glyph->bitmap.rows,
    8 M' k  t& I7 H8 h$ x' e" m7 J% @
  55.             0,
    $ `) v5 ~" t4 t, R( \8 r  `8 p- l
  56.             GL_RED,
    . X4 ~1 s. A7 I" o
  57.             GL_UNSIGNED_BYTE,
    / G$ O; N/ v! q& D0 m
  58.             face->glyph->bitmap.buffer
    9 j5 Y! j' d  U, k; b' P
  59.         );. F) `- T  T1 r; F6 c1 ?0 J' k

  60. + U$ A3 P/ x7 |7 M7 [9 t% ^( L1 s
  61.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    0 r  x1 f6 J$ g
  62.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    ) e6 E9 K8 F1 f1 ?/ p9 Q6 H( O
  63.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);& R* K# I5 X( a8 v0 g5 ~8 C
  64.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);4 N& |5 B! O& s1 g# Z. `
  65.     }. U" d' D* ~# i& w: t! u
  66. }' K% a9 I7 A6 s6 l) n# E- Q& v; N  ]6 W- V

  67. $ o: G. d" r7 E
  68. // 渲染字符串$ h) |$ O% B# j" i
  69. void renderString(const char* text, float x, float y) {
    2 a0 V' A, R2 {) k4 N  `
  70.     glBindTexture(GL_TEXTURE_2D, fontTexture);! a" A$ j/ m+ \! H7 P7 V; C6 H$ A

  71. # J& L+ d0 J! X. m/ T
  72.     glEnable(GL_BLEND);0 q. ~1 `& c% {. R6 d
  73.     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);: \3 k3 W! l3 Q! m* |4 E

  74. - T' u+ o; M) y, T; R
  75.     glBegin(GL_QUADS);/ @8 x: [+ [* U7 _4 J: C# r; y7 o
  76.     for (const char* p = text; *p; p++) {
    ! K4 o1 |! @7 Y! M0 T% }3 p# h) b' d
  77.         FT_Load_Char(face, *p, FT_LOAD_RENDER);, K# S5 x/ u- q+ F' o; s
  78. 9 W' ]% c7 G' F$ Q' {  W( f5 x$ q
  79.         glTexImage2D(
    1 R, j4 g3 `$ u
  80.             GL_TEXTURE_2D,
    $ n% Q) _, a1 R& g
  81.             0,/ a' o7 t- j4 s9 R8 d8 e$ U& e& T
  82.             GL_RED,
    % W: O, H9 V% U
  83.             face->glyph->bitmap.width,6 |" X- F- D6 V7 b: p6 W4 y; S
  84.             face->glyph->bitmap.rows,
    . u* [1 m8 ~0 L& [
  85.             0,
    7 E8 ~* y# P7 F1 z
  86.             GL_RED,
    9 T0 L3 y& Z( Y0 U8 V# |
  87.             GL_UNSIGNED_BYTE,0 Z! l. p. v' x, B' b( f6 B
  88.             face->glyph->bitmap.buffer
    2 P3 `2 y$ D" {8 ~6 J
  89.         );
    & o2 v/ t0 h* |) I, C: s. }( E0 n
  90. 8 e9 E# v! T# r' l% k
  91.         float xpos = x + face->glyph->bitmap_left;
      T! Z0 I$ J# j3 {% T
  92.         float ypos = y - (face->glyph->bitmap.rows - face->glyph->bitmap_top);) S/ Q: O0 i1 b' P! D& n

  93. : H( Z) I. {) c& s
  94.         float w = face->glyph->bitmap.width;8 N% c6 x- I  W4 `  M3 i- V' M2 P
  95.         float h = face->glyph->bitmap.rows;
    7 g4 h1 n% d) K2 E( u

  96. 2 F7 D  B9 E& o8 [
  97.         glTexCoord2f(0, 0);5 W* F3 V' ?, |* ]6 q
  98.         glVertex2f(xpos, ypos);
    ; q0 r/ Q% l5 ^: O6 @' j
  99. " i3 `6 C3 d8 a, Q! F! a
  100.         glTexCoord2f(0, 1);
    7 `0 m+ _  `4 G3 k" F( O
  101.         glVertex2f(xpos, ypos + h);6 k9 \- y- v! m! B% u. |- C
  102. 3 Z; K* F, ~# Q4 U8 \5 o
  103.         glTexCoord2f(1, 1);* w; O  v; j5 I
  104.         glVertex2f(xpos + w, ypos + h);/ N; s% c3 \3 C- m/ G

  105. ' Y: D. q# i* C9 J" g
  106.         glTexCoord2f(1, 0);
    8 z8 w3 h) V4 f& f- l8 E  {5 l
  107.         glVertex2f(xpos + w, ypos);
    4 n/ w* U+ l. B! E5 i0 O

  108. " L0 ?" ~  A  R9 g
  109.         x += (face->glyph->advance.x >> 6); // 字符之间的间距
    " z6 k, z( Q  `/ J
  110.     }& ?6 t+ @7 v4 [: b" P+ ]+ p
  111.     glEnd();
    4 ]* W5 F! r% P. Y: ^- Y. w% b

  112. $ J' |' Y7 z+ p4 @8 A) K+ n' L) m8 ^
  113.     glDisable(GL_BLEND);. }- u( g" b  i+ I  G
  114. }% i# Z5 Z% z' H
  115. 7 Y+ }1 q5 S- g5 W
  116. int main() {  x; R' i' [5 x3 a' j
  117.     if (!glfwInit()) {1 S9 z/ U) w% r
  118.         fprintf(stderr, "Failed to initialize GLFW\n");! A) }: \/ j4 r9 H' E% f3 m: q
  119.         return -1;9 W$ K! r0 l. [3 c- s1 M+ M7 T9 e1 M
  120.     }
    $ U& x6 Z* A9 t9 }3 S4 V
  121. $ R& v0 V/ P: \. P2 {% x
  122.     GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL Text Rendering", NULL, NULL);
    0 G- I8 O( d4 c' I3 }+ j1 A. Y
  123.     if (!window) {) P7 u& @- x2 Y8 i2 ?8 e
  124.         fprintf(stderr, "Failed to create GLFW window\n");4 G+ L0 S$ ^6 y
  125.         glfwTerminate();" D) X, T. K' v/ Q8 J' |1 }5 J, y
  126.         return -1;
    # ], p0 [! v: O; a) E8 p
  127.     }
      z7 {5 O9 D0 ^

  128. + h2 z8 A( J: X/ |
  129.     glfwMakeContextCurrent(window);  ~0 Q( y! \; \
  130.     glewInit();: \. m" v, d4 n+ g  ?
  131. ( D5 C% `3 R' }7 [
  132.     initialize();. T+ t. F' f) a4 @5 U

  133. ; }5 W. Y: s, V/ }. e
  134.     while (!glfwWindowShouldClose(window)) {
    8 R" M/ m/ N7 z9 s
  135.         glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    8 q. h% @( B3 y+ k7 e  R- @
  136.         glClear(GL_COLOR_BUFFER_BIT);
      r: D6 w: Z/ J
  137. - c7 j5 A; z: w0 r( e- R. A
  138.         glColor3f(1.0f, 1.0f, 1.0f);
    8 r/ u- K( m1 K( n2 I
  139.         renderString("Hello, OpenGL!", 100.0f, 100.0f);' s& ~: g- k" |+ g
  140. & {2 v( e$ R( W9 z/ H# `
  141.         glfwSwapBuffers(window);" R; {4 V: Z1 y* p: ?
  142.         glfwPollEvents();
    ; ^  T5 Q( A% X# n$ N+ \# U3 Y2 g* X
  143.     }
    ( X8 w; i) F/ ]1 z" f* T

  144. * }3 O- n$ W! h: Z1 q
  145.     FT_Done_Face(face);
    3 Y$ H7 b0 J% r; n# z0 c: j8 K& x' ~/ x
  146.     FT_Done_FreeType(library);: ^3 ~8 _0 T0 W0 M
  147. ; d( ~: W  H, Q' j
  148.     glfwTerminate();
    & t! W3 r# i. o1 t( X1 y
  149. " \$ v1 u) b8 w
  150.     return 0;7 I# \. S  B( M) i
  151. }
    2 U/ Y$ [. V$ L; v' u( P7 G! S
复制代码

/ K9 r* ]( \* g
( q9 E7 r6 ^' j9 o
分享到:  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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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