QOpenGLWidget 中QOpenGLBuffer 和freetype渲染汉字的程序
时间: 2024-06-09 14:04:50 浏览: 120
下面是一个在QOpenGLWidget中使用QOpenGLBuffer和freetype渲染汉字的程序。这个程序通过使用FreeType库,将一个Unicode字符串转换为纹理并将其渲染到OpenGL上下文中。
```cpp
#include <QtGui/QOpenGLFunctions>
#include <QtGui/QOpenGLShaderProgram>
#include <QtGui/QOpenGLBuffer>
#include <ft2build.h>
#include FT_FREETYPE_H
class TextRenderer : protected QOpenGLFunctions
{
public:
TextRenderer(QOpenGLWidget* widget)
: m_widget(widget)
, m_program(nullptr)
, m_vbo(QOpenGLBuffer::VertexBuffer)
, m_texture(0)
{
// Initialize FreeType library
FT_Library ft;
if (FT_Init_FreeType(&ft))
{
qWarning("Failed to initialize FreeType library");
return;
}
// Load font face
FT_Face face;
if (FT_New_Face(ft, "/path/to/font.ttf", 0, &face))
{
qWarning("Failed to load font face");
return;
}
// Set font size
FT_Set_Pixel_Sizes(face, 0, 48);
// Create shader program
m_program = new QOpenGLShaderProgram(m_widget);
m_program->addShaderFromSourceCode(QOpenGLShader::Vertex,
"attribute vec4 vertex;\n"
"uniform mat4 matrix;\n"
"varying vec2 texCoord;\n"
"void main() {\n"
" gl_Position = matrix * vertex;\n"
" texCoord = vertex.zw;\n"
"}\n"
);
m_program->addShaderFromSourceCode(QOpenGLShader::Fragment,
"uniform sampler2D texture;\n"
"uniform vec4 color;\n"
"varying vec2 texCoord;\n"
"void main() {\n"
" gl_FragColor = color * texture2D(texture, texCoord);\n"
"}\n"
);
m_program->link();
// Create VBO
GLfloat vertices[] = {
// Position TexCoord
0.0f, 1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 1.0f, 1.0f,
0.0f, 0.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f, 0.0f,
1.0f, 1.0f, 1.0f, 0.0f,
1.0f, 0.0f, 1.0f, 1.0f,
};
m_vbo.create();
m_vbo.bind();
m_vbo.allocate(vertices, sizeof(vertices));
// Create texture
glGenTextures(1, &m_texture);
glBindTexture(GL_TEXTURE_2D, m_texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// Set up font rendering parameters
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
// Clean up FreeType library
FT_Done_Face(face);
FT_Done_FreeType(ft);
}
~TextRenderer()
{
m_vbo.destroy();
glDeleteTextures(1, &m_texture);
delete m_program;
}
void renderText(const QString& text, const QPointF& position, const QColor& color)
{
if (!m_program)
return;
// Bind shader program
m_program->bind();
// Enable blending
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// Set color uniform
m_program->setUniformValue("color", color);
// Set matrix uniform
QMatrix4x4 matrix;
matrix.setToIdentity();
matrix.translate(position.x(), position.y(), 0.0f);
matrix.scale(textWidth(text), textHeight(text), 1.0f);
m_program->setUniformValue("matrix", matrix);
// Bind texture
glBindTexture(GL_TEXTURE_2D, m_texture);
// Enable vertex attribute array
m_program->enableAttributeArray("vertex");
m_program->setAttributeBuffer("vertex", GL_FLOAT, 0, 4);
// Render each character
GLfloat x = 0.0f;
GLfloat y = 0.0f;
for (int i = 0; i < text.length(); ++i)
{
renderChar(text[i], x, y);
}
// Disable vertex attribute array
m_program->disableAttributeArray("vertex");
// Disable blending
glDisable(GL_BLEND);
// Release shader program
m_program->release();
}
private:
QOpenGLWidget* m_widget;
QOpenGLShaderProgram* m_program;
QOpenGLBuffer m_vbo;
GLuint m_texture;
void renderChar(QChar character, GLfloat& x, GLfloat& y)
{
// Initialize FreeType library
FT_Library ft;
if (FT_Init_FreeType(&ft))
{
qWarning("Failed to initialize FreeType library");
return;
}
// Load font face
FT_Face face;
if (FT_New_Face(ft, "/path/to/font.ttf", 0, &face))
{
qWarning("Failed to load font face");
return;
}
// Set font size
FT_Set_Pixel_Sizes(face, 0, 48);
// Load glyph
if (FT_Load_Char(face, character.unicode(), FT_LOAD_RENDER))
{
qWarning("Failed to load glyph");
return;
}
// Create texture
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, face->glyph->bitmap.width, face->glyph->bitmap.rows, 0, GL_RED, GL_UNSIGNED_BYTE, face->glyph->bitmap.buffer);
// Calculate character position and advance
GLfloat xpos = x + face->glyph->bitmap_left;
GLfloat ypos = y - face->glyph->bitmap_top;
GLfloat w = face->glyph->bitmap.width;
GLfloat h = face->glyph->bitmap.rows;
x += (face->glyph->advance.x >> 6);
// Update vertex buffer with new character position and texture coordinates
GLfloat vertices[] = {
xpos, ypos + h, 0.0f, 0.0f,
xpos + w, ypos, 1.0f, 1.0f,
xpos, ypos, 0.0f, 1.0f,
xpos, ypos + h, 0.0f, 0.0f,
xpos + w, ypos + h, 1.0f, 0.0f,
xpos + w, ypos, 1.0f, 1.0f,
};
m_vbo.bind();
m_vbo.write(0, vertices, sizeof(vertices));
// Draw character
glDrawArrays(GL_TRIANGLES, 0, 6);
// Clean up FreeType library
FT_Done_Face(face);
FT_Done_FreeType(ft);
}
int textWidth(const QString& text)
{
int width = 0;
for (int i = 0; i < text.length(); ++i)
{
// Initialize FreeType library
FT_Library ft;
if (FT_Init_FreeType(&ft))
{
qWarning("Failed to initialize FreeType library");
return 0;
}
// Load font face
FT_Face face;
if (FT_New_Face(ft, "/path/to/font.ttf", 0, &face))
{
qWarning("Failed to load font face");
return 0;
}
// Set font size
FT_Set_Pixel_Sizes(face, 0, 48);
// Load glyph
if (FT_Load_Char(face, text[i].unicode(), FT_LOAD_RENDER))
{
qWarning("Failed to load glyph");
return 0;
}
// Add glyph advance to width
width += (face->glyph->advance.x >> 6);
// Clean up FreeType library
FT_Done_Face(face);
FT_Done_FreeType(ft);
}
return width;
}
int textHeight(const QString& text)
{
// Initialize FreeType library
FT_Library ft;
if (FT_Init_FreeType(&ft))
{
qWarning("Failed to initialize FreeType library");
return 0;
}
// Load font face
FT_Face face;
if (FT_New_Face(ft, "/path/to/font.ttf", 0, &face))
{
qWarning("Failed to load font face");
return 0;
}
// Set font size
FT_Set_Pixel_Sizes(face, 0, 48);
// Get font height
int height = face->size->metrics.height >> 6;
// Clean up FreeType library
FT_Done_Face(face);
FT_Done_FreeType(ft);
return height;
}
};
```
这个程序包含一个名为TextRenderer的类,它可以在QOpenGLWidget上渲染Unicode字符串。该类使用FreeType库将字符串转换为纹理,并使用QOpenGLBuffer和着色器程序将其渲染到OpenGL上下文中。要使用此类,请将其实例化并在QOpenGLWidget的paintGL()函数中调用renderText()函数。例如:
```cpp
void MyOpenGLWidget::paintGL()
{
// Initialize OpenGL functions
initializeOpenGLFunctions();
// Clear the background
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// Render some text
TextRenderer textRenderer(this);
textRenderer.renderText("你好,世界!", QPointF(0.0f, 0.0f), QColor(0, 0, 0));
}
```
在这个例子中,我们使用TextRenderer类在QOpenGLWidget上渲染“你好,世界!”。该字符串的颜色为黑色,并出现在左上角。
阅读全文