回 帖 发 新 帖 刷新版面

主题:[原创]OpenGL入门学习——第十六课

现在即将放出的是第十六课的内容。

首先还是以前课程的连接:
[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],因此这里并没有放到附件中。在编译的时候应该将这两个文件和其它代码文件一起编译。

=====================未完,请勿跟帖=====================

回复列表 (共106个回复)

31 楼

为什么我用drawCNString显示字符串时,第一个字符显示不出来?
如:drawCNString("我是初学者");
结果只显示“是初学者”;

drawCNString("我是初学者");
drawCNString("我是初学者");
第二个就可以完全显示了。
这是怎么回事哪?请老师指教

32 楼

[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 楼

我不是全用你的程序,只是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 楼

找到原因了
显示英文用的
 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 楼

特地注册来感谢eastcowboy的精彩教程,真是受益匪浅,鞠躬

36 楼

楼上莫非是传说中的WTT?

37 楼

是的姐姐

38 楼

啊呀呀……这个签名真是让我汗颜。
作为回报,国庆准备写下一课。不过现在的课程估计已经没有刚开始时那样有效果了,主要是我不知道读者的情况。

39 楼

呵呵,楼上的怎么能这么说呢。
地震已经都过去了。

40 楼

感谢 eastcowboy 的勤奋

我来回复

您尚未登录,请登录后再回复。点此登录或注册