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

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

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

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

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

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

本帖最后由 shane007 于 2023-9-6 15:32 编辑 8 K% ^9 k8 h/ B6 X1 k; b

7 z8 W) z  X& t) ^* k' Y以下是一个用来做参照的opengl显示字符串的代码,使用了freetype库。
( Y' D* V. ^' r3 ]6 R* w本代码经过分析以及改写之后,将取代游戏原有的显示函数。& T; `3 S- Z+ }+ Z0 p1 q' w6 u2 C" U8 c

" R. {9 H, u; n+ q4 q( y( f代码详细说明如下
; M9 ^/ Q! O0 L1 V8 P
+ b% G& V' x+ q+ [2 `1 c
  1. 在上述 renderString 函数中,我们有以下关键部分的解释:
    6 [& R% @& E4 Z! [% [

  2. ( X* d7 `, H8 u% \
  3. glBindTexture(GL_TEXTURE_2D, fontTexture);:将字体纹理绑定到当前的OpenGL上下文。这是因为我们要使用 fontTexture 中存储的字形位图数据进行渲染。* D& y, L* Q1 W

  4. , K+ H( f+ L$ {1 k2 m
  5. glEnable(GL_BLEND); 和 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);:启用混合模式以处理字符的透明度。混合模式通过 glBlendFunc 设置,这里使用了常见的源和目标因子来实现源颜色与目标颜色的混合,从而实现透明效果。7 n% H2 x1 U, r/ v' ]( N6 y
  6. 2 \( J$ N' G3 ]7 F
  7. glBegin(GL_QUADS); 和 glEnd();:在这两个函数之间的代码用于指定字符的四边形顶点,以便在OpenGL上下文中绘制字符。% _! r  l) W' Y! o  f8 v+ d

  8. # S9 i$ x  S3 c9 E
  9. for (const char* p = text; *p; p++) { ... }:这个循环遍历传递给函数的字符串 text 中的每个字符,然后为每个字符执行以下操作:
      X0 m, h, t2 u, Q

  10. ! p; S' M0 F, V3 a
  11. FT_Load_Char(face, *p, FT_LOAD_RENDER);:使用FreeType加载字符的字形数据,包括轮廓和位图信息。加载后,可以从 face->glyph 中访问该字符的字形数据。
    ) g# ^* ^- u1 f7 k

  12. 2 r% Y: a$ h! F, z( s
  13. 计算字符在屏幕上的位置和大小,包括 xpos(x坐标)、ypos(y坐标)、w(宽度)和 h(高度)。+ t$ u, ^; c! s) k. X+ O2 {9 I

  14. / ]/ N, t6 U. |  j/ p( z5 u# c
  15. 使用 glTexCoord2f 和 glVertex2f 来指定字符的纹理坐标和顶点坐标,以创建一个四边形。这四边形将字形的位图数据绘制到屏幕上的指定位置。7 w1 t, E( M7 ?) P; H

  16. ) m. z. x6 F* P5 S' M
  17. x += (face->glyph->advance.x >> 6);:更新 x 坐标,以便将下一个字符紧密排列在当前字符的后面。face->glyph->advance.x 包含字符的横向位移信息,>> 6 是用来将其转换为像素单位的操作。" X* u+ e8 b! b: e% {$ |3 r8 i
  18. : _3 b2 H; B+ V1 B
  19. 最后,glDisable(GL_BLEND); 用于禁用混合模式,以免影响后续的绘制操作。
    ! t- g* y! z1 J, G0 y2 E
  20. ) V$ y  `  x, J: V: s' S3 S
  21. 总之,renderString 函数的作用是将传递给它的字符串中的字符一个接一个地绘制到OpenGL上下文中,使用FreeType加载的字形数据和字体纹理来实现文本渲染效果。渲染过程涉及到字符的位置计算、纹理坐标的设置以及混合模式的启用和禁用,以确保字符在屏幕上正确显示。
    ! s  O: E0 b$ w- S$ c+ I
复制代码

7 {% [2 t7 g# |8 m0 m& p* z# B1 t! F$ o* z
  1. 字形数据处理的关键函数之一。以下是 FT_Load_Char 函数的详细解释:
    " c5 Q0 `$ d1 s' Q6 v, M

  2. ( W! S3 \3 b; f% a/ S
  3. 参数:0 B! v! r9 i1 T2 `2 f( i
  4. ' M' F; ^4 I" ]1 f
  5. face:一个指向已经打开的字体文件的 FT_Face 结构体的指针。FT_Face 包含了字体的各种信息,包括字形数据。
    ' n8 y" b& d) i3 y2 ~
  6. char_code:要加载的字符的Unicode编码值。您需要传递字符的Unicode编码作为此参数,以指定要加载的字符。
    * X2 S! J; U9 |2 O/ O
  7. load_flags:一个用于控制字形加载选项的标志位。您可以使用这些标志位来控制加载的方式,例如是否要加载字形的轮廓数据、是否要加载字形的位图数据等。
      }2 |/ P. }+ F+ W! u" x* D
  8. 功能:
    # N3 ]" q/ R, ?& G2 M9 ~) T

  9. + X8 |' |) _( |/ p, [
  10. FT_Load_Char 函数的主要功能是加载指定字符的字形数据。. Y. h6 i8 ]- U; B( ^  T1 m
  11. 如果成功,它将在 FT_Face 结构体中的 glyph 字段中填充有关字符的字形信息。
    & ~8 [# ?, j. k0 o
  12. 这包括了字符的轮廓数据、位图数据、宽度、高度、位图偏移等等,具体取决于传递给 load_flags 参数的设置。* e3 A( ~$ Y$ V0 z- b* C/ O
  13. 使用示例:
    8 Y: A, q% J- U  B( D; ?
  14. : Y* E6 T( t3 e3 v3 ~, M
  15. c6 a# s# d$ T' g! D
  16. Copy code
    + H) Z! G6 H# Y4 m5 g9 R
  17. FT_Load_Char(face, 'A', FT_LOAD_RENDER);: v$ C5 y4 G# T$ q( l- D' N4 u
  18. 这个示例会加载字体中字符 'A' 的字形数据,并将其渲染到位图中。FT_LOAD_RENDER 标志告诉FreeType要渲染字符的位图数据。加载后,您可以在 face->glyph 结构体中找到有关 'A' 字符的相关信息,包括位图数据、宽度、高度、位图偏移等等。  c! T3 H% k: X7 N- f4 |  F9 B
  19. 0 E' B6 t1 k! @3 a% \
  20. 错误处理:6 ?' M2 T9 E  B8 n' [

  21. 1 M( c+ l& I: S8 |
  22. 如果加载失败,FT_Load_Char 函数可以返回错误代码。您应该检查返回值以进行错误处理,并根据需要采取适当的措施,例如跳过加载失败的字符或终止渲染过程。
    ! q+ i' Y# K) s. j
  23. 总之,FT_Load_Char 函数是FreeType库中用于加载指定字符的字形数据的重要功能之一,它使您能够准备要渲染的字符数据,以便在文本渲染中使用。加载的数据可以包括字符的轮廓信息(矢量数据)和位图信息,具体取决于 load_flags 参数的设置。这个函数在字体渲染中起到关键作用,以便将字符正确呈现在屏幕上。
复制代码
" q/ [# H# p! u. i8 y7 ^4 m/ j

6 g; [4 f0 d8 M$ p2 f代码
( P  T4 b2 ?) A, U7 v, D8 L
& X. Y. Y4 L; r( E- [; V+ d

  1. ! x6 Y0 R6 U: W2 Q9 G: W5 v) \

  2. : s2 r/ U& F7 o
  3. % G* z4 h5 f8 a8 M0 J, V
  4. #include <stdio.h>
    7 f' ?+ @: ?+ p9 J
  5. #include <stdlib.h>
    " y' Y6 k& S5 O, K% L
  6. #include <GL/glew.h>
    , D% ], M8 h+ z6 J3 `6 M
  7. #include <GLFW/glfw3.h>
    9 l; O- r1 {  ?
  8. #include <ft2build.h>
    1 `9 t1 Y7 G( ~
  9. #include FT_FREETYPE_H* q1 g0 u* U% R6 E/ N) s
  10. ; {4 ^* M' U- O; L
  11. // 定义字形数据的字节数组- \, Y6 ~9 |5 N4 H2 d
  12. unsigned char fontData[] = {
    7 S& U% L( U. `4 j1 G- i, `
  13.     // 字形数据的字节表示
    & A, k  H& o) f: [- v! T: }
  14.     // 例如,这里可以包含字母、数字和符号的字形数据
    3 K+ l. C# F9 v" L9 P1 u3 D
  15. };  L- k% g$ V8 L1 @+ w1 _
  16. , B7 Y  _! k( }- z
  17. FT_Library library;$ P1 P7 h1 T, ?) m+ p
  18. FT_Face face;6 M8 E) t- Y7 c" C0 K- D
  19. GLuint fontTexture;
    2 @3 H5 g1 U4 d* J

  20. : s' W* M: w) |) Q3 @  x
  21. // 初始化FreeType库和OpenGL% L! j4 i" z, K2 R1 G8 W9 Z9 K
  22. void initialize() {
    ! J" `7 p$ S( L/ g( J) Y5 V
  23.     if (FT_Init_FreeType(&library)) {
    # m% M- |# _4 e
  24.         fprintf(stderr, "Failed to initialize FreeType\n");
    1 J( |& D$ K$ [. M7 i7 G
  25.         exit(EXIT_FAILURE);
    5 D/ w# T( ?; L$ \2 y
  26.     }
    - H0 w/ ^* ^; l$ ~" B

  27. * t; M, M0 r+ {% C# C# Z
  28.     if (FT_New_Memory_Face(library, fontData, sizeof(fontData), 0, &face)) {
    , r  e- {( L" I. Z! Q
  29.         fprintf(stderr, "Failed to create a FreeType font face\n");- t7 [+ @. q: D$ M7 L9 o! O- _
  30.         exit(EXIT_FAILURE);0 X. ]# z" }' e8 ?8 g0 [9 C$ b2 O. F
  31.     }
    7 m" D7 v5 E$ K! O
  32. , _3 X" _2 C7 I' r
  33.     if (FT_Set_Pixel_Sizes(face, 0, 48)) { // 设置字体大小! Q, D. p6 X1 J" Y9 M% ?5 [
  34.         fprintf(stderr, "Failed to set font size\n");
    - j  v. B; }% d& D8 A
  35.         exit(EXIT_FAILURE);
    ( }, j) m9 W2 u: M
  36.     }
    4 \" v; _5 L5 G5 Y' d0 ^
  37. / P# }3 u5 U, F* L5 g; a. M
  38.     glGenTextures(1, &fontTexture);
    , t( M- `+ C( ^1 B, ^% E, ?- _
  39.     glBindTexture(GL_TEXTURE_2D, fontTexture);1 N8 Q* E/ E* Q1 B
  40.     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    / C& d- Y1 u5 P! j2 @

  41. 9 Y" A$ N. H" z  Q4 m1 @% m3 w
  42.     // 将字形数据传递给OpenGL纹理8 l3 @* A- c+ ~7 j- K0 j
  43.     for (int i = 0; i < 128; i++) {' Y! M: v& W1 c
  44.         if (FT_Load_Char(face, i, FT_LOAD_RENDER)) {1 }; b/ \- u, e8 {  M
  45.             fprintf(stderr, "Failed to load glyph for character '%c'\n", i);
    " L9 K0 }/ o/ ?4 ~
  46.             continue;' ^/ K$ U" m2 x1 L6 K
  47.         }
    5 Z8 k, N; W' Z' I+ D
  48. - U6 J. b% l  f# y0 R2 y2 @
  49.         glTexImage2D(
    . _7 u* h% n( w6 a* a& x: y
  50.             GL_TEXTURE_2D,2 ?# ]  {0 k, }  U" J6 o5 I
  51.             0,
    3 ?5 `4 Z$ K$ X: F6 n
  52.             GL_RED,9 V7 `/ y3 [, L/ q
  53.             face->glyph->bitmap.width,
    # ~& i1 U$ z: X  d* u
  54.             face->glyph->bitmap.rows,( H$ T8 `8 j6 p; `0 l! {
  55.             0,% s6 X" I5 x" h2 B) E. c# o
  56.             GL_RED,% g4 v  p/ X3 S; H9 \; M$ H1 s
  57.             GL_UNSIGNED_BYTE,: V0 P# h% Q* i
  58.             face->glyph->bitmap.buffer
    % V8 Z! z3 K  o) s! B& Z& r
  59.         );
    ( L8 N9 a- ]& u9 v& R

  60. 6 n6 {. |8 D: ?
  61.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    5 E- r1 r1 }0 z; T, c
  62.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    6 v# H' b; e& U" E1 u
  63.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);% d. A. l# }  o8 {3 D8 K
  64.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    , P. [" g% W8 M% i
  65.     }
    2 E, D# w, z9 {/ ^) P& w
  66. }
    & O# w7 I/ D3 g$ }! @
  67.   r' q' H5 z* t5 O3 j2 r- _
  68. // 渲染字符串2 r2 m/ W4 s9 G6 Y  w
  69. void renderString(const char* text, float x, float y) {
    7 Z" P1 y( {3 ~
  70.     glBindTexture(GL_TEXTURE_2D, fontTexture);
    8 Z, t# t# ?3 S  \, S6 R! F! x
  71. ) D+ u$ \9 n3 o5 c9 {
  72.     glEnable(GL_BLEND);( q# [- g  j* s: c. m0 q' s) Y
  73.     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    * c$ V1 r3 _* H# @9 {2 h
  74. & E- T, x& X" b5 Z0 S
  75.     glBegin(GL_QUADS);
    # J/ ~  G! c6 x# V: M
  76.     for (const char* p = text; *p; p++) {) O* u& C) Q+ u, k6 n4 G0 L
  77.         FT_Load_Char(face, *p, FT_LOAD_RENDER);, [6 R2 c+ Z( g% y6 W+ z
  78. 1 W2 m- ?+ x% E. L; A
  79.         glTexImage2D(* }/ k8 y0 H* K
  80.             GL_TEXTURE_2D,1 k% g: b7 t1 N+ a0 ?- H
  81.             0,* w5 w, E. ?# c" Z; V
  82.             GL_RED,6 z% {& A% j) R' V0 t
  83.             face->glyph->bitmap.width,. {% Q: {$ t0 ]* ?/ {: h
  84.             face->glyph->bitmap.rows,
      P) C& L+ I( L" F+ V1 `
  85.             0,; N' N; ?4 v! R0 z# y6 {& s8 A% g
  86.             GL_RED,
    $ l* u) {, g% Z7 x2 p
  87.             GL_UNSIGNED_BYTE,2 j* u& ^# I7 b) g) h2 _. V0 J6 y
  88.             face->glyph->bitmap.buffer# @& |( i. i* U
  89.         );4 t" @/ T4 K8 R4 e9 p
  90. ( Z$ N, R" ^7 ~- x7 |) |
  91.         float xpos = x + face->glyph->bitmap_left;% k% l% t$ _& H- W0 R1 H9 L* i* D
  92.         float ypos = y - (face->glyph->bitmap.rows - face->glyph->bitmap_top);
    : ~. P& h; u! Z# D& x

  93. % q1 w6 Y6 B6 k1 ?' b
  94.         float w = face->glyph->bitmap.width;
    . x  A- z/ s* G* ]4 j; M0 A4 ~" Z
  95.         float h = face->glyph->bitmap.rows;# G$ N8 U  @+ n' O) \* o% X0 L8 y
  96. ! d2 l+ S7 P; X
  97.         glTexCoord2f(0, 0);
    * }6 h# D* ~: D  c$ c% `/ g
  98.         glVertex2f(xpos, ypos);
    7 o' |/ P# q3 c) u
  99. " N% y  x' I( _1 B
  100.         glTexCoord2f(0, 1);5 @4 j) q$ h  g9 S, Y0 [7 T+ _- R% m
  101.         glVertex2f(xpos, ypos + h);
    7 _+ E1 E4 j1 X; f

  102. 5 V0 b: s$ f4 m1 ^8 [
  103.         glTexCoord2f(1, 1);
    ' F1 y+ l+ t, m/ L8 {2 T
  104.         glVertex2f(xpos + w, ypos + h);
    % b* a' r6 V7 z+ W! I2 b
  105. ! }" F4 Z$ y' {; L2 ]( Q/ M
  106.         glTexCoord2f(1, 0);
    ' K: _7 b8 O5 i6 k
  107.         glVertex2f(xpos + w, ypos);, F5 `$ V# f# u( @# [5 f

  108. " g7 s! [2 q" h# A  n2 L
  109.         x += (face->glyph->advance.x >> 6); // 字符之间的间距% o$ t! ~/ Z9 R; Q0 j$ l
  110.     }
    $ U, ^  z) V$ D$ q0 G# e2 V# k
  111.     glEnd();2 r: v' }0 I# {5 n, q% X6 V+ G

  112. ) {7 j3 h7 m8 k+ Y
  113.     glDisable(GL_BLEND);
    2 ?# A& F  l1 a* [4 o, K2 C, ^
  114. }
    ( q) ]0 q& X2 _. ]: Y8 z0 ]
  115. " @1 k4 {: V' X8 m$ b$ o
  116. int main() {+ o9 O9 C( T( V/ a/ V
  117.     if (!glfwInit()) {
    # |; o. l2 }# f# j
  118.         fprintf(stderr, "Failed to initialize GLFW\n");
    % I# d  p% [' b$ k, t2 u/ p6 O
  119.         return -1;& B6 y% p# T0 a; t5 Y0 E
  120.     }
    $ v! i6 u2 k) S' z
  121. 3 V( B; c. S# {5 m
  122.     GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL Text Rendering", NULL, NULL);1 {6 b6 e3 K7 o' c9 z( k9 J
  123.     if (!window) {  S" _2 k9 S6 Y" N) t  J, Y1 Z
  124.         fprintf(stderr, "Failed to create GLFW window\n");5 N. o* `# C; L; Y# |
  125.         glfwTerminate();
    / d3 L8 d3 S) m. a; N- P
  126.         return -1;+ W/ g( E, C6 h( }* V" X5 g
  127.     }# Q' ~  S; c& R, F8 d
  128. % p  M9 g" Z+ |7 S# o9 V; P* Z
  129.     glfwMakeContextCurrent(window);* Y8 G5 w5 _2 c* L# m7 P8 e
  130.     glewInit();
    * J" A) ^' T3 o/ S' q5 r" q
  131. 8 t( @1 D" r5 V5 q/ b
  132.     initialize();5 I4 a% k/ \4 F- l

  133. ) P- n1 U, Y; |5 {
  134.     while (!glfwWindowShouldClose(window)) {
    ) O) e/ t2 e7 T1 D8 q
  135.         glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    ( J* J5 V4 c* Q3 ~$ E
  136.         glClear(GL_COLOR_BUFFER_BIT);* ?4 N/ X7 o1 n, r$ \# R

  137. 9 w! O+ ?1 W: t2 w5 k2 F1 [% z: G. g
  138.         glColor3f(1.0f, 1.0f, 1.0f);
    / a! g7 {% j, o0 B1 M0 S
  139.         renderString("Hello, OpenGL!", 100.0f, 100.0f);
    $ G5 Y7 w% y0 S* S! A& t. v

  140. 0 A% W0 ]4 G, d& ?! V5 Z" \
  141.         glfwSwapBuffers(window);
    1 V1 k, E+ {0 W8 ~2 a: r: y- g( A
  142.         glfwPollEvents();
    . L, a8 g! z" ^/ o9 M
  143.     }1 J, k/ H% y4 N/ b
  144. 1 J) u3 u5 J# K. S- V# Y# J+ g
  145.     FT_Done_Face(face);- L$ p7 A% |. q* v" f) @+ J6 D" y; _3 Z7 X0 ]
  146.     FT_Done_FreeType(library);$ l1 L/ e. P7 {  d3 S- D4 k4 n/ @/ v

  147. $ ?4 l. J% ?% y1 v0 X6 R' n8 Z
  148.     glfwTerminate();
    - f" b" i3 O" F# O2 O0 X
  149. 9 O3 J( B  o4 V- Y; l" O
  150.     return 0;5 p0 o5 N( V# u0 G) C5 T7 R  t
  151. }/ J$ Y) i8 M% |8 H
复制代码
9 \/ S% ~3 s! X* c0 |
$ y, v0 l/ x' P, D5 l* j6 {
分享到:  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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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