加快文本渲染性能openGL
Speed up text rendering performance openGL
我使用 FreeType 库提取每个字形信息,例如宽度、高度和位图。这是在 init 函数中完成的,我不太关心它花费的时间。我将每个角色信息存储在地图容器中,以便以后可以轻松访问每个角色。
在渲染时,我读取字符串并使用字符串迭代器遍历每个字符,并使用字形参数创建要在其上绘制位图的多边形。
多边形是使用 VAO 和 VBO 绘制的
为了让它透明,我使用了混合,着色器用于着色。
这是我的渲染函数的样子:
void CFreeType::RenderText(std::string text, int posX, int posY, Vector3d color)
{
ViewOrtho(RESx, RESy);
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_DEPTH_TEST);
textShader->Use();
glUniform3dv(textColor_uniform_location, 1, color.v);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
this->x = posX;
this->y = posY + FontHeight;
std::string::const_iterator c;
for(c = text.begin(); c != text.end(); c++)
{
//Load character from map
Character ch = Characters[*c];
//If we hit the '^' character, we probably want to change the text color
if(*c == '^')
{
//Check if the next character is a number, if so, change the text color and skip this character.
c++;
ch = Characters[*c];
if(isdigit(*c))
{
glUniform3dv(glGetUniformLocation(textShader->GetProgram(), "textColor"), 1, Color[*c-48].v); // *c-48 for conversion from ASCII to in int - '0' == 48
continue;
}
//In the other case go back to previous character ('^').
else
{
c--;
ch = Characters[*c];
}
}
//If we hit a new line character, move the new line below the previous and skip this character.
else if(*c == '\n')
{
x = posX;
y += FontHeight;
continue;
}
//If we hit tab character, insert 4 spaces
else if(*c == '\t')
{
x += (Characters[' '].AdvanceX >> 6) << 2; //Bit shifting is hopefuly a bit faster than multiplying/dividing.
continue;
}
xpos = x + ch.Bearing.x;
ypos = y - ch.Bearing.y;
font_width = ch.Size.x;
font_height = ch.Size.y;
float vertices[6][4] = {
{xpos, ypos, 0.0, 0.0},
{xpos, ypos + this->font_height, 0.0, 1.0},
{xpos + this->font_width, ypos + this->font_height, 1.0, 1.0},
{xpos, ypos, 0.0, 0.0},
{xpos + this->font_width, ypos + this->font_height, 1.0, 1.0},
{xpos + this->font_width, ypos, 1.0, 0.0}
};
//Render character
glBindTexture(GL_TEXTURE_2D, ch.TextureID);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
glDrawArrays(GL_TRIANGLES, 0, 6);
x += (ch.AdvanceX >> 6);
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
ViewPerspective();
textShader->StopShader();
glDisable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
glDisable(GL_TEXTURE_2D);
}
我正在考虑使用显示列表而不是 VBO,但我认为它不会有任何改进。
绘制了大约 400 个字符后,我的帧率只有 165FPS 左右,而在没有渲染任何字符的情况下,我的帧率几乎达到了 390FPS。
如果能帮助我提高文本渲染性能,我将不胜感激。
纹理绑定和glDrawArrays()
每个字符?不是最好的方法。
最小化纹理绑定和绘制调用的数量:
- Glom all your glyphs into (ideally) a single texture atlas
- 将一帧文本的所有顶点信息放入单个 VBO
- 通过一次
glDrawArrays()
调用 绘制框架的所有字符串
我使用 FreeType 库提取每个字形信息,例如宽度、高度和位图。这是在 init 函数中完成的,我不太关心它花费的时间。我将每个角色信息存储在地图容器中,以便以后可以轻松访问每个角色。
在渲染时,我读取字符串并使用字符串迭代器遍历每个字符,并使用字形参数创建要在其上绘制位图的多边形。
多边形是使用 VAO 和 VBO 绘制的
为了让它透明,我使用了混合,着色器用于着色。
这是我的渲染函数的样子:
void CFreeType::RenderText(std::string text, int posX, int posY, Vector3d color)
{
ViewOrtho(RESx, RESy);
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_DEPTH_TEST);
textShader->Use();
glUniform3dv(textColor_uniform_location, 1, color.v);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
this->x = posX;
this->y = posY + FontHeight;
std::string::const_iterator c;
for(c = text.begin(); c != text.end(); c++)
{
//Load character from map
Character ch = Characters[*c];
//If we hit the '^' character, we probably want to change the text color
if(*c == '^')
{
//Check if the next character is a number, if so, change the text color and skip this character.
c++;
ch = Characters[*c];
if(isdigit(*c))
{
glUniform3dv(glGetUniformLocation(textShader->GetProgram(), "textColor"), 1, Color[*c-48].v); // *c-48 for conversion from ASCII to in int - '0' == 48
continue;
}
//In the other case go back to previous character ('^').
else
{
c--;
ch = Characters[*c];
}
}
//If we hit a new line character, move the new line below the previous and skip this character.
else if(*c == '\n')
{
x = posX;
y += FontHeight;
continue;
}
//If we hit tab character, insert 4 spaces
else if(*c == '\t')
{
x += (Characters[' '].AdvanceX >> 6) << 2; //Bit shifting is hopefuly a bit faster than multiplying/dividing.
continue;
}
xpos = x + ch.Bearing.x;
ypos = y - ch.Bearing.y;
font_width = ch.Size.x;
font_height = ch.Size.y;
float vertices[6][4] = {
{xpos, ypos, 0.0, 0.0},
{xpos, ypos + this->font_height, 0.0, 1.0},
{xpos + this->font_width, ypos + this->font_height, 1.0, 1.0},
{xpos, ypos, 0.0, 0.0},
{xpos + this->font_width, ypos + this->font_height, 1.0, 1.0},
{xpos + this->font_width, ypos, 1.0, 0.0}
};
//Render character
glBindTexture(GL_TEXTURE_2D, ch.TextureID);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
glDrawArrays(GL_TRIANGLES, 0, 6);
x += (ch.AdvanceX >> 6);
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
ViewPerspective();
textShader->StopShader();
glDisable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
glDisable(GL_TEXTURE_2D);
}
我正在考虑使用显示列表而不是 VBO,但我认为它不会有任何改进。
绘制了大约 400 个字符后,我的帧率只有 165FPS 左右,而在没有渲染任何字符的情况下,我的帧率几乎达到了 390FPS。
如果能帮助我提高文本渲染性能,我将不胜感激。
纹理绑定和glDrawArrays()
每个字符?不是最好的方法。
最小化纹理绑定和绘制调用的数量:
- Glom all your glyphs into (ideally) a single texture atlas
- 将一帧文本的所有顶点信息放入单个 VBO
- 通过一次
glDrawArrays()
调用 绘制框架的所有字符串