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

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

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

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

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

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

本帖最后由 shane007 于 2023-9-6 15:32 编辑 ' c( i" B  F+ e3 G  x
; X+ s% p9 Y" m+ T6 [1 E2 ]( A" k
以下是一个用来做参照的opengl显示字符串的代码,使用了freetype库。: r1 F% p0 t# k" _
本代码经过分析以及改写之后,将取代游戏原有的显示函数。$ y/ b. w% i" o5 t% ?$ b/ R

; t7 D- M0 x- V, Q3 }代码详细说明如下6 r: n1 ]$ c5 M' S& V

5 G$ J& |0 w9 @3 \) i! Z' |: j% w
  1. 在上述 renderString 函数中,我们有以下关键部分的解释:
    1 x/ N; R0 l% x& V1 P
  2. ) t5 |$ I! ^& J3 [  `
  3. glBindTexture(GL_TEXTURE_2D, fontTexture);:将字体纹理绑定到当前的OpenGL上下文。这是因为我们要使用 fontTexture 中存储的字形位图数据进行渲染。- _( K) l/ l- Y0 {

  4. + v( j- X2 ]) ]* U
  5. glEnable(GL_BLEND); 和 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);:启用混合模式以处理字符的透明度。混合模式通过 glBlendFunc 设置,这里使用了常见的源和目标因子来实现源颜色与目标颜色的混合,从而实现透明效果。9 w5 r: Z' {3 N3 y
  6. 7 ]" n- W4 v2 s' G$ S
  7. glBegin(GL_QUADS); 和 glEnd();:在这两个函数之间的代码用于指定字符的四边形顶点,以便在OpenGL上下文中绘制字符。) O+ Y, J. B9 j6 Z& `9 ^
  8. : p/ o6 x" ?) g; l8 p& r; D( T, L
  9. for (const char* p = text; *p; p++) { ... }:这个循环遍历传递给函数的字符串 text 中的每个字符,然后为每个字符执行以下操作:2 M4 J* s' j3 c$ [& C
  10.   Q- i5 H! n3 Q0 Q* F
  11. FT_Load_Char(face, *p, FT_LOAD_RENDER);:使用FreeType加载字符的字形数据,包括轮廓和位图信息。加载后,可以从 face->glyph 中访问该字符的字形数据。
    + L6 ^! h0 t% b5 V
  12. % }) B' M& l( k/ x1 B+ U
  13. 计算字符在屏幕上的位置和大小,包括 xpos(x坐标)、ypos(y坐标)、w(宽度)和 h(高度)。
    6 z" o) G: h; S1 P. {+ Y) j# r6 ]. ~
  14. 3 U0 \: |' Z8 U
  15. 使用 glTexCoord2f 和 glVertex2f 来指定字符的纹理坐标和顶点坐标,以创建一个四边形。这四边形将字形的位图数据绘制到屏幕上的指定位置。
    ; p7 C1 d  G( |2 E4 \1 ~% K
  16. 0 p7 U; Q' V, \8 x( Z# d
  17. x += (face->glyph->advance.x >> 6);:更新 x 坐标,以便将下一个字符紧密排列在当前字符的后面。face->glyph->advance.x 包含字符的横向位移信息,>> 6 是用来将其转换为像素单位的操作。5 {. u% u; ?- v7 z3 r6 Y; l, g

  18. 1 `! o) i6 @' V8 ~
  19. 最后,glDisable(GL_BLEND); 用于禁用混合模式,以免影响后续的绘制操作。( ]$ N, S; f6 e, ]; c5 {
  20. ; i. A5 S2 A1 K; O9 X/ q
  21. 总之,renderString 函数的作用是将传递给它的字符串中的字符一个接一个地绘制到OpenGL上下文中,使用FreeType加载的字形数据和字体纹理来实现文本渲染效果。渲染过程涉及到字符的位置计算、纹理坐标的设置以及混合模式的启用和禁用,以确保字符在屏幕上正确显示。
    ' _3 I* l! q2 H9 D  X; O7 E- r
复制代码

6 o. H1 ~. ]5 F/ L! d3 x! m
2 o7 G- {% ?$ J0 v2 X* t1 Y5 A; o
  1. 字形数据处理的关键函数之一。以下是 FT_Load_Char 函数的详细解释:5 J. D, o/ N4 q  w
  2. ! y+ h  o* }9 R+ F3 m
  3. 参数:
    , A# V% s4 l  W' U3 P+ N/ w
  4. ! z  L8 E8 W+ f3 [" d, q
  5. face:一个指向已经打开的字体文件的 FT_Face 结构体的指针。FT_Face 包含了字体的各种信息,包括字形数据。
    / v& \6 G. q  x8 `2 i. f0 W
  6. char_code:要加载的字符的Unicode编码值。您需要传递字符的Unicode编码作为此参数,以指定要加载的字符。' g" S; ~8 }1 Y" L/ X4 v& S5 o( B
  7. load_flags:一个用于控制字形加载选项的标志位。您可以使用这些标志位来控制加载的方式,例如是否要加载字形的轮廓数据、是否要加载字形的位图数据等。
    6 o3 f% h, b. b
  8. 功能:
    ( f& h( F2 s" S

  9. 3 D& U8 c. o* ]7 ?1 @9 I1 l
  10. FT_Load_Char 函数的主要功能是加载指定字符的字形数据。
    - x7 X  H& w1 R1 `* P7 ?
  11. 如果成功,它将在 FT_Face 结构体中的 glyph 字段中填充有关字符的字形信息。
    9 O' |& H) O+ {  b/ t
  12. 这包括了字符的轮廓数据、位图数据、宽度、高度、位图偏移等等,具体取决于传递给 load_flags 参数的设置。
    8 Y  d# L  c7 h! P, `* r- P0 D1 N- y* z
  13. 使用示例:# y2 o7 a2 _! ~
  14. % \% D+ i5 U) }# ?" A# B! T
  15. c
    1 `6 |- T. B+ j  K1 T7 v8 A$ T' ?
  16. Copy code( X) U% e& H! y- j$ r7 x1 X0 i
  17. FT_Load_Char(face, 'A', FT_LOAD_RENDER);
    ' j+ s( W8 }# ~
  18. 这个示例会加载字体中字符 'A' 的字形数据,并将其渲染到位图中。FT_LOAD_RENDER 标志告诉FreeType要渲染字符的位图数据。加载后,您可以在 face->glyph 结构体中找到有关 'A' 字符的相关信息,包括位图数据、宽度、高度、位图偏移等等。( z2 t2 B7 W; I8 g+ @

  19. 5 I$ O+ n1 l. q$ R- s. P
  20. 错误处理:1 F3 `5 n7 Z* w* X7 ?5 \* [5 R: X% z
  21. 4 F* x! D4 f9 r4 ^" f
  22. 如果加载失败,FT_Load_Char 函数可以返回错误代码。您应该检查返回值以进行错误处理,并根据需要采取适当的措施,例如跳过加载失败的字符或终止渲染过程。
    + B9 R/ D% d6 w, M/ I
  23. 总之,FT_Load_Char 函数是FreeType库中用于加载指定字符的字形数据的重要功能之一,它使您能够准备要渲染的字符数据,以便在文本渲染中使用。加载的数据可以包括字符的轮廓信息(矢量数据)和位图信息,具体取决于 load_flags 参数的设置。这个函数在字体渲染中起到关键作用,以便将字符正确呈现在屏幕上。
复制代码

1 ^) G% @. O; a2 n  e4 r( h6 P  ]3 Y, k2 Y2 }1 S# Q
代码9 d) E8 w- o/ @( |
& e5 v3 a# J3 ^8 V

  1. ; o# `5 }0 q6 W8 {7 G+ W
  2. ' n9 ?0 s1 ?; ~/ B+ K

  3. % E( v, g! L9 @( @% l
  4. #include <stdio.h>, Q: j! T$ V8 @3 o) b8 Q8 ^7 M& I( D) p
  5. #include <stdlib.h>) I9 F+ u' s$ w
  6. #include <GL/glew.h>
    3 z2 L; x! E- H# y4 a8 D
  7. #include <GLFW/glfw3.h>
    : |4 z6 P) _# w3 N3 U" k/ I
  8. #include <ft2build.h>
    8 A& ~. s. n9 y3 \$ d
  9. #include FT_FREETYPE_H6 [' [: Z$ q- J# T) a6 ~- e* [

  10. , B4 {! d5 k8 b; E* g& r
  11. // 定义字形数据的字节数组
    ) O7 m7 \* ?2 U! e$ I3 \
  12. unsigned char fontData[] = {
    3 |. w% g' |% d' q
  13.     // 字形数据的字节表示, g7 L$ V% \' B+ W2 }/ \) g
  14.     // 例如,这里可以包含字母、数字和符号的字形数据- G. T% }0 t- d) }2 h6 z
  15. };
    / l$ J2 v" B) w+ z8 D9 g7 O

  16. 4 z6 M$ o! ^7 g6 w7 m9 F
  17. FT_Library library;+ K4 I& x  B) A0 B; |" N5 o
  18. FT_Face face;+ r# f0 Y& r; R9 l9 R. e% K
  19. GLuint fontTexture;
    : v1 \$ c8 F: q8 ]6 L- `

  20.   T6 v5 k) |# B3 N; x( R
  21. // 初始化FreeType库和OpenGL4 \  U: q1 E5 Z2 U7 _3 B8 r( V' |; p
  22. void initialize() {
    5 G# b- E% {5 ]: q+ M/ X, \
  23.     if (FT_Init_FreeType(&library)) {
    0 J( d7 t+ W: @7 G- G$ j
  24.         fprintf(stderr, "Failed to initialize FreeType\n");
    2 a1 _. q4 I3 u% Q
  25.         exit(EXIT_FAILURE);: m! f' x/ _# u1 t  r
  26.     }
    6 y) S6 |( C, o

  27. $ O0 K' F- Z2 }% }6 e* C4 V3 y
  28.     if (FT_New_Memory_Face(library, fontData, sizeof(fontData), 0, &face)) {
    $ \7 \; i* n* m6 b! U& s! W; o
  29.         fprintf(stderr, "Failed to create a FreeType font face\n");
    ! o" {5 }+ Z8 h$ U! u2 |
  30.         exit(EXIT_FAILURE);* x! E% }; `3 t
  31.     }
    . j4 i! G, _. n& z- C. O( b4 L: u# o

  32. ; W" e& v9 A  I8 ]4 C) d
  33.     if (FT_Set_Pixel_Sizes(face, 0, 48)) { // 设置字体大小
    : p& \, F* J! R# t- t% E2 C! X
  34.         fprintf(stderr, "Failed to set font size\n");1 N6 Y( e- L4 X9 M% v
  35.         exit(EXIT_FAILURE);
    ! o. Y' |/ u0 l6 s* }3 i- N3 S
  36.     }4 E) p. m8 |( C4 [2 D7 c( b$ k, I: P

  37. 8 X( f* H( Z2 I2 n& V6 ^, g
  38.     glGenTextures(1, &fontTexture);
    " {$ r7 L5 i. {( _- O4 _1 N+ f5 X
  39.     glBindTexture(GL_TEXTURE_2D, fontTexture);
    . Y+ L4 `1 `/ Q0 w: C
  40.     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    9 a; M6 ~; f2 U/ b2 ?
  41. , |- m: p6 U* R7 v& `" K$ i
  42.     // 将字形数据传递给OpenGL纹理: ?! s. L  A( c- @, a
  43.     for (int i = 0; i < 128; i++) {
    * J% [& n$ K* E* p' @- `" j( B
  44.         if (FT_Load_Char(face, i, FT_LOAD_RENDER)) {! F. Q3 w/ L$ O; ]9 v
  45.             fprintf(stderr, "Failed to load glyph for character '%c'\n", i);1 N& o5 ^0 i" B. T. {
  46.             continue;
    3 \$ q8 H- a  Z7 {- w. n
  47.         }; `2 R% i7 r+ v7 F7 v: h. ?, x

  48. 4 ]% {8 |. j- c; i: D5 _) b
  49.         glTexImage2D(
    0 M- ~( L* `, Z' j" |3 j! z
  50.             GL_TEXTURE_2D,8 q) {' Z  a1 a, n, c
  51.             0,
    & b( E5 K% T. G! m' b/ s. F
  52.             GL_RED,
    9 C0 K, n$ w- x) y0 Q4 i5 r1 @
  53.             face->glyph->bitmap.width,
    / D2 a5 U: h% j$ Z
  54.             face->glyph->bitmap.rows,
    ; _( R5 A2 q9 }% V2 l8 i
  55.             0,
    , K8 f& l# d8 D, F  \4 u
  56.             GL_RED,6 b6 i: c7 {3 b# ?1 a/ ?$ L, g) Z
  57.             GL_UNSIGNED_BYTE,) ^0 B8 ^& c& y
  58.             face->glyph->bitmap.buffer& V+ a. h* D: t9 ?5 x# z
  59.         );( m, i1 P: d7 L9 E7 f

  60. 1 l- f5 w# z; U$ N, E) y
  61.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    ) A8 u' n) B$ E; ~) ?1 w" T
  62.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);; v; D% Z7 N( a" w3 L% Y- S9 ~
  63.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);' b/ y0 `8 L. r8 O  ^/ c
  64.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    9 N  E* o7 X6 B' X  v" `9 Z' k
  65.     }' V% V# M8 S5 `0 P3 z' b; D/ v
  66. }) b" ?1 Q9 y0 y/ i" u+ B8 d+ D  z

  67. 1 s0 a4 z2 [( s( f* |
  68. // 渲染字符串# i* {/ e/ W* g# ]" b0 h! ?+ l
  69. void renderString(const char* text, float x, float y) {" z# M& i  P8 b& K4 H2 C3 I
  70.     glBindTexture(GL_TEXTURE_2D, fontTexture);
    / g7 ]4 W; A- T- I4 u; t1 g% U

  71. ) B0 D4 a& N& h$ I
  72.     glEnable(GL_BLEND);" Q0 C' s2 }# V# x# w- s% W
  73.     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);: N( W8 k0 u/ S9 G+ i+ [

  74. # }$ q7 {7 Y5 Q( H% I8 U
  75.     glBegin(GL_QUADS);  T3 W+ ], P9 u1 s& ^/ \/ B- ^- b
  76.     for (const char* p = text; *p; p++) {
    / m" O5 f  M; m, B6 I8 u3 s: b# P' {
  77.         FT_Load_Char(face, *p, FT_LOAD_RENDER);6 A6 R% S% {' R6 E. F8 j, G3 W* X

  78. 0 p' @4 W4 ?7 c9 M9 ^: F; N
  79.         glTexImage2D(' o1 H, L* H3 s( q) T4 \9 B2 H
  80.             GL_TEXTURE_2D,
      [8 h& d5 \: F3 t$ @* F: R
  81.             0,6 _* I9 c& Z) I  _$ A* J
  82.             GL_RED,- d0 u) p# U' w' K5 g! y5 I
  83.             face->glyph->bitmap.width,
    ) e; n: _4 Q: ~- Y2 y
  84.             face->glyph->bitmap.rows,  z2 V  W0 d4 o5 }8 k( {
  85.             0,
    5 Y7 J7 D8 Y* P3 O9 m. Q
  86.             GL_RED,- M2 @! C2 }- [
  87.             GL_UNSIGNED_BYTE,) U$ x8 S6 R5 o% N( X" M6 g5 \! n
  88.             face->glyph->bitmap.buffer
    - w! r! b1 r4 o4 V/ p3 a5 @
  89.         );
    9 J: z0 E. V7 |

  90.   Z: T. U" F) \. I- k9 h
  91.         float xpos = x + face->glyph->bitmap_left;1 w% i9 v' B9 Q# `1 D7 f
  92.         float ypos = y - (face->glyph->bitmap.rows - face->glyph->bitmap_top);
    $ }1 [. w$ ~" u3 b2 Z8 C9 I$ a, f7 \1 {

  93. " m# _$ b" o% R- ~# z3 G
  94.         float w = face->glyph->bitmap.width;4 x$ x9 i9 q! q# F& h9 L3 o0 J' Z
  95.         float h = face->glyph->bitmap.rows;) J: c# I3 t' O. }

  96. 7 `$ E  v5 r5 m1 Z9 R
  97.         glTexCoord2f(0, 0);. e, A% S8 h: K. f/ Y
  98.         glVertex2f(xpos, ypos);8 v: W( W! z$ W7 {
  99. . U2 W! u$ T" G% F+ v0 ^5 _+ j5 A
  100.         glTexCoord2f(0, 1);
    - m$ z3 {0 S: W1 x
  101.         glVertex2f(xpos, ypos + h);6 s6 a, C6 w  _* r1 r
  102. ! S0 ^/ r# e8 k. p; u
  103.         glTexCoord2f(1, 1);
    & V* k; y$ w. h2 [7 h6 Z
  104.         glVertex2f(xpos + w, ypos + h);3 A; d% N& C/ r6 g; l% u

  105. 5 }( R5 y4 T$ A2 ?( z& `
  106.         glTexCoord2f(1, 0);" U6 f) y! j$ i8 g+ O
  107.         glVertex2f(xpos + w, ypos);' w2 [# d, S/ b! _. ?+ J; _7 {5 ]% m
  108. 2 I9 }$ ]5 V+ P0 H, l# w
  109.         x += (face->glyph->advance.x >> 6); // 字符之间的间距
    + e  s4 l4 i7 o+ A: ]* U
  110.     }
    4 T1 ^: h; |  ?% C+ {
  111.     glEnd();1 r0 t: W: T) y  u% u! l& \# o

  112. 7 ^, s0 N* ~$ t) O; ]
  113.     glDisable(GL_BLEND);
    0 T3 i& p$ {$ n( w: \
  114. }) |2 T& }% H6 T$ S% ?! G4 e

  115. * {) l6 j& ~' P6 X; U
  116. int main() {# ^2 q$ _. G# C: q% W: i
  117.     if (!glfwInit()) {
    , F" K2 D0 {' d9 G# Z" A" B0 C+ N. Z
  118.         fprintf(stderr, "Failed to initialize GLFW\n");
    3 ^# Q! r# ]# o2 c# q6 Q8 `
  119.         return -1;" ]* q* \7 ^8 n1 s5 h  ]$ ]! A" ~
  120.     }. I$ b7 j- h$ J

  121. & H/ U; d6 J; P  w( H5 P+ w
  122.     GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL Text Rendering", NULL, NULL);3 d. Y7 ^2 V7 \
  123.     if (!window) {
    6 Y& q3 {) }' i% U) e/ p6 r# `1 _
  124.         fprintf(stderr, "Failed to create GLFW window\n");
    : Z9 U! h+ T, O( h5 v
  125.         glfwTerminate();
    ' J% T1 w. \7 c0 Z3 u/ `" [$ B/ z" V; z
  126.         return -1;6 B/ t) c- d, F% w. {& C
  127.     }2 [9 X3 n  @1 @( ~

  128. ; N  W8 B! W- j9 ^  i9 D4 a2 t2 j
  129.     glfwMakeContextCurrent(window);: T- h6 \( x7 o5 U
  130.     glewInit();) H# r+ ?$ x' e: W
  131. 5 H5 T& m! p/ y7 g: e
  132.     initialize();
    % l9 l( G6 {% ]7 N9 ^# f( g" V; C

  133. ' e. {. W4 U8 Q* |
  134.     while (!glfwWindowShouldClose(window)) {
    : ^0 Z) ]! u$ G) {- X+ H7 D
  135.         glClearColor(0.0f, 0.0f, 0.0f, 1.0f);  }$ X+ r/ j6 ^" x3 G# ~7 {8 \
  136.         glClear(GL_COLOR_BUFFER_BIT);
    & x  B& o( u, N
  137. ( f' q5 u8 X/ [% ~
  138.         glColor3f(1.0f, 1.0f, 1.0f);2 d( E# M% P2 U! j
  139.         renderString("Hello, OpenGL!", 100.0f, 100.0f);  w' L9 n5 r( X* A& m# D& X  l

  140. 5 U: F& W  X, h
  141.         glfwSwapBuffers(window);4 J/ z; a1 ]0 S
  142.         glfwPollEvents();4 P* x: y+ n6 X$ R
  143.     }$ m# b& A' S2 |: T" t

  144. & h1 u( X9 \: e& f& w4 }! e
  145.     FT_Done_Face(face);
    : Y9 t% B% C5 ^% P# u- w1 ^2 m, Y
  146.     FT_Done_FreeType(library);+ j2 Q* h: C5 Q9 `+ J) R

  147. 1 S5 _9 U& M0 m
  148.     glfwTerminate();; r& E. R2 O6 p8 V& J5 j

  149. * ^% E4 k+ q+ [
  150.     return 0;" X' o. N& F3 Y$ B
  151. }
    / P. D+ I' X, N! w
复制代码
* A3 F0 |0 r5 n7 q) T( F  B4 c/ j

0 c6 x% d2 f* d& X; q1 T
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 很美好很美好1 很差劲很差劲
回复

使用道具 举报

沙发
发表于 2025-4-12 16:41 | 只看该作者
学习学习一下
回复 支持 反对

使用道具 举报

高级模式
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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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