0

我正在创建一个QGLWidget子类initializeGLresizeGLpaintGL. 一切都很好,我也可以用 gluOrtho2D 和 3D 绘制 2D 图形。一切都很好。

现在我需要绘制一些文本,没有文本旋转,没有文本变形,没有特定的字体。第一次试验是使用 glut 引擎,但程序不断崩溃,所以我认为 QGLWidget glut 在这种情况下不起作用。

我试过了QPainter,记得也使用end()方法swapBuffers,但是..什么都没有,文本被渲染但是opengl的东西没有..

在 QGLWidget 上绘制一些文本的最简单方法是什么?

4

2 回答 2

3

我通常首先将文本渲染到QImage中,然后使用glTexSubImage2D将其内容复制到纹理中。然后我画了一个带纹理的四边形。

来自实际项目的代码

void displayText(QString const &text, bool render_text)
{
    if(!text_texture) {
        glGenTextures(1, &text_texture);
    }

    glActiveTexture(GL_TEXTURE0); gltPrintMultiError("glActiveTexture");
    glBindTexture(GL_TEXTURE_2D, text_texture); gltPrintMultiError("glBindTexture");

    int tex_width, tex_height;
    glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &tex_width); gltPrintMultiError("glGetTexLevelParameteriv GL_TEXTURE_WIDTH");
    glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &tex_height); gltPrintMultiError("glGetTexLevelParameter GL_TEXTURE_HEIGHT");

    if(tex_width != text_width || tex_height != text_height ) {
        render_text = true;
        tex_width = text_width;
        tex_height = text_height;
        glTexImage2D(
            GL_TEXTURE_2D, 0, GL_RGB8,
            tex_width, tex_height, 0,
            GL_RGB, GL_UNSIGNED_BYTE, NULL);
        gltPrintMultiError("glTexImage2D");
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    }

    if(render_text) {
        QImage textimg(tex_width, tex_height, QImage::Format_RGB888);
        {
            QPainter painter(&textimg);
            painter.fillRect(0, 0, tex_width, tex_height, QColor(0,0,0));
            painter.setBrush(QColor(255, 255, 255));
            painter.setPen(QColor(255, 255, 255));
            painter.setFont(QFont("Sans", 15));
            painter.drawText(5, 20, text);
        }

        glPixelStorei(GL_UNPACK_SWAP_BYTES,   GL_FALSE);
        glPixelStorei(GL_UNPACK_LSB_FIRST,    GL_FALSE);
        glPixelStorei(GL_UNPACK_ROW_LENGTH,   0);
        glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
        glPixelStorei(GL_UNPACK_SKIP_ROWS,    0);
        glPixelStorei(GL_UNPACK_SKIP_PIXELS,  0);
        glPixelStorei(GL_UNPACK_SKIP_IMAGES,  0);
        glPixelStorei(GL_UNPACK_ALIGNMENT,    4);

        glTexSubImage2D(
            GL_TEXTURE_2D, 0,
            0, 0,
            tex_width, tex_height,
            GL_RGB, GL_UNSIGNED_BYTE, textimg.constBits() );
    }

    static GLfloat const pos[] = {
        0, 1,
        1, 1,
        1, 0,
        0, 0
    };
    static GLfloat const tex[] = {
        0, 0,
        1, 0,
        1, 1,
        0, 1
    };

    glUseProgram(frame2d.program);

    /* frame2d is a program consisting of the
       following vertex and fragment shaders:
// Vertex Shader
#version 330    
in vec2 position;
in vec2 texcoord;    
out vec2 vert_tex;
void main()
{
    vert_tex = texcoord;
    gl_Position = vec4(position*2 - 1., 0, 1);
}

// Fragment Shader
#version 330
uniform sampler2D frame;
in vec2 vert_tex;    
void main()
{
    gl_FragColor = texture(frame, vert_tex);
}
    */

    glEnableVertexAttribArray(frame2d.attrib_position);
    glEnableVertexAttribArray(frame2d.attrib_texcoord);

    glVertexAttribPointer(frame2d.attrib_position, 2, GL_FLOAT, GL_FALSE, 0, pos);
    gltPrintMultiError("glVertexAttribPointer(attrib_position, ...)");
    glVertexAttribPointer(frame2d.attrib_texcoord, 2, GL_FLOAT, GL_FALSE, 0, tex);
    gltPrintMultiError("glVertexAttribPointer(attrib_texcoord, ...)");
    glUniform1i(frame2d.uniform_sampler_frame, 0);
    gltPrintMultiError("glUniform1i(frame2d.uniform_sampler_frame)");

    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR);

    glViewport(0, 0, tex_width, tex_height);

    glDisable(GL_DEPTH_TEST);
    glDepthMask(0);
    glColorMask(1,1,1,1);

    glDrawArrays(GL_QUADS, 0, 4);

    glDisableVertexAttribArray(frame2d.attrib_position);
    glDisableVertexAttribArray(frame2d.attrib_texcoord);
    glUseProgram(0);

    glBindTexture(GL_TEXTURE_2D, 0);
}
于 2013-05-08T18:02:29.037 回答
2

我不知道,但QGLWidget 类中还内置了renderText方法。

于 2013-05-12T09:16:46.657 回答