冒险解谜游戏中文网 ChinaAVG
标题:
【OpenGL汉化研究】OpenGL中文本的显示
[打印本页]
作者:
shane007
时间:
2009-10-15 00:38
标题:
【OpenGL汉化研究】OpenGL中文本的显示
Nibiru经测试,用了OpenGL的wglUseFontBitmaps,glCallLists函数来显示文字。
( i; ~ c6 y% m. l
也许是一个汉化的突破口?
3 \/ V0 m5 Y' ^0 w' X2 h( b
# I& r7 _7 `# @% J6 U% N
---- 本文详细讨论了在OpenGL中显示文本的几种方法。
- S$ }& _, L. H+ S
( B- w& S; M8 M! q1 `. }0 h% g
----也许大多数程序员使用OpenGL更多的是将精力集中于动态三维图形应用,因此,OpenGL中的文本显示往往被忽视,使人有不见积薪之感。本文介绍了几种文本显示的方法,希望能对使用OpenGL的编程者有所帮助。
& C e/ A7 S) o% F
8 h; ~& q! S2 x
建立并修改程序
% ~* N4 J' h2 j9 q% K' K
----建立一个MFC SDI Windows应用工程Text,除单文档属性外,使用其他的所有默认选择。在菜单Project打开Settings对话框,在Link属性页的 object/library modules编辑框中加入opengl32.lib glu32.lib glaux.lib三个GL库。我们利用这些库函数完成图形编辑工作。
% b9 r7 t+ R( k: V
----为使VC++的AppWizard产生的SDI应用程序能使用 OpenGL绘图,还需要作一些修改,说明如下。
8 [0 R8 r9 L1 y
0 s% l) U6 h, z3 ?! r3 C, y
----1.介绍PreCreateWindow函数
2 z- U/ e0 W5 c* m! n- J
) _+ N% K& H9 s x; t W
---- OpenGL窗口必须具有WS_CLIPCHILDREN(创建父窗口使用的Windows风格,用于重绘时剪裁子窗口所覆盖的区域)和WS_CLIPIBLINGS(创建子窗口使用的Windows风格,用于重绘时剪裁其他子窗口所覆盖的区域)两种风格。此外,窗口类属性不能包括CS_PARENTDC风格。具体程序实现如下:
x; f/ {0 W5 R& f% f
7 y3 Z) i( l# j8 Z- X/ Z
BOOL CTextView::PreCreateWindow
- M/ L- k0 G. H, e5 G# I; H
(CREATESTRUCT& cs)
+ R0 O- n' D6 g2 L
{
' V, I3 y; J4 g& r& E, `
// TODO: Modify the Window class or styles here by modifying
, \2 N) n3 O, H( S0 D
// the CREATESTRUCT cs
# O, P4 d$ M2 N2 R' u: q, k2 I
* F( S2 r, t+ Y( I$ t0 v2 u$ ~
//An OpenGL window must be created with the following flag
# j+ E4 M: b$ Q |# Y5 s
// and must not include CS_PARENTIDC for the class style.
" g2 d- ^; r4 ~$ @; k: o
cs.style|=WS_CLIPSIBLINGS|WS_CLIPCHILDREN;
: ?( X9 s( e9 u8 i( j$ x
3 x7 }6 r. n# e! A- m
return CView::PreCreateWindow(cs);
' f E: D- M8 J/ {
}
; V( p! X6 r8 o' C
9 g; W; D- @! T' T
----2.OnCreate函数中定义像素格式PIXELFORMAT和创建 RC
: ^; {. J$ \0 Z* |. ~: a! R
; x5 K7 \1 r) n1 I
----要使窗口支持OpenGL绘图,必须对窗口进行初始化。其中包括定义像素格式PIXELFORMAT和创建RC,为OpenGL指定一个合适的像素格式,创建着色上下文并将它和窗口的设备上下文关联起来。着色上下文保存着当前着色环境的信息。可在OnCreate中调用一个自建视口成员函数SetupPixelFormat(),具体函数如下:
* G6 d5 h3 Y/ @4 ?0 _
1 m, X0 o" V# G7 v8 g5 ]: p
BOOL CTextView::SetupPixelFormat()
, S* O+ L1 K7 ] t! B1 O+ n
{
/ q* b% \# y- |5 |) u+ P% o
//Create a rendering context
4 \0 R* j9 t1 k. ?6 y' o
CDC* m_pDC=GetDC();
- c/ C5 J9 V {: f R4 R
if(m_pDC==NULL) //failure to get DC
. @1 e8 r; G0 |
{
% D1 P# t+ I( E
MessageBox(“Could't get a valid DC.");
4 M7 Q% M" J8 C8 |" D2 ~- s
return FALSE;
& M/ ~6 Z7 ` Z4 N8 _
}
3 O3 s2 b/ A. |
) u2 x+ ~/ B. h/ I2 d! }" T
//Default pixel format is a single-buffered,
7 b/ z! b6 p, Q! V# l% Q; b
//OpenGL support hardware-accelerated,RGBA mode format
2 C1 w/ D* Q* z' U- v4 J! I# `
PIXELFORMATDESCRIPTOR pfd =
; n2 R# e+ t5 C7 {8 ^
{
$ e& V" n' [* E
sizeof(PIXELFORMATDESCRIPTOR),//Structure size.
8 |' s# C" m; o' r& g" v% _5 Y. s
1,
! y8 \+ T# l# H3 F5 m; g# n: R1 m
// Structure version number.Property flags(特性标志):
6 F! Q7 u* ^. ~# W
PFD_DRAW_TO_WINDOW | // support window
! n& b# p; _) z. A' t
PFD_SUPPORT_OPENGL | // support OpenGL
4 \1 G8 {2 b8 m! p: g% ?( m ~
PFD_DOUBLEBUFFER,
! y% z3 u9 ^8 u* H
PFD_TYPE_RGBA, // RGBA type
: u. o% m, V2 t7 H* z
24, // 32-bit color.
2 f) s: F+ r+ H
0, 0, 0, 0, 0, 0, // Not concerned with these:不涉及的属性
* B, d6 T1 L# j/ v. n, h$ s& K
0, // No alpha :无alpha缓存
9 A# C/ _* f9 A$ T- h) i
0, // Shift bit ignored:忽略转换位
2 I; O" Y) W+ M* z' A/ c2 b
0, 0, 0, 0, 0,// No accum buffer:没有累积缓存
0 D& S5 d, P% f% q& {+ a. t
32, // 32-bit depth buffer.
1 r" p4 g, ^! v( I( j# H
0, // No stencil:无模板缓存
& L$ n0 E9 A' L0 O4 A
0, // No auxliliary buffers:无辅助缓存
3 j( z1 v2 J/ h; Q3 C
PFD_MAIN_PLANE, // Main layer type.:主层类型
' [. b* _- ], ^% | z* S
0, // Reserved.:保留结构数
4 }! E; v, r$ h; z3 h# Q
0, 0, 0 // Unsupported.:不支持结构数
8 l! I; F; X7 z8 M
};
6 Z# W( A! i& O+ [" c
int nPixelFormat=
: k) `1 E9 b- N
ChoosePixelFormat(m_pDC->GetSafeHdc(),&pfd);
. V1 Q9 M( ?7 y* V
if( nPixelFormat ==0)
% O! f d/ p* }0 M: Y7 w
{
& i& A) Y$ Z2 b" d. d7 `6 G
MessageBox(“ChoosePixelFormat failed.");
+ z% |; {! i' C5 b2 x/ J$ `; q7 y
return FALSE;
. Z; S) v- B- i W: E% g
}
' B4 q+ `4 U; I0 z; `$ J
0 l! A8 J% e% a' ^. r3 T
if(SetPixelFormat(m_pDC->GetSafeHdc(),
9 f* ?) _7 V7 u6 F
nPixelFormat,&pfd)==0)
% G3 c6 b8 `! [; S, r1 \6 a
{
# U; b7 B$ X" p) s! x( F/ ^
MessageBox(“SetPixelFormat failed.");
( V7 e4 {" Q* x) S/ {4 s* _
return FALSE;
" P) }5 E; l* X$ i
}
( C: N+ Q! T: J) K! }
$ [* S, c: [2 ^ V
if( (m_hRC=wglCreateContext(m_pDC->
* Z( a3 I" H# b9 v( W- L; [
GetSafeHdc())) ==0)
' T/ K: d2 D8 }( P. U# g3 X$ _: p
{
2 \, B; J" A* W/ u9 [- W7 F
MessageBox(“wglCreateContext failed.");
8 W6 C& t N! G8 r! i
return FALSE;
0 U: k, B" v% z. \$ K' a0 F
}
! N! Y2 z2 [+ O9 E' a
if( (wglMakeCurrent(m_pDC->GetSafeHdc(),m_hRC)) ==0)
$ H7 Y$ E- W2 U% J! |( y; L. j
{
8 k+ ]1 K: o- ]7 Q1 y! S+ T
MessageBox(“wglMakeCurrent failed.");
1 }' k- G& m Q9 Y% h) n
return FALSE;
7 o5 ^( W3 d ]5 {( {& s
}
* {2 `3 U8 a, n* M+ x
) u$ G T6 [- c8 P9 C$ s
if(m_pDC) ReleaseDC(m_pDC);
8 @0 A$ Z* x( h* [& [. I& q" s
return TRUE;
" R3 U4 M; q% ? a! }. }
}
4 d0 c: R/ T6 G; c4 i0 O
8 C) N- H( t; ~1 T# z+ f, ^# J
----3.在OnCreate()函数中调用初始化背景函数 InitializeOpenGL()
/ u3 T! Z0 I9 I
1 h6 K" G- M! G8 ?
void CTextView::InitializeOpenGL()
) Y; m0 F5 U7 z+ z) b: G9 ?
{
, x: m2 _6 Q( R2 Y: d3 \$ T8 {
glClearColor(0.2f,0.2f,0.2f,0.0f);
9 g8 |+ @" K0 f1 F+ A! X
glClearDepth(1.0);
, q9 Q' C1 g, S
glDepthFunc(GL_LESS);
]1 u# y. ?( Z- x4 K' h4 _
glEnable(GL_DEPTH_TEST);
4 F! B6 G8 L7 _& u
glShadeModel(GL_SMOOTH);
* z- Y) W( R Z! ]
}
* S. Q% y, ?# ]3 @( d; e
$ L0 r, L4 U6 q+ [
----4.在OnCreate()中启动动画定时器
{/ k) |* n' T! C1 v. `' m* n
' G. {0 W, T; W
SetTimer(0,40,NULL);
0 |3 }9 W/ s4 ~8 u6 X
5 b5 d& ]8 _: p+ n- ?' c! j
----5.在收到WM_SIZE消息时要重新计算场景尺寸,用OnSize 设置图形显示模式
4 t# Y2 h- m5 i( v
, m3 z, ?) q+ k7 |* S
----为了使物体能合适的显示,必须要经过投影和确定视口的工作。
* }0 d+ m' _; p. m2 u) r7 F, h) Q
6 U, H$ e7 e5 m. y; \
void CTextView::OnSize(UINT nType, int cx, int cy)
7 u. t$ f$ g6 X( Y) O+ c$ P* L
{
6 ]' R% a5 g; H: b. F
CView::OnSize(nType, cx, cy);
" U: g- @9 p- x( g
' A) }# a4 K/ V$ }/ V. Z
// TODO: Add your message handler code here
" g1 C) k* M% t, j# P- l
//Save the wide and height of the current window Client
: |$ T+ f7 e! S; E
GLsizei nWidth=(GLsizei)cx;
8 X7 r% T" }3 J& Y- E$ a- k
GLsizei nHeight=(GLsizei)cy;
, S& K! E8 b2 f2 E+ I% v9 s% U& n
ratio=(double)cx/(double)cy;
# }: v$ T- ~# v; ?! E+ A3 a* F' M
* H; M& a _: A: t3 r
//Coupute the aspect ratio
1 \: t4 |! U+ ?! T
GLdouble dAspect=(GLdouble)nWidth/(GLdouble)nHeight;
1 }4 q- Y# A/ g6 C/ |( f4 u* p. a
- A& _$ m/ x- F" U+ e# [% k
glViewport(0,0,nWidth,nHeight);
: `& i( \; o7 R& Y1 R3 s
glMatrixMode(GL_PROJECTION);
; \; {/ p0 h4 w& i2 J7 ~0 Y% l
glLoadIdentity();
7 k% w5 W& i- ~; H9 H
gluPerspective
V/ m; o) y6 ?; o- w& b8 A1 o- C
(FOV,dAspect,NEARPLANE,FARPLANE);
5 d8 Y2 g5 b+ B+ B: g/ k* w
) Q( P: l5 t; f" I/ r* E
glMatrixMode(GL_MODELVIEW);
$ U6 \ x! O/ v1 b$ Y5 w; E( T) A
glLoadIdentity();
" j i6 d4 c. X( j2 J
}
+ O* V# b* k: ?2 U) }
" u' W' V M9 e o+ `
----6.在OnDraw()中简单调用DrawScene()以执行OpenGL函数
, m9 N% p+ S) e8 X& F* V7 `' E
5 K( Q( M, ?, x
void CTextView::OnDraw(CDC* pDC)
% T+ M8 U+ l7 E: p: g2 l. l
{
5 S) }5 J P! \# }9 S* ` G, G
CTextDoc* pDoc = GetDocument();
& y0 L( Z7 P6 a5 v S( k
ASSERT_VALID(pDoc);
6 Z0 C& l2 |, d; s4 ?3 V: d
9 R1 v. B# I8 w7 R, n
// TODO: add draw code for native data here
. v s. c) P& G
DrawScene();
5 m9 }3 l8 |. B1 d" K
//Invalidate();
5 J; V, v. ~. A* H9 J1 L: J
}
u4 {5 H% y. b) M4 f$ { a
8 n7 r; O, J, T% y" Q+ P) f
----7.撤销视窗时删除上下文并撤销定时器
0 ]+ C; {2 J K
n. @/ E* N( @
void CTextView::OnDestroy()
( e; `. @* j+ M" M
{
; ^9 }: z8 d' Q# n. g ?& Y
CView::OnDestroy();
6 C% z1 C Y8 |- H# n' Z1 E
- K+ N4 ^( f! B: A8 O1 V/ n
// TODO: Add your message handler code here
) h0 T6 U% Q n" l
//This call makes the current RC not current
3 t# _+ z. ~* q/ n9 r
if(wglMakeCurrent(0,0)==FALSE)
2 e! h M% v! g" X
MessageBox(“wglMakeCurrent failed.");
! U T/ d5 N) I t5 @; `: r& ?
/ B* w8 x+ P N- J
//delete the RC
: V# M1 Z2 u. s$ G _" ?
if(m_hRC && (wglDeleteContext(m_hRC)==FALSE))
6 c+ W( Z+ A2 `$ L0 r* h
MessageBox(“wglDeleteContext fail.");
9 Y& m4 W+ Z ]) p7 L
KillTimer(1);
% b+ `) E. }" c/ ]+ s6 Q3 B6 A
}
/ \0 O o9 {5 F( R. @
$ \8 f! t9 G6 P B; e, N6 a
----8.当40ms定时器时间到时,简单地将整个场景的客户区置无效,使之重画
8 u: M8 x3 l/ }0 x. p+ ?
( S* F6 F7 ~, Z
void CTextView::OnTimer(UINT nIDEvent)
: g# U% W% ]2 C. ?+ `. o
{
1 [" M: |) e6 l1 e* J! v
// TODO: Add your message handler code here and/or call default
$ ]5 p% [) Q9 a6 J, m8 l$ K
Invalidate();
1 l. S* }0 X9 c% h% i
CView::OnTimer(nIDEvent);
4 t( ~1 T5 D7 j+ T/ R
}
6 m2 W$ B) X% o
; ~: h6 G; A( D6 H. n) ?1 f
修改界面
0 n; f& A4 l& ?, h( I
---- 删除菜单IDR_MAINFRAME中File下除去Exit菜单项外的所有选项,添加“显示GDI文字” “列表制作文字”“列表三维文字”三个菜单项,并给他们分配适当的ID。使用ClassWizard为这三个菜单项在视类中添加命令处理函数和界面更新函数,其中显示GDI文字的对应的函数如下:
; O$ [" p" U$ k, X e/ b2 J
void CTextView::OnGdiText()
4 I; l! O, ?6 r; S& b! x
{
6 s( b9 d4 O1 G, @/ S- p9 e0 T* j' F
// TODO: Add your command handler code here
+ x4 W% I5 X9 q8 f# `' t5 ^8 f
m_iWhichText=0;
9 N& W h3 f" B$ o# y
Invalidate();
) i: }" H- i3 |; j: @
}
6 ]0 R b% J( J% k; i. @" Y
. p4 C/ n2 G: C/ L4 S% M
void CTextView::OnUpdateGdiText(CCmdUI* pCmdUI)
% j# `( D, G9 q/ e# u; y( f" J3 Y
{
# A/ X- T* g. g" E$ [
// TODO: Add your command update UI handler code here
) E5 {" k3 o9 ?7 F4 N6 |) Q
if(m_iWhichText==0) pCmdUI->SetCheck();
2 p8 `& o' d1 |7 {) f
else pCmdUI->SetCheck(0);
9 p0 \' w: F: Z; ?1 ]4 z
}
8 I7 }; ]" u; O4 F9 v
H$ N# I K2 [; b
----增加Draw3DText()、DrawListText()和DrawGdiText()三个函数用于三种不同的文本绘制方法。增加DrawScene()函数,它被OnDraw函数调用,用于绘制场景。在DrawScene()函数中,当m_iWhichText为0、1、2时,分别调用 DrawGdiText()、DrawListText()和Draw3DText()显示文本。具体函数实现如下:
2 k/ h& ~& Z7 I/ T* b1 p
* ]& `2 N6 Q0 Z7 |; Q/ a
void CTextView::OnDraw(CDC* pDC)
3 w1 K) P4 z0 ?, U- v1 D9 E
{
* {9 P1 ^3 [/ g7 U# t' B
CTextDoc* pDoc = GetDocument();
7 |0 i& `) o `, |) J
ASSERT_VALID(pDoc);
1 y4 o4 h& u+ e# Z
9 W) d* N% v5 L+ U' G
// TODO: add draw code for native data here
+ T0 `" j' b" r# j2 U3 v ?
DrawScene();
- Y. n6 `; e4 G2 O
//Invalidate();
* Z8 I( |2 \8 C, S
}
& M# I; @; }9 c8 m3 ]% U% p9 e
) K4 P. {' e3 j; d% B* g( F& [1 N
void CTextView::DrawScene()
% n0 m2 a ~3 F
{
2 c/ i$ z4 N+ P& Z
glClear
p O6 l! [+ X' W9 y- p$ z, _7 t
(GL_COLOR_BUFFERBIT|GL_DEPTH_BUFFER_BIT);
( \: X7 k7 D/ O" z5 |5 Q
- z" |1 ^: W: `# i9 R
glPushMatrix();
6 y2 `; P& F( x
glTranslatef(0.0f,0.0f,-FARPLANE);
p! ^6 k/ n4 G$ L Y% N' {6 }* O
//TextureMap();
; ^+ U+ r, q3 N, z; j
glPopMatrix();
q0 c; v% c1 o6 n$ V1 k
glPushMatrix();
3 D. Q* K9 u1 H9 T
glTranslatef
- E' M% j6 Q& ~7 s0 R2 K% s0 l
(0.0f,0.0f,-(FARPLANE+NEARPLANE)/2);
- v) ]8 r$ t) l
; C5 N5 L4 ? M$ \3 T. j9 m& s
if(m_iWhichText==1) DrawListText();
6 h2 B& T; a; ^$ W
if(m_iWhichText==2) Draw3DText();
: n3 d1 V8 ?: p/ Z& U! a
glPopMatrix();
- L, Y" r0 q8 p) v+ o8 l7 Q4 J
glFinish();
. V6 `' E- u. Y( M1 i) k
SwapBuffers(wglGetCurrentDC());
" m6 C+ M: Q2 w
& v6 I2 K4 y! K0 p1 M
if(m_iWhichText==0) DrawGdiText();
1 L' R+ {2 ^- v8 w5 G+ C4 s% A1 r
}
7 R% I1 W" Y' _$ u s# h; @* P: W
$ C5 |5 @1 e" v3 r( ?
GDI 显示文本
" m! n4 |5 o/ p
---- 调用wglGetCurrentDC()函数取得当前的设备上下文,使用TextOut函数显示文本,不过要注意在DoubleBuffer模式下,绘制函数要在glFinish()和 SwapBuffers(wglGetCurrentDC())函数之后调用,否则会产生闪烁,在绘制OpenGL结束之前使用GDI函数,要除去闪烁则只能使用SingleBuffer模式,具体函数如下:
) m, _# L( D# Q8 J3 j
void CTextView::DrawGdiText()
( x+ r) Y2 m3 f9 G# ^' a
{
+ q/ T& x+ \5 z
HDC hdc=wglGetCurrentDC();
, {% W5 L# H" d$ h
::SetBkMode( hdc, TRANSPARENT );
$ `: R$ n: P6 v6 H: \
::SetTextColor( hdc, RGB(250,0,0) );
- Z) n3 v1 d) l5 q& v: f
+ N% P! C- H8 c1 v5 Z# L
CString sState(“显示GDI文本。");
1 t6 K# c4 P% j* }5 M4 r( e% x9 o
::TextOut(hdc,5,5,sState,sState.GetLength());
3 @/ V+ G% V6 `- I3 s) F" { ?
}
0 Q) ?* j- o& h& w
3 |, o1 b0 A% m! R- o: M" S
wglUseFontBitmaps
0 v, ~- t5 Q7 d9 [3 G
函数显示文字
/ B% l# M2 w! a# K) O v' R8 m1 t
----使用wglUseFontBitmaps()将ASCII字符装入显示列表,然后使用glCallLists()函数利用显示列表序列显示文本。wglUseFontBitmaps有四个参数,分别是当前使用的DC、从第几个ASCII字符起始装入列表、装入列表的ASCII字符数和起始的列表序号。glListBase()指定glCallLists执行的起始列表序列号。glCallLists()含有三个参数:执行列表序列的个数、列表值的类型和所要显示的文本。注意如果所要显示的文本是字符串,它所提供的信息是相对于起始装入ASCII字符的偏移量,因此最终所显示的ASCII字符是从glListBase()所指定的列表起始号在经过glCallLists()中偏移后的列表,因此wglUseFontBitmaps的从第几个ASCII字符起始装入列表参数、glListBase()指定的 glCallLists执行的起始列表序列号和glCallLists()中的所要显示的文本参数都可以影响最终显示结果。由于显示的是ASCII 字符,因此不能显示汉字。glRasterPos3f函数决定在 OpenGL视景体坐标系下的偏移。具体函数实现如下:
6 Z/ }. j/ n+ j2 u+ z
void CTextView::DrawListText()
; _& i' Q" ^( p6 L; u9 B4 b8 P
{
6 H6 a. }1 x6 G5 R* i
wglUseFontBitmaps(wglGetCurrentDC(),0,256,1000);
- g- F9 C6 s0 y9 ^8 O& Y
glListBase(1000);
6 M) ?0 r/ |; a. @6 T) T2 g
glRasterPos3f(-5.0f,0.0f,0.0f);
8 t7 V% P8 X1 R
glCallLists(20,GL_UNSIGNED
/ U' \) \! H. a) Z% N6 x
_BYTE,“Draw with List Text.");
/ J/ c9 B8 M w( f _( v2 n* Z. r' q# A
}
: {1 n! G' W. _' N2 Z( m2 K+ Q
* M" ^4 A9 K7 v z2 T- @/ e
wglUseFontOutlines
2 q6 i4 w: J* K' |4 J, F: [1 L7 _
函数显示三维文字
5 O$ B9 k- E# W# @
----wglUseFontOutlines使得OpenGL可以显示三维文字。它的用法与wglUseFontBitmaps函数大致相同,但是多了内插计算参数、字体深度、显示方式和装载字模的缓存四个参数,且只能显示TrueType字体,显示前应该先选择字体类型。具体函数实现如下:
7 D8 M* v7 Y9 ^; t* z
void CTextView::Draw3DText()
, E7 e3 Y! |0 J$ M9 K
{
; P" P* n% e. f$ i' l& m
GLYPHMETRICSFLOAT agmf[256];
% ~& w( Z8 z- |4 z. X; {8 q
// create display lists for glyphs 0 through 255
3 f0 m" u2 w6 t c
// with 0.1 extrusion and default deviation.
- E# w. N& Q- A- R( ^. ?
//The display list numbering starts at 1000
/ i6 D7 `6 k Z' r
(it could be any number)
3 G& e9 g; J* N3 a: f+ f- o4 z0 R
wglUseFontOutlines(wglGetCurrentDC(),
6 t2 M# @, V; i) a: ]
0,255,1000,0.3f,0.8f, WGL_FONT_LINES ,agmf);
, T3 k! P. k, I- o
1 l% Q( `+ m0 f* d/ H( @9 S9 n/ ?
// Set up transformation to draw the string
- J2 M) t7 a; I, M
glTranslatef(-15.0f,0.0f,0.0f);
: T, A& }7 B, Z* j# o# l- t
glScalef(4.0f, 4.0f, 4.0f);
, O1 W, ]' ]$ r$ Q
// Display a string
# Q; ?% A' K# D& M
glListBase(1000);
2 D. O1 y) m8 Y, f' w
// Indicates the start of display lists for the glyphs
4 P# A- x0 p; [' I; ^$ x
// Draw the characters in a string
4 c& r& N6 g/ h; l' Z! |0 j
$ B0 a' k! L$ ^5 B
glCallLists(26, GL_UNSIGNED_BYTE,
$ s$ W: J4 G. S! y- E2 v+ G
“Draw outline list 3D text.");
3 p; k- W& D5 C( X' _: ^
}
作者:
shane007
时间:
2010-1-23 16:46
更改标题
欢迎光临 冒险解谜游戏中文网 ChinaAVG (https://chinaavg.com/)
Powered by Discuz! X3.2