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

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

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

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

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

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

本帖最后由 shane007 于 2023-9-6 15:32 编辑 & H( p7 c: D& e( i4 J2 f# E
! S3 [0 y) S" b% x
以下是一个用来做参照的opengl显示字符串的代码,使用了freetype库。
6 G( V: j1 d/ N+ e. }本代码经过分析以及改写之后,将取代游戏原有的显示函数。5 Y+ h3 F- i3 u: |6 n6 s( B, K
5 @' {! e& Y0 p& N/ I% Z0 \# P$ I. U
代码详细说明如下4 X3 D4 z6 H: U7 h4 C

' ^0 j5 `0 K8 w
  1. 在上述 renderString 函数中,我们有以下关键部分的解释:1 n" l1 ~9 D! h& h
  2. . I2 ]- R+ h2 K5 m% C- D- n
  3. glBindTexture(GL_TEXTURE_2D, fontTexture);:将字体纹理绑定到当前的OpenGL上下文。这是因为我们要使用 fontTexture 中存储的字形位图数据进行渲染。9 _9 q2 Q. ]; F1 p1 M7 `

  4. # Z% L& j% H4 ]# n! t
  5. glEnable(GL_BLEND); 和 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);:启用混合模式以处理字符的透明度。混合模式通过 glBlendFunc 设置,这里使用了常见的源和目标因子来实现源颜色与目标颜色的混合,从而实现透明效果。
    % R* }& _% W7 R' D2 L6 h

  6. - p* _' R$ f$ E8 [3 N/ q
  7. glBegin(GL_QUADS); 和 glEnd();:在这两个函数之间的代码用于指定字符的四边形顶点,以便在OpenGL上下文中绘制字符。: O  \1 f* Z* q! e  e- A% J
  8. 2 U* q+ i  y* @1 n4 o8 h  f
  9. for (const char* p = text; *p; p++) { ... }:这个循环遍历传递给函数的字符串 text 中的每个字符,然后为每个字符执行以下操作:
    : G. A  a8 l! @' G/ A( D! z

  10. ) V0 d4 E2 J" |( l- w4 ]8 D
  11. FT_Load_Char(face, *p, FT_LOAD_RENDER);:使用FreeType加载字符的字形数据,包括轮廓和位图信息。加载后,可以从 face->glyph 中访问该字符的字形数据。6 {1 M7 |* J+ y2 G

  12. * n  \* N. ~- B2 ^* `% P( {
  13. 计算字符在屏幕上的位置和大小,包括 xpos(x坐标)、ypos(y坐标)、w(宽度)和 h(高度)。
    8 f/ F( R0 M+ M& Z5 V* z

  14. $ F8 U7 C6 U9 R3 X, J6 m
  15. 使用 glTexCoord2f 和 glVertex2f 来指定字符的纹理坐标和顶点坐标,以创建一个四边形。这四边形将字形的位图数据绘制到屏幕上的指定位置。* r8 m4 V- k+ w% `9 J3 v

  16. , C/ \$ p& z& g% D7 O5 b7 w7 \
  17. x += (face->glyph->advance.x >> 6);:更新 x 坐标,以便将下一个字符紧密排列在当前字符的后面。face->glyph->advance.x 包含字符的横向位移信息,>> 6 是用来将其转换为像素单位的操作。
    & K0 Z/ w* ^* r2 Q

  18. . x3 u1 X& R2 H  o2 I
  19. 最后,glDisable(GL_BLEND); 用于禁用混合模式,以免影响后续的绘制操作。
    * U7 ]/ z8 ?1 O7 x  A1 \' L
  20. 1 z* c" ?# U$ B! Z( i* A
  21. 总之,renderString 函数的作用是将传递给它的字符串中的字符一个接一个地绘制到OpenGL上下文中,使用FreeType加载的字形数据和字体纹理来实现文本渲染效果。渲染过程涉及到字符的位置计算、纹理坐标的设置以及混合模式的启用和禁用,以确保字符在屏幕上正确显示。, I' x2 U0 i8 n# ^$ _0 q
复制代码
0 s% S5 _5 l' l# f
. Z) y$ L% S% k2 k( c" u
  1. 字形数据处理的关键函数之一。以下是 FT_Load_Char 函数的详细解释:+ r, T' X9 M/ W7 g$ }1 @

  2. ' i/ f; m" g) P& ]; y8 _
  3. 参数:
    * d+ w8 \) W  p( T. U1 n+ ~

  4. - U- v5 ?! z+ z% s
  5. face:一个指向已经打开的字体文件的 FT_Face 结构体的指针。FT_Face 包含了字体的各种信息,包括字形数据。
    + L7 p! v/ `  S- O2 B* |$ R  U6 L
  6. char_code:要加载的字符的Unicode编码值。您需要传递字符的Unicode编码作为此参数,以指定要加载的字符。
    + N" y( ^* t% N3 ~  r' h: Z4 k
  7. load_flags:一个用于控制字形加载选项的标志位。您可以使用这些标志位来控制加载的方式,例如是否要加载字形的轮廓数据、是否要加载字形的位图数据等。7 o% Z( r' D1 L$ D) o
  8. 功能:2 ?) L% x7 n. r- P$ F
  9. 1 N  k9 Z& _8 ?. V. b1 C
  10. FT_Load_Char 函数的主要功能是加载指定字符的字形数据。
    7 D/ D8 w" R# r* d" v. M
  11. 如果成功,它将在 FT_Face 结构体中的 glyph 字段中填充有关字符的字形信息。
    : d4 S5 D; P3 X" ~3 i4 [$ _
  12. 这包括了字符的轮廓数据、位图数据、宽度、高度、位图偏移等等,具体取决于传递给 load_flags 参数的设置。4 `; B) \5 ^& W, m' R% L8 k6 h
  13. 使用示例:: n( @! A! A7 @2 h
  14. 0 F4 v" ~8 \9 B( G1 N# u9 q
  15. c
    + `' l2 c+ J8 i8 ^# q4 I7 K
  16. Copy code, ~: z2 g" i" @+ H7 c% y1 G3 R
  17. FT_Load_Char(face, 'A', FT_LOAD_RENDER);* V' Q& |. k6 T5 e
  18. 这个示例会加载字体中字符 'A' 的字形数据,并将其渲染到位图中。FT_LOAD_RENDER 标志告诉FreeType要渲染字符的位图数据。加载后,您可以在 face->glyph 结构体中找到有关 'A' 字符的相关信息,包括位图数据、宽度、高度、位图偏移等等。
    / M5 \) e  d4 l
  19. . d* D; K, Y* @& @1 K8 n. ]
  20. 错误处理:
    ) x2 P1 ?' {- _4 d5 @3 b/ j  n& u

  21. 1 A- Z  b6 q3 J
  22. 如果加载失败,FT_Load_Char 函数可以返回错误代码。您应该检查返回值以进行错误处理,并根据需要采取适当的措施,例如跳过加载失败的字符或终止渲染过程。3 `; g! q9 F- x( ?5 D: y
  23. 总之,FT_Load_Char 函数是FreeType库中用于加载指定字符的字形数据的重要功能之一,它使您能够准备要渲染的字符数据,以便在文本渲染中使用。加载的数据可以包括字符的轮廓信息(矢量数据)和位图信息,具体取决于 load_flags 参数的设置。这个函数在字体渲染中起到关键作用,以便将字符正确呈现在屏幕上。
复制代码
1 R' h" D( W3 ?6 T* L

. h& L" P& D) ]8 i/ N& _& Q) F( r- Y$ _代码
6 c( ?4 q. [0 [$ _/ Q( J" @8 k% f% r% Z% {3 G

  1. 0 ~8 i4 H5 m% H" }; t% _/ J$ ?
  2. + H" |4 ~% P9 U, V; g& g5 e& Y
  3. & F- {5 F' j2 H/ u# e5 }: }* N+ I, I
  4. #include <stdio.h>3 F. f, G/ h! w1 w4 }( [: A" f. t/ \
  5. #include <stdlib.h>6 d& V; [/ E7 H. M7 I
  6. #include <GL/glew.h>" g5 `( ~: {6 y. h5 K
  7. #include <GLFW/glfw3.h>
    ) o) ^, b$ H+ W3 _
  8. #include <ft2build.h>/ q7 @9 U0 T3 l5 H- [0 ?6 p$ d
  9. #include FT_FREETYPE_H
    & A2 X9 h3 h0 H, m: j- C- C

  10. - @# h* y; q' P4 A
  11. // 定义字形数据的字节数组
    & \$ w$ `3 ~: x- h2 r! H
  12. unsigned char fontData[] = {
    ) |! W2 S5 ~& f9 L. J
  13.     // 字形数据的字节表示4 M  x5 j2 m" z# k) I+ i! h8 d( q' l
  14.     // 例如,这里可以包含字母、数字和符号的字形数据
    * {. j/ C6 G6 E2 m8 v6 ^
  15. };
    - n! F/ j; S2 ?1 F+ e& E% i
  16. : o/ h+ r2 ]. c& b  U3 F& N- g; m- K6 F
  17. FT_Library library;
    : ]( R, |+ N: q$ a) ^
  18. FT_Face face;
    ' n. [$ u5 c9 P( O; J- q+ W
  19. GLuint fontTexture;- `1 C' i& H0 E, S, I% V0 M
  20. 9 K$ S/ y+ K  c) s* M' b
  21. // 初始化FreeType库和OpenGL  {/ l" g% M+ D5 [# w5 g" s
  22. void initialize() {* K) o3 J" D( E; [* v# ~
  23.     if (FT_Init_FreeType(&library)) {( ^# M5 W) W# ~) ~0 }# b2 C" U
  24.         fprintf(stderr, "Failed to initialize FreeType\n");3 s6 S$ J- ?" E  v8 m
  25.         exit(EXIT_FAILURE);
    ( l: E5 o# _  S9 n# B! y" M1 N
  26.     }
    + i& c7 ]" y7 h/ J& H! U- _/ a% |
  27. 7 T2 \. X4 _# F3 P; m  }
  28.     if (FT_New_Memory_Face(library, fontData, sizeof(fontData), 0, &face)) {0 ?& X  }, h0 G! x* o- C& W" t- x- }
  29.         fprintf(stderr, "Failed to create a FreeType font face\n");
    9 O1 O9 u4 g3 {. w/ d/ o9 F
  30.         exit(EXIT_FAILURE);
    ' w/ U% i) D+ v$ I
  31.     }' j  e/ C9 X0 t. h' ]
  32. # I1 t' n  k  W8 ]/ s
  33.     if (FT_Set_Pixel_Sizes(face, 0, 48)) { // 设置字体大小+ s  v+ S* X: u& G! n: f
  34.         fprintf(stderr, "Failed to set font size\n");# H0 d* _- T* c9 Y
  35.         exit(EXIT_FAILURE);
    ' @/ z8 {# m9 n# ~8 ^7 Q4 R
  36.     }# R7 X: k0 c1 H+ ?6 G. G

  37. $ R- r# j9 Y$ F) D
  38.     glGenTextures(1, &fontTexture);, H3 H8 P- N1 A; }9 y  F' U" F* r
  39.     glBindTexture(GL_TEXTURE_2D, fontTexture);' Z7 \) {: {% {
  40.     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    4 H1 h# ?6 F# I- \- H

  41. ) A8 h2 K  |0 c
  42.     // 将字形数据传递给OpenGL纹理
    # d5 |/ P6 o, O
  43.     for (int i = 0; i < 128; i++) {
      S8 t$ |+ Y+ ^- R
  44.         if (FT_Load_Char(face, i, FT_LOAD_RENDER)) {! |  f0 t3 |) z! X$ g( h5 g
  45.             fprintf(stderr, "Failed to load glyph for character '%c'\n", i);* {" C1 C) B8 ~# F7 \4 f
  46.             continue;
    # l( E5 f) e1 U( Y7 s
  47.         }' u7 d& i5 m4 {3 i$ K; |% ~1 p
  48. % T3 O: T7 C8 e9 [& i7 t
  49.         glTexImage2D(- U& D! E0 d7 F4 o7 B
  50.             GL_TEXTURE_2D,0 i3 M  F) {% l" `2 _4 U
  51.             0,
    1 i* u/ l! k; A! w0 w: X5 M, B
  52.             GL_RED,
    & a" m4 s8 O! X5 p
  53.             face->glyph->bitmap.width,
    + H/ R0 |  L: @/ B* E' g0 d  H* ~
  54.             face->glyph->bitmap.rows,
    * m/ f. o1 m/ @# Y8 e
  55.             0,5 m0 c# _" t1 O1 o
  56.             GL_RED,
    * g( n" U3 ]; `% e. Q
  57.             GL_UNSIGNED_BYTE,6 u  C& Q- w8 x& L5 X+ i
  58.             face->glyph->bitmap.buffer2 Z# n  |: h8 b0 Z
  59.         );) i& o; {+ d1 s) y

  60. $ F$ c/ G, o8 f, X! j
  61.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    % q! ^6 n4 M) A( n* Q4 C
  62.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);  Z$ [1 E# ~3 Z. w. v2 a1 K! Y! \
  63.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);& j* D! E7 B( y$ r9 \5 v  {
  64.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);( s3 {0 }' o. V, ?( n2 m7 ?
  65.     }' G7 E+ V- R1 o
  66. }: D4 `5 z! d1 b

  67. ( b, ~3 x5 O: |5 X* q! X* S# m0 ?
  68. // 渲染字符串
    ( b( B; R7 U' k- L+ X- i
  69. void renderString(const char* text, float x, float y) {
    3 c7 Q6 l7 r* O% v8 O
  70.     glBindTexture(GL_TEXTURE_2D, fontTexture);
    ' K; e8 I& ^4 A! C9 `( t

  71. # P: _+ E$ U3 i" R* X0 s
  72.     glEnable(GL_BLEND);
    , C  b6 t4 i8 x; W" i) o
  73.     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    ! n) a( o% _6 ]/ y9 E
  74. 9 Q$ p$ {( O* k2 a6 G% \
  75.     glBegin(GL_QUADS);; i8 j5 e% i9 H  w, d/ ~8 N
  76.     for (const char* p = text; *p; p++) {( M8 V* i8 z7 k5 n, f% u8 K7 g
  77.         FT_Load_Char(face, *p, FT_LOAD_RENDER);
    4 n# Q2 C; x0 L; H1 |2 D$ R$ n

  78. & U) r+ c/ P  n+ x# K" i; r
  79.         glTexImage2D(
    * _, k$ W& v9 R& l6 g) b; `! W
  80.             GL_TEXTURE_2D,( o" z- D- o5 y- R! v; W
  81.             0,
    : J& v8 [$ c, c& ^. y  m3 `$ X
  82.             GL_RED,: w: l! q& n! p8 j* L7 o6 @
  83.             face->glyph->bitmap.width,! O. O. w9 m. u! C& i& F1 o4 X
  84.             face->glyph->bitmap.rows,  x9 a# S0 e+ I8 l8 k
  85.             0,
    , \% [0 d: z3 ~4 s) n
  86.             GL_RED,
    & |" X, |- m8 t. W+ d; ]( e3 n
  87.             GL_UNSIGNED_BYTE,: T+ \6 C- @7 S9 y1 |- X: G
  88.             face->glyph->bitmap.buffer
    ; U/ `9 f  T6 j" o2 o
  89.         );& M- {& h: K  |1 X/ m

  90. ( Q2 V3 S& {* h% h' g
  91.         float xpos = x + face->glyph->bitmap_left;
    ! ^. e' q0 W; K9 d4 {! y9 D
  92.         float ypos = y - (face->glyph->bitmap.rows - face->glyph->bitmap_top);
    & W7 r1 u! K" ]8 s
  93. * s0 T7 t2 g" t
  94.         float w = face->glyph->bitmap.width;0 ^1 t& W+ _" d! ~/ M3 Z
  95.         float h = face->glyph->bitmap.rows;) o3 R& s4 P: k

  96. 6 b+ K; O4 q, H6 R9 l  S
  97.         glTexCoord2f(0, 0);
    9 Y3 `1 k5 U! {
  98.         glVertex2f(xpos, ypos);" U  \: N! t9 {) _2 z3 }
  99. ! U' z- L8 X5 u1 @6 W) V- e4 P. Y
  100.         glTexCoord2f(0, 1);; b/ I0 w' C7 W; ]
  101.         glVertex2f(xpos, ypos + h);5 a" k8 T( v6 P
  102. : X1 b! S) V3 b/ B- ?; l
  103.         glTexCoord2f(1, 1);
    " y5 L. x' g5 J5 z( T& n+ T+ \: x
  104.         glVertex2f(xpos + w, ypos + h);
    " X2 ~* m  G& S
  105. ( k2 d- u) f6 Z# |" ^
  106.         glTexCoord2f(1, 0);
    ; L1 Z  Y' O7 ]+ K6 C  o
  107.         glVertex2f(xpos + w, ypos);& j, M, i3 {- J/ z

  108. ' R9 I. d2 I1 s, v$ v
  109.         x += (face->glyph->advance.x >> 6); // 字符之间的间距
    - L  S$ e* E* a, L% s! w" y
  110.     }
    ' M8 C  q+ |: Z4 ?. l5 u( I
  111.     glEnd();
    ' O6 p) w- x) o9 s2 R

  112. 7 F: l3 F( ^: \  y- A
  113.     glDisable(GL_BLEND);
    ; x. t: q; p! i1 V1 @
  114. }$ |( r8 u3 S; b. [1 W1 k7 O. C: |) b
  115. 7 t! _7 E# G/ U# m  Q
  116. int main() {
    * w* E7 C$ L- x. Z
  117.     if (!glfwInit()) {
    ! g3 E9 t; C" P
  118.         fprintf(stderr, "Failed to initialize GLFW\n");
    7 v  t- k- g8 H3 K0 }& x
  119.         return -1;
    - C- T- A; _9 W$ O& g8 f/ r# w& K
  120.     }
    $ f. \! [( ^5 N! a
  121. . c" `: i# l' w1 s+ |6 m
  122.     GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL Text Rendering", NULL, NULL);
    4 r. K2 p" A7 t
  123.     if (!window) {  R" y9 A: G4 o; r) ^- x7 k
  124.         fprintf(stderr, "Failed to create GLFW window\n");% {- z4 o7 |9 A. J
  125.         glfwTerminate();( _. U# w8 r( {0 @, O
  126.         return -1;- }" p, L+ b. k$ K
  127.     }
    . @% x* |6 B0 E' U; s: m! [
  128.   |1 r3 j+ p. k* b
  129.     glfwMakeContextCurrent(window);" q1 e9 h, b% S; `( c% `
  130.     glewInit();
    . T% d& p! y' `! l

  131. ' e9 m7 n9 a2 }: q0 x
  132.     initialize();( E4 f3 ]. w/ Q* Q: f, a! o

  133. / x! h7 x/ |% @: c+ j: l# `
  134.     while (!glfwWindowShouldClose(window)) {
    / ^) ~  B) \' k8 d. e: h; V1 G* S1 }
  135.         glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    , W/ W. Q3 i: D8 {( w
  136.         glClear(GL_COLOR_BUFFER_BIT);7 w- l- q, @- K6 F! I& H

  137. , G& g  l$ A$ |6 |, m
  138.         glColor3f(1.0f, 1.0f, 1.0f);& u& `4 g+ q' t, O: e. `
  139.         renderString("Hello, OpenGL!", 100.0f, 100.0f);
    : U! i! M& H7 k
  140. 0 D' {' n5 s. l- t. Y* |5 x
  141.         glfwSwapBuffers(window);1 ?( j  T4 w# e; ~$ Y+ }1 d9 j
  142.         glfwPollEvents();
    7 `0 d" G% M5 s: w! l: c" L& r
  143.     }; l. ^4 p" ~3 H  o) A4 g

  144. 5 i# y' ]5 E7 o. D/ M$ y0 W+ ]7 P
  145.     FT_Done_Face(face);$ O7 V, P$ }7 P# y  Z- G6 O
  146.     FT_Done_FreeType(library);3 \' B6 G3 {% R' @& W$ D
  147. 2 {. @; G, m; {! {/ @8 R
  148.     glfwTerminate();
    7 [0 e; K+ X5 k% y6 |2 C/ }' b; _/ c
  149. 1 t% x7 w' m' U. D0 _* K" W% ?% I
  150.     return 0;8 O) |( N9 Q$ Y+ v; o
  151. }. s4 G' U8 U) `
复制代码
, z$ o: n% A/ ]+ q6 P  ?# J

/ T) p9 w! b6 k8 |* a
分享到:  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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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