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

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

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

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

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

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

本帖最后由 shane007 于 2023-9-6 15:32 编辑
1 [) Y) o3 z5 z# j  j
8 Q9 u! r7 e2 G# l3 m2 q0 M& e以下是一个用来做参照的opengl显示字符串的代码,使用了freetype库。3 o. _) j1 m* _, X# A5 K8 |: D8 S
本代码经过分析以及改写之后,将取代游戏原有的显示函数。
: N; @/ |$ @- S9 t: z3 j
- ], s: z  ~$ A2 u7 V, a5 C/ V代码详细说明如下
  G. K7 b% g5 j/ `  w+ i! E
$ k; M8 B# H  R. |0 g
  1. 在上述 renderString 函数中,我们有以下关键部分的解释:
    , F* Y* T. \  |& D5 Q1 Q/ k$ E. \
  2.   \5 k! C* C& S- a/ f
  3. glBindTexture(GL_TEXTURE_2D, fontTexture);:将字体纹理绑定到当前的OpenGL上下文。这是因为我们要使用 fontTexture 中存储的字形位图数据进行渲染。
    2 v" L: g5 z% _) d: |
  4. ( H% q; ~7 w2 O, o* R" u+ e( B7 A- I
  5. glEnable(GL_BLEND); 和 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);:启用混合模式以处理字符的透明度。混合模式通过 glBlendFunc 设置,这里使用了常见的源和目标因子来实现源颜色与目标颜色的混合,从而实现透明效果。: h) X) f% S! h
  6. , p$ {' P: y2 @4 B- a
  7. glBegin(GL_QUADS); 和 glEnd();:在这两个函数之间的代码用于指定字符的四边形顶点,以便在OpenGL上下文中绘制字符。( W6 m& k) l) N# \

  8.   M9 h% N9 c3 S' _2 g4 |5 B
  9. for (const char* p = text; *p; p++) { ... }:这个循环遍历传递给函数的字符串 text 中的每个字符,然后为每个字符执行以下操作:
    . J) H7 E: B9 v( V% {
  10. * }3 N/ O6 T% Q" E
  11. FT_Load_Char(face, *p, FT_LOAD_RENDER);:使用FreeType加载字符的字形数据,包括轮廓和位图信息。加载后,可以从 face->glyph 中访问该字符的字形数据。
    3 V2 _1 H8 B4 z  F
  12. 1 v  l& l( N1 F" T* y
  13. 计算字符在屏幕上的位置和大小,包括 xpos(x坐标)、ypos(y坐标)、w(宽度)和 h(高度)。2 _9 Y7 d1 p; O  g; Q6 |
  14. ( A- ]5 E& P3 I3 j* Z* l/ K# ]. A
  15. 使用 glTexCoord2f 和 glVertex2f 来指定字符的纹理坐标和顶点坐标,以创建一个四边形。这四边形将字形的位图数据绘制到屏幕上的指定位置。1 e% N( _9 c8 X6 G' p
  16. 2 p* ~: m/ _$ R3 R4 S
  17. x += (face->glyph->advance.x >> 6);:更新 x 坐标,以便将下一个字符紧密排列在当前字符的后面。face->glyph->advance.x 包含字符的横向位移信息,>> 6 是用来将其转换为像素单位的操作。# p/ N9 W" b! h! I( C* N
  18. ! K9 {  f. E/ S( u8 Z# C8 A
  19. 最后,glDisable(GL_BLEND); 用于禁用混合模式,以免影响后续的绘制操作。, N% H2 i1 L( Y, w0 R2 }4 V. g' g

  20. & s) X2 L* C* \: L% G+ r
  21. 总之,renderString 函数的作用是将传递给它的字符串中的字符一个接一个地绘制到OpenGL上下文中,使用FreeType加载的字形数据和字体纹理来实现文本渲染效果。渲染过程涉及到字符的位置计算、纹理坐标的设置以及混合模式的启用和禁用,以确保字符在屏幕上正确显示。
    ( G3 B' |. D2 o3 q, T
复制代码

3 @& W8 f( ^  W! H: O5 }% {6 l% B: |$ ~3 C3 q5 D" `. _
  1. 字形数据处理的关键函数之一。以下是 FT_Load_Char 函数的详细解释:
    " Q+ w5 U4 t- T1 z0 X/ e
  2. 6 e. g: p& i1 I. [: ^9 ~5 c3 u: J
  3. 参数:9 @  F# I6 R5 [, j- n# |5 L

  4. 4 [2 w( v/ {; \/ ]0 w2 A$ g# s5 h
  5. face:一个指向已经打开的字体文件的 FT_Face 结构体的指针。FT_Face 包含了字体的各种信息,包括字形数据。6 U" a7 P! O+ L0 F
  6. char_code:要加载的字符的Unicode编码值。您需要传递字符的Unicode编码作为此参数,以指定要加载的字符。
    " b' {% K: G4 T1 H
  7. load_flags:一个用于控制字形加载选项的标志位。您可以使用这些标志位来控制加载的方式,例如是否要加载字形的轮廓数据、是否要加载字形的位图数据等。: a+ q" ]1 @3 t& u+ U# G7 S
  8. 功能:8 Q+ G( {1 S2 f4 }
  9. 0 P, G# X+ f& n- p# [+ g9 z% x
  10. FT_Load_Char 函数的主要功能是加载指定字符的字形数据。  @! B1 D% V# M5 N; W0 k- C
  11. 如果成功,它将在 FT_Face 结构体中的 glyph 字段中填充有关字符的字形信息。
    / d) \2 G9 q$ N! ?# `) d# w
  12. 这包括了字符的轮廓数据、位图数据、宽度、高度、位图偏移等等,具体取决于传递给 load_flags 参数的设置。) v" W9 i+ [+ z8 W" D7 B
  13. 使用示例:# Y& T) O! _& p- z, _

  14. - V3 A% Y) t" c  ]  G
  15. c
    7 A) ^6 T1 y+ ]1 ?6 M( ^
  16. Copy code6 L: ~( v+ o6 ^! h3 i
  17. FT_Load_Char(face, 'A', FT_LOAD_RENDER);4 [: ^% a  @( B( `' a; ?9 I
  18. 这个示例会加载字体中字符 'A' 的字形数据,并将其渲染到位图中。FT_LOAD_RENDER 标志告诉FreeType要渲染字符的位图数据。加载后,您可以在 face->glyph 结构体中找到有关 'A' 字符的相关信息,包括位图数据、宽度、高度、位图偏移等等。
    6 r; D# \4 y1 t( y  s

  19. , h9 d0 }  r7 U" f& X4 F+ t
  20. 错误处理:
    7 Z6 m( j' k* Q# T

  21. 0 H% \- W: D3 i  C$ ~8 m
  22. 如果加载失败,FT_Load_Char 函数可以返回错误代码。您应该检查返回值以进行错误处理,并根据需要采取适当的措施,例如跳过加载失败的字符或终止渲染过程。0 W$ V. o& K" y
  23. 总之,FT_Load_Char 函数是FreeType库中用于加载指定字符的字形数据的重要功能之一,它使您能够准备要渲染的字符数据,以便在文本渲染中使用。加载的数据可以包括字符的轮廓信息(矢量数据)和位图信息,具体取决于 load_flags 参数的设置。这个函数在字体渲染中起到关键作用,以便将字符正确呈现在屏幕上。
复制代码

7 m+ M& L5 N$ M/ S( E$ U- q0 ]+ A6 p2 \" U7 p' \* ]
代码
" Z1 _- q& T0 y) S# D0 H7 h: k9 c+ p# \" y: Z
  1. # t8 W0 A5 {7 }

  2. ' i( F* K3 ^4 h
  3. 1 }3 q! @) v* Y! G' H! d( B3 l% x! Z, ^
  4. #include <stdio.h>. v0 f) w6 {+ \  Q1 q5 ]" G6 h
  5. #include <stdlib.h>
    7 O3 l" v. Z3 d/ K4 R, A9 X
  6. #include <GL/glew.h>/ U, s. L8 d: u& B. d7 `, `
  7. #include <GLFW/glfw3.h>
    8 A+ l9 X6 N$ u  c" s
  8. #include <ft2build.h>
    * E- H7 j* I. |, ?
  9. #include FT_FREETYPE_H
    3 \$ X, F+ k# V; y3 m
  10. ' a1 `: X- n/ ~) U; k) Q
  11. // 定义字形数据的字节数组
    . ?8 e9 S6 F: |; Z' E$ @
  12. unsigned char fontData[] = {
    1 R: {0 P1 e0 Q( s* F3 y  T: a
  13.     // 字形数据的字节表示
    % B4 a( N2 C: j! _
  14.     // 例如,这里可以包含字母、数字和符号的字形数据
      X' c- ~( C/ T8 a4 L- D
  15. };
    ( h" I9 |/ @! R; U3 s) f4 Q& {
  16. & o4 ^! z, }+ L9 ]
  17. FT_Library library;0 C/ S; j4 I2 P3 P
  18. FT_Face face;
    : Q" o$ `$ K9 a& _% D+ v
  19. GLuint fontTexture;
      n/ j% {: C; Z/ |0 b

  20. & f0 Y: E; K$ V6 R9 P4 N3 @6 R  P3 r
  21. // 初始化FreeType库和OpenGL
    ) N3 U3 N' k; G) [+ B+ R
  22. void initialize() {8 v4 r+ Q1 }1 l
  23.     if (FT_Init_FreeType(&library)) {: l- }" j' e# a+ ?
  24.         fprintf(stderr, "Failed to initialize FreeType\n");8 O, _# O" `0 ^1 f9 t2 ?2 u& ^0 K
  25.         exit(EXIT_FAILURE);
    & T4 C5 [8 u, n5 Z" s; @
  26.     }
      O8 k& C- J" I+ p+ u, a0 k; r! u' y
  27. + G. H, |- Y1 A. K! r0 v9 A& m) L
  28.     if (FT_New_Memory_Face(library, fontData, sizeof(fontData), 0, &face)) {: u5 o7 e8 {/ F* z7 U2 a7 R7 C
  29.         fprintf(stderr, "Failed to create a FreeType font face\n");/ @% t' o7 x2 x" K6 g' J2 P
  30.         exit(EXIT_FAILURE);3 {6 ?- j' I9 T
  31.     }
    7 {1 E8 ~9 `: ]8 L* q

  32. ( U$ S; A( Q6 r) k) M
  33.     if (FT_Set_Pixel_Sizes(face, 0, 48)) { // 设置字体大小
    ( j& ]. }0 ~- Y, Z/ {
  34.         fprintf(stderr, "Failed to set font size\n");! A% ~& A( u2 ?, S/ P
  35.         exit(EXIT_FAILURE);9 [) z, a& \. u# a) o3 b
  36.     }
    / n# M0 o' x8 U3 x
  37. 4 s3 d3 z- }6 G9 Z* P+ k# q2 Y' n, \
  38.     glGenTextures(1, &fontTexture);
    # H3 [; I& E& n7 p5 J! l1 w* Q6 i% s
  39.     glBindTexture(GL_TEXTURE_2D, fontTexture);
    % a" Z! q( h# B3 L
  40.     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    , U$ d" [6 C% O9 E) E

  41. 6 ^* W( Z/ [0 F) B; T
  42.     // 将字形数据传递给OpenGL纹理
    9 n4 T# t2 o& L- M2 L  Z7 @. X* ?
  43.     for (int i = 0; i < 128; i++) {7 g: {1 s# e: P! i) u7 m
  44.         if (FT_Load_Char(face, i, FT_LOAD_RENDER)) {* q& X. u( ~5 L, i# x2 Y
  45.             fprintf(stderr, "Failed to load glyph for character '%c'\n", i);
    1 e3 T7 w% W" M; r6 L
  46.             continue;
    7 K* ~  a# d- b/ X
  47.         }
    : h3 p5 @, t$ p
  48. ) O+ G# z$ J' f
  49.         glTexImage2D(+ k3 X& q1 M+ {, [2 }
  50.             GL_TEXTURE_2D,, _/ e+ z9 [  j8 p& @8 m
  51.             0,+ E6 Q$ B* j2 I
  52.             GL_RED,
    ' S" u. u% [; v5 |
  53.             face->glyph->bitmap.width,, ]0 }: I. c; p( ]
  54.             face->glyph->bitmap.rows,3 [1 a! F* o- t$ S- f
  55.             0,
    9 w$ t! C+ J; z7 p4 f, @
  56.             GL_RED,
    ; U* j$ x0 ~, {5 |$ ], I4 z. e
  57.             GL_UNSIGNED_BYTE,
    % R! e7 P/ M' M0 f7 o3 ?
  58.             face->glyph->bitmap.buffer
    + A+ [9 L+ q/ d
  59.         );
    9 X/ E. h/ l7 p8 q( ]2 ?
  60. $ Y+ V3 R+ X! t( u
  61.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    ! k! m" l) e9 C* n1 R7 c- m
  62.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    . M+ [/ B- b+ `. x
  63.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);& D! y- x2 X- z5 p; M5 R
  64.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    - z/ C* w5 ?+ f  S1 d6 O* m
  65.     }
    6 X9 W1 x0 N# q  \- V5 S$ c! q
  66. }
    8 S- K# N* v6 u) Q" Q8 q

  67. + P3 L8 e( [0 k
  68. // 渲染字符串
    3 U- \5 W- z2 f0 K9 c/ T; o- \- b
  69. void renderString(const char* text, float x, float y) {
    % V' h6 n$ ~7 Y* ~1 C, b) D: O
  70.     glBindTexture(GL_TEXTURE_2D, fontTexture);/ \' p# k9 @- Z2 v: |# k
  71. ( P+ L5 i  O" i' I1 T
  72.     glEnable(GL_BLEND);
    ( m/ I6 M4 P% I/ ~' `1 Z* S
  73.     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);2 ?; I7 g! V  s; E, V$ H6 W6 x
  74. : C! }, g  c6 v% b: Y
  75.     glBegin(GL_QUADS);6 a# Q) F3 U2 v8 ?. S* S% ]' h
  76.     for (const char* p = text; *p; p++) {
    5 `1 [- {6 ]2 D
  77.         FT_Load_Char(face, *p, FT_LOAD_RENDER);  V& D' c0 D% {0 s
  78. ! {9 P9 ?6 M( ~$ w
  79.         glTexImage2D(
    # ]: B+ ^: V& h( i& [) H) _! U
  80.             GL_TEXTURE_2D,0 D2 |, u7 t. l7 z% n$ }& T
  81.             0,
    6 x" |+ }# O, A9 R# f8 F
  82.             GL_RED,
    / @- J: H5 b( d) K# y- |
  83.             face->glyph->bitmap.width,
    ( M; b2 y9 L! s1 T
  84.             face->glyph->bitmap.rows,
    , A: D& l4 q9 K2 r2 ~6 `
  85.             0,
    8 D3 g  G$ s) M, _$ ~7 c
  86.             GL_RED,
    $ C; d; z& ~5 z
  87.             GL_UNSIGNED_BYTE,
    : d0 D; o0 |: R( X# p4 M
  88.             face->glyph->bitmap.buffer
    $ O" Q3 E4 w, M
  89.         );: T) H- t+ d: ?- H2 s# ?

  90. 1 c7 Z: p2 p2 l! G
  91.         float xpos = x + face->glyph->bitmap_left;
    / q; @3 `  w; K/ G- m; M0 Y+ y2 p
  92.         float ypos = y - (face->glyph->bitmap.rows - face->glyph->bitmap_top);
    ) B9 U4 N7 D7 Y5 l
  93. 4 m" C: N4 l; Z" u
  94.         float w = face->glyph->bitmap.width;2 p- v0 ?. r7 o! K4 o8 [) \! ?
  95.         float h = face->glyph->bitmap.rows;
    . C+ S6 K4 G" |& O( I' Q4 r' e
  96. 3 r& A; w. Z' K  p& A# o8 i) N% y
  97.         glTexCoord2f(0, 0);% d4 j# a( ~- P& ?9 V+ ^. }
  98.         glVertex2f(xpos, ypos);
    % u4 F5 e* T2 m) ~5 V
  99. * U6 k9 `# A; j
  100.         glTexCoord2f(0, 1);) v5 d' s& z1 W9 D
  101.         glVertex2f(xpos, ypos + h);& ^& V3 U: Q/ Q* ~0 s4 }- F% k% w
  102. ! O3 H" q: {+ @
  103.         glTexCoord2f(1, 1);7 r6 g" o9 j  T8 a4 ?6 l
  104.         glVertex2f(xpos + w, ypos + h);- e# x8 J9 ^* I) ]

  105. + S+ k( X5 _6 M+ H% d' P- v
  106.         glTexCoord2f(1, 0);
    1 Q& E  c3 r# a! @2 A! d
  107.         glVertex2f(xpos + w, ypos);& |3 y9 ]3 c4 q( w" L+ ]

  108. 4 o2 X5 T  i5 g/ j* \
  109.         x += (face->glyph->advance.x >> 6); // 字符之间的间距
    * P+ r, j  {! T8 k
  110.     }
    / {7 i" Q+ i: c4 t
  111.     glEnd();1 o3 b) c" k, V  t

  112. 3 U( W9 X2 l7 Z  \2 H
  113.     glDisable(GL_BLEND);
    : |  l+ M7 n) q" U
  114. }
      r. R6 e7 z. s% O8 A* K4 ]
  115. : k( ~1 V( @/ ?
  116. int main() {
    * d0 w  ?: K$ z9 e" D. M
  117.     if (!glfwInit()) {. ?6 D5 t9 b/ i( [& G$ ~. Q
  118.         fprintf(stderr, "Failed to initialize GLFW\n");
    . b4 |# x' k4 a$ k$ `+ E+ x
  119.         return -1;
    1 J/ t" b/ R/ t- a9 l
  120.     }) z+ P3 T# f. Y3 q2 h8 W+ `

  121. / b; \) G% S7 p0 n# }
  122.     GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL Text Rendering", NULL, NULL);# F. K) b( Y" H+ Y9 r* }
  123.     if (!window) {/ n4 b8 ]1 T& [8 c  @, Z, V# ?+ \" Y
  124.         fprintf(stderr, "Failed to create GLFW window\n");
    ( L+ M$ k- N, E6 Z# {, x
  125.         glfwTerminate();
    ) A2 z# h6 y% p2 n
  126.         return -1;
    5 B# _" Y5 l# K" v, ~
  127.     }, d# Z2 j0 b2 _4 F1 l: N$ `0 l
  128. ) o6 n/ I. e- z1 |* ^) Q5 d3 J
  129.     glfwMakeContextCurrent(window);
    / E/ B/ {4 }! a* F
  130.     glewInit();3 O5 n& P! u- K) p; N7 d

  131. * ]0 M( k% N' A, G
  132.     initialize();
    1 s1 _( }( g0 T  v7 I

  133. : h/ f2 Z& ~8 n/ M/ |
  134.     while (!glfwWindowShouldClose(window)) {
    . U" h. F3 u2 k4 y& s$ m
  135.         glClearColor(0.0f, 0.0f, 0.0f, 1.0f);7 B' D3 T- S- a" o: Q7 s' c0 C  k/ w$ h9 J
  136.         glClear(GL_COLOR_BUFFER_BIT);  U: r' ^. p! P- {( X5 s. q* u% t

  137. % a. N# ]7 N* T( O" E& x
  138.         glColor3f(1.0f, 1.0f, 1.0f);
    + D# Z" }0 |9 w; o" P6 w$ D
  139.         renderString("Hello, OpenGL!", 100.0f, 100.0f);
      N9 g9 n! O# r; L0 F8 f+ \

  140. 4 L; W0 l1 U* u+ U# b0 L! h
  141.         glfwSwapBuffers(window);( p* \( v: Z$ @2 [
  142.         glfwPollEvents();
    6 O/ d; X, p1 n& i; A5 E; D
  143.     }( h/ h8 G' ]+ T$ {5 Z4 {0 x
  144. ! m* G5 {8 `: ~; l7 k
  145.     FT_Done_Face(face);+ y' |$ F" n7 ]6 c& P
  146.     FT_Done_FreeType(library);
      U/ M: @  i" w  a9 R" _% L
  147. $ r2 Y& u2 j6 E. R. M$ {
  148.     glfwTerminate();
    $ m1 F5 V" F2 I$ N! J* j6 y9 l

  149.   W& i; v/ ^" M& E+ h9 K
  150.     return 0;5 `) I2 b  J; X/ F
  151. }6 g6 f  ?+ \% A  B& L1 E
复制代码
. v1 p7 z" A: y: q/ o

& u) H6 k0 N; x& D# J
分享到:  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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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