主题:[原创]OpenGL入门学习——第十六课
eastcowboy
[专家分:25370] 发布于 2008-05-05 14:24:00
现在即将放出的是第十六课的内容。
首先还是以前课程的连接:
[url=http://www.programfan.com/club/showbbs.asp?id=184355]第一课,编写第一个OpenGL程序[/url]
[url=http://www.programfan.com/club/showbbs.asp?id=184525]第二课,绘制几何图形[/url]
[url=http://www.programfan.com/club/showbbs.asp?id=184769]第三课,绘制几何图形的一些细节问题[/url]
[url=http://www.programfan.com/club/showbbs.asp?id=185032]第四课,颜色的选择[/url]
[url=http://www.programfan.com/club/showbbs.asp?id=196017]第五课,三维的空间变换[/url]
[url=http://www.programfan.com/club/showbbs.asp?id=196231]第六课,动画的制作[/url]
[url=http://www.programfan.com/club/showbbs.asp?id=218828]第七课,使用光照来表现立体感[/url]
[url=http://www.programfan.com/club/showbbs.asp?id=219518]第八课,使用显示列表[/url]
[url=http://www.programfan.com/club/showbbs.asp?id=224877]第九课,使用混合来实现半透明效果[/url]
[url=http://www.programfan.com/club/post-227694.html]第十课,BMP文件与像素操作[/url]
[url=http://www.programfan.com/club/post-244703.html]第十一课,纹理的使用入门[/url]
[url=http://bbs.pfan.cn/post-252901.html]第十二课,OpenGL片断测试[/url]
[url=http://bbs.pfan.cn/post-275218.html]第十三课,OpenGL是一个状态机[/url]
[url=http://bbs.pfan.cn/post-275219.html]第十四课,OpenGL版本和OpenGL扩展[/url]
[url=http://bbs.pfan.cn/post-275223.html]第十五课,从“绘制一个立方体”来看OpenGL的进化过程[/url]
第十六课,在Windows系统中显示文字 ——→ [color=0000FF]本次课程的内容[/color]
内容超多的一课!不过我想精彩的程度也一定不会让大家失望。大家不妨先浏览一下课程里的图片:)。
[color=FF0000]2008-06-10 修改了附件[/color]
增加了两个文件,showline.c, showtext.c。分别为第二个和第三个示例程序的main函数相关部分。
在ctbuf.h和textarea.h最开头部分增加了一句#include <stdlib.h>
附件中一共有三个示例程序:
第一个,飘动的“曹”字旗。代码为:flag.c, GLee.c, GLee.h
第二个,带缓冲的显示文字。代码为:showline.c, ctbuf.c, ctbuf.h, GLee.c, GLee.h
第三个,显示歌词。代码为:showtext.c, ctbuf.c, ctbuf.h, textarea.c, textarea.h, GLee.c, GLee.h
其中,GLee.h和GLee.c可以[url=http://www.opengl.org/sdk/libs/GLee/GLee5_21.zip]从网上下载[/url],因此这里并没有放到附件中。在编译的时候应该将这两个文件和其它代码文件一起编译。
=====================未完,请勿跟帖=====================
最后更新于:2008-06-10 15:57:00
回复列表 (共106个回复)
31 楼
viclouis [专家分:0] 发布于 2008-09-03 15:14:00
为什么我用drawCNString显示字符串时,第一个字符显示不出来?
如:drawCNString("我是初学者");
结果只显示“是初学者”;
而
drawCNString("我是初学者");
drawCNString("我是初学者");
第二个就可以完全显示了。
这是怎么回事哪?请老师指教
32 楼
eastcowboy [专家分:25370] 发布于 2008-09-03 21:18:00
[quote]为什么我用drawCNString显示字符串时,第一个字符显示不出来?[/quote]
我重新测试了一下,没有发现有这样的问题。
因为源代码是分散给出的,可能因为在组合时的一些偏差而导致最终的错误。下面我给一份完整的源代码,你可以对照一下。如果你运行这份代码仍然出现问题,请再跟帖告诉我。
[code=c]#include <gl/glut.h>
#include <windows.h>
// ASCII字符总共只有0到127,一共128种字符
#define MAX_CHAR 128
void selectFont(int size, int charset, const char* face) {
HFONT hFont = CreateFontA(size, 0, 0, 0, FW_MEDIUM, 0, 0, 0,
charset, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, face);
HFONT hOldFont = (HFONT)SelectObject(wglGetCurrentDC(), hFont);
DeleteObject(hOldFont);
}
void drawString(const char* str) {
static int isFirstCall = 1;
static GLuint lists;
if( isFirstCall ) { // 如果是第一次调用,执行初始化
// 为每一个ASCII字符产生一个显示列表
isFirstCall = 0;
// 申请MAX_CHAR个连续的显示列表编号
lists = glGenLists(MAX_CHAR);
// 把每个字符的绘制命令都装到对应的显示列表中
wglUseFontBitmaps(wglGetCurrentDC(), 0, MAX_CHAR, lists);
}
// 调用每个字符对应的显示列表,绘制每个字符
for(; *str!='\0'; ++str)
glCallList(lists + *str);
}
void drawCNString(const char* str) {
int len, i;
wchar_t* wstring;
HDC hDC = wglGetCurrentDC();
GLuint list = glGenLists(1);
// 计算字符的个数
// 如果是双字节字符的(比如中文字符),两个字节才算一个字符
// 否则一个字节算一个字符
len = 0;
for(i=0; str[i]!='\0'; ++i)
{
if( IsDBCSLeadByte(str[i]) )
++i;
++len;
}
// 将混合字符转化为宽字符
wstring = (wchar_t*)malloc((len+1) * sizeof(wchar_t));
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, str, -1, wstring, len);
wstring[len] = L'\0';
// 逐个输出字符
for(i=0; i<len; ++i)
{
wglUseFontBitmapsW(hDC, wstring[i], 1, list);
glCallList(list);
}
// 回收所有临时资源
free(wstring);
glDeleteLists(list, 1);
}
void display(void) {
glClear(GL_COLOR_BUFFER_BIT);
selectFont(48, ANSI_CHARSET, "Comic Sans MS");
glColor3f(1.0f, 0.0f, 0.0f);
glRasterPos2f(-0.7f, 0.4f);
drawCNString("我是初学者");
selectFont(48, GB2312_CHARSET, "楷体_GB2312");
glColor3f(1.0f, 1.0f, 0.0f);
glRasterPos2f(-0.7f, -0.1f);
drawCNString("我是初学者");
selectFont(48, DEFAULT_CHARSET, "华文仿宋");
glColor3f(0.0f, 1.0f, 0.0f);
glRasterPos2f(-0.7f, -0.6f);
drawCNString("我是初学者");
glutSwapBuffers();
}
int main(int argc, char* argv[]) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
glutCreateWindow("OpenGL 显示文字");
glutDisplayFunc(&display);
glutMainLoop();
return 0;
}
[/code]
33 楼
viclouis [专家分:0] 发布于 2008-09-04 14:16:00
我不是全用你的程序,只是drawCNString用的是你的函数。我写的不是控制台程序,相关代码如下:
wglMakeCurrent(m_hdc,m_hRC);
wglUseFontBitmaps(m_hdc,32,223,m_FontBase);
glEnable(GL_SCISSOR_TEST);
glScissor(rt.left,0,rt.Width(),rt.Height());
glClearColor(GetRValue(BackgroundColor)/255.0f,GetGValue (BackgroundColor)/255.0f,GetBValue(BackgroundColor)/255.0f,0.0);
glClear(GL_COLOR_BUFFER_BIT);
glDisable(GL_SCISSOR_TEST);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0,0,rt.Width(),rt.Height());
gluOrtho2D(0,rt.right,rt.bottom,0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRasterPos2f(m_Left-6,m_Bottom+m_DisCFY+5);
drawCNString("我是初学者");
glFinish();
SwapBuffers(m_hdc);
34 楼
viclouis [专家分:0] 发布于 2008-09-04 14:27:00
找到原因了
显示英文用的
wglUseFontBitmaps(m_hdc,32,223,m_FontBase);
没消去。
另外还有个问题想请教,我用两种不同字体显示一句话中的字,本来效果很好,可是屏幕一刷新就变成同一种字体了,在一刷新,又变成两种字体了,是怎么回事哪?
openGL有时真的学的很迷糊
相关程序如下:
SelectObject(m_hdc, 字体1);
wglUseFontBitmaps(m_hdc,32,223,m_FontBase);
显示英文
SelectObject(m_hdc, 字体2);
wglUseFontBitmaps(m_hdc,32,223,m_FontBase);
显示英文
[b] SelectObject(m_hdc, 字体1);
wglUseFontBitmaps(m_hdc,32,223,m_FontBase);[/b]
加黑这段如果不加,就全是字体1,如果加了,就出现我开始说的那种情况,一刷新,就会发生改变
35 楼
PureMilk [专家分:0] 发布于 2008-09-23 19:18:00
特地注册来感谢eastcowboy的精彩教程,真是受益匪浅,鞠躬
36 楼
雨中飞燕 [专家分:18980] 发布于 2008-09-23 20:09:00
楼上莫非是传说中的WTT?
37 楼
PureMilk [专家分:0] 发布于 2008-09-23 23:05:00
是的姐姐
38 楼
eastcowboy [专家分:25370] 发布于 2008-09-24 13:07:00
啊呀呀……这个签名真是让我汗颜。
作为回报,国庆准备写下一课。不过现在的课程估计已经没有刚开始时那样有效果了,主要是我不知道读者的情况。
39 楼
wangbin039 [专家分:0] 发布于 2008-12-13 16:33:00
呵呵,楼上的怎么能这么说呢。
地震已经都过去了。
40 楼
tianyuan008 [专家分:14360] 发布于 2009-03-10 00:56:00
感谢 eastcowboy 的勤奋
我来回复