我通常首先将文本渲染到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);
}