用OpenGL绘制位图字体,glRasterPos2i()是做啥的?

Posted

技术标签:

【中文标题】用OpenGL绘制位图字体,glRasterPos2i()是做啥的?【英文标题】:Drawing bitmap fonts with OpenGL, what does glRasterPos2i() do?用OpenGL绘制位图字体,glRasterPos2i()是做什么的? 【发布时间】:2013-07-19 14:12:10 【问题描述】:

这是另一个“我有一个空白屏幕,请帮我解决它”的时刻。

此示例来自 OpenGL 编程指南,版本 2.1,第 311-312 页。

该示例应该在屏幕上绘制 2 行文本。

我认为过去的问题是我不明白 glRasterPos2i() 是如何工作的。可以: A :) 设置要在 3D 世界中绘制的位图的位置在同质/“OpenGL 坐标”中 B:) 设置要绘制的位图在屏幕上的像素坐标位置

这是我目前的代码:您几乎可以忽略定义位图是什么的第一个大块。

#include <GL/glut.h>
#include <cstdlib>
#include <iostream>
#include <cstring>


// This first bit is kind of irreverent, it sets up some fonts in memory as bitmaps
GLubyte space[] = 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ;

GLubyte letters[][13] = 
                         0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xff, 0xc3, 0xc3, 0xc3, 0x66, 0xc3, 0x18 ,
                         0x00, 0x00, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe ,
                         0x00, 0x00, 0x7e, 0xe7, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e ,
                         0x00, 0x00, 0xfc, 0xce, 0xc7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc7, 0xce, 0xfc ,
                         0x00, 0x00, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xff ,
                         0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xff ,
                         0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xcf, 0xc0, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e ,
                         0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xff, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3 ,
                         0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e ,
                         0x00, 0x00, 0x7c, 0xee, 0xc6, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06 ,
                         0x00, 0x00, 0xc3, 0xc6, 0xcc, 0xd8, 0xf0, 0xe0, 0xf0, 0xd8, 0xcc, 0xc6, 0xc3 ,
                         0x00, 0x00, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0 ,
                         0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xff, 0xff, 0xe7, 0xc3 ,
                         0x00, 0x00, 0xc7, 0xc7, 0xcf, 0xcf, 0xdf, 0xdb, 0xfb, 0xf3, 0xf3, 0xe3, 0xe3 ,
                         0x7e, 0xe7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xe7, 0x7e ,
                         0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0xc0, 0xf3, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe ,
                         0x00, 0x00, 0x3f, 0x6e, 0xdf, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c ,
                         0x00, 0x00, 0xc3, 0xc6, 0xcc, 0xd8, 0xf0, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe ,
                         0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0x7e, 0xe0, 0xc0, 0xc0, 0xe7, 0x7e ,
                         0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff ,
                         0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3 ,
                         0x00, 0x00, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3 ,
                         0x00, 0x00, 0xc3, 0xe7, 0xff, 0xff, 0xdb, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3 ,
                         0x00, 0x00, 0xc3, 0x66, 0x66, 0xc3, 0xc3, 0x18, 0xc3, 0xc3, 0x66, 0x66, 0xc3 ,
                         0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xc3, 0xc3, 0x66, 0x66, 0xc3 ,
                         0x00, 0x00, 0xff, 0xc0, 0xc0, 0x60, 0x30, 0x7e, 0x0c, 0x06, 0x03, 0x03, 0xff 
                        ;


// This is just copying from the book
GLuint fontOffset;

void makeRasterFont()

    GLuint i, j;
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    fontOffset = glGenLists(128);
    for(i = 0, j = 'A'; i < 26; i ++, j ++)
    
        glNewList(fontOffset + ' ', GL_COMPILE);
            glBitmap(8, 13, 0.0, 2.0, 10.0, 0.0, letters[i]);
        glEndList();
    
    glNewList(fontOffset + ' ', GL_COMPILE);
        glBitmap(8, 13, 0.0, 2.0, 10.0, 0.0, space);
    glEndList();



void init()

    glShadeModel(GL_FLAT);
    makeRasterFont();



void printString(char* s)

    glPushAttrib(GL_LIST_BIT);
        glListBase(fontOffset);
        glCallLists(std::strlen(s), GL_UNSIGNED_BYTE, (GLubyte*)s);
    glPopAttrib();



void display()

    GLfloat white[3] = 1.0, 1.0, 1.0 ;

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glColor3fv(white);

    // Print some text on the screen at (20,60) and (20,40)
    glRasterPos2i(20, 60);
    printString("THE QUICK BROWN FOX JUMPS");
    glRasterPos2i(20, 40);
    printString("OVER A LAZY DOG");

    glFlush();



void reshape(int w, int h)

    // Set the viewport
    glViewport(0, 0, (GLsizei)w, (GLsizei)h);

    // Set viewing mode
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0, (GLfloat)w / (GLfloat)h, 0.01, 100.0);
    glMatrixMode(GL_MODELVIEW);




int main(int argc, char** argv)


    /* Init glut with a single buffer display mode,
     * window size, position and title */
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(500, 500);
    glutInitWindowPosition(100, 100);
    glutCreateWindow(argv[0]);

    // Call init routine to set OpenGL specific initialization values
    init();

    // Set callback function
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);

    // Enter main loop
    glutMainLoop();

    return EXIT_SUCCESS;

对于这种问题,我很抱歉——我讨厌只问“请修复我的代码”,因为我真的应该能够自己修复它。在这种情况下,我发现自己基本上被卡住了。感谢您的时间和帮助。

解决方案:

对于那些感兴趣的人,为了“让它发挥作用”,所做的更改是:

1:将 gluPerspective 更改为 gluOrtho2D(0, width, 0, height)。

2:将 glnewList(fontOffset + ' ', GL_COMPILE) 更改为 glnewList(fontOffset + j, GL_COMPILE) - 不是两者,只是循环中的第一个。

3:将 glRasterPos2i 设置为 glOrtho2D 指定区域内的任何位置。我的宽度和高度都是 500,所以我使用坐标 (20, 60) 和 (20, 40)。

您可以将其保留为 gluPerspective,并使用大约 (0,0) 的坐标而不指定任何转换。但是,由于位图是 2D 的,我认为这不太直观。

【问题讨论】:

那么试图解决什么问题? 我尝试了几种不同的投影,包括 3D 和 2D 投影,我尝试移动“相机”以将字体放置在近剪裁平面和远剪裁平面之间,我尝试加载身份矩阵,等等 【参考方案1】:

至于你的渲染问题,提示,你不要使用 j...

在for循环中:

glNewList(fontOffset + ' ', GL_COMPILE);

用你想要的字母替换你的空格。

【讨论】:

书有错误!震惊!好的,谢谢,我改一下。 好的,这是修复了一个错误...虽然仍然是空白屏幕,我会尝试一些其他的东西。【参考方案2】:

glRasterPos function 指定对象坐标中的光栅位置。这些通过当前模型视图和投影矩阵(在glRasterPos-调用时)获得窗口(视口)坐标中的实际光栅位置,用于glDrawPixelsglBitmap(因此选项一个)。因此,鉴于您当前的透视投影和身份模型视图,那些(20,40)(可能表示为像素)完全不在屏幕上。如果你想以像素为单位指定它(通常是这种情况),你需要相应地设置你的转换管道。

但我完全不建议使用那些旧的和已弃用(并且可能很慢)的像素绘图功能(也不建议从不幸过时的红皮书中学习)。只需使用仅获取窗口坐标的自定义着色器绘制一个带纹理的四边形。

【讨论】:

好的,谢谢,我已经老了一百万倍,我正在做的事情已经过时了——在升级到 3.0 到 4.3 之前,我正在经历 2.0/2.1 版。我确定我已经告诉过你了? @EdwardBird 好吧,在这种情况下,当然第一部分仍然是相关的。鉴于您当前的透视投影,那些(20, 40) 是完全错误的。 (顺便说一句,没有人阻止你在 2.0 中编写适当的现代 OpenGL,最后没有人认真使用自 GL 1.1 以来的glBitmapglDrawPixels,而不仅仅是自 3.0 以来,但是好的,为了学习,请随意试试看)。 啊,我刚看完你的帖子把它改成了(0,0),现在我可以在屏幕上看到一些文字了,谢谢!

以上是关于用OpenGL绘制位图字体,glRasterPos2i()是做啥的?的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL 抗锯齿与 glAccum 和 glRasterPos

将 OpenGL 绘制到离屏位图

如何在 C++ 中将位图绘制为 OpenGL 纹理?

Opengl es 2.0 在视频上绘制位图叠加

OpenGL之位图的绘制和gluOrtho2D等函数详解

Android OpenGL 是不是具有用于绘制位图性能的离屏功能