在QGLWidget中绘制字符串的最简单方法

时间:2013-05-08 17:07:07

标签: c++ qt opengl

我正在使用QGLWidget创建一个initializeGL子类。 resizeGLpaintG L。一切都很好,我也可以用gluOrtho2D和3D绘制2D graphivcs。一切都很好。

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

我尝试使用QPainter,请记住使用end()方法和swapBuffers,但是......没有,文字会被渲染但是opengl的东西没有...

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

2 个答案:

答案 0 :(得分: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);
}

答案 1 :(得分:1)

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