我最近发布了一个问题here,我做了adviced me by @genpfault(感谢您:])。问题是,我的字体仍然花费很长时间来绘制。
我将所有字体顶点和texcoords存储在一个std::vector
容器中,颜色存储在另一个std::vector
中,然后使用VBO(在流模式下)绘制它。
我正在收集当前帧的数据,如下所示:
void CFreeType::RenderText(std::string text, int posX, int posY, Vector3d color)
{
std::string::const_iterator c;
for(c = text.begin(); c != text.end(); c++)
{
//Load character from map
Character ch = Characters[*c];
/*I know it's embarrassing, but I don't know, how can I use
only one Colors.push_back(newColor); so it applies to one face.
Right now I have to color each vertex. I guess it can be set somewhere in VBO*/
Vert_and_TexCoords.push_back(Vec4f(xpos, ypos, ch.texCoordOffset.x, ch.texCoordOffset.y));
Colors.push_back(newColor);
Vert_and_TexCoords.push_back(Vec4f(xpos, ypos + ch.Size.y, ch.texCoordOffset.x, ch.texCoordOffset2.y));
Colors.push_back(newColor);
Vert_and_TexCoords.push_back(Vec4f(xpos + ch.Size.x, ypos + ch.Size.y, ch.texCoordOffset2.x, ch.texCoordOffset2.y));
Colors.push_back(newColor);
Vert_and_TexCoords.push_back(Vec4f(xpos, ypos, ch.texCoordOffset.x, ch.texCoordOffset.y));
Colors.push_back(newColor);
Vert_and_TexCoords.push_back(Vec4f(xpos + ch.Size.x, ypos + ch.Size.y, ch.texCoordOffset2.x, ch.texCoordOffset2.y));
Colors.push_back(newColor);
Vert_and_TexCoords.push_back(Vec4f(xpos + ch.Size.x, ypos, ch.texCoordOffset2.x, ch.texCoordOffset.y));
Colors.push_back(newColor);
}
}
这是我的绘图功能:
void CFreeType::TextPopBack()
{
textShader->Use();
//Bind VBO
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, Vert_and_TexCoords.size() * sizeof(Vec4f) + Colors.size() * sizeof(Color3f), 0, GL_STREAM_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, Vert_and_TexCoords.size() * sizeof(Vec4f), Vert_and_TexCoords.data());
glBufferSubData(GL_ARRAY_BUFFER, Vert_and_TexCoords.size() * sizeof(Vec4f), Colors.size() * sizeof(Color3f), Colors.data());
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, (void*)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*)(Vert_and_TexCoords.size() * sizeof(Vec4f)));
glDrawArrays(GL_TRIANGLES, 0, Vert_and_TexCoords.size());
//Unbind VBO
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
textShader->StopShader();
Vert_and_TexCoords.clear();
Colors.clear();
}
我想让文本呈现灵活,所以静态VBO缓冲区大小不是很好的方法 此外,文本着色不是以我在代码注释中注意到的最佳方式完成的,但我希望能够使用用户指定的颜色为每个字母着色。
着色器很好,我希望。如果有人有兴趣,我会发布它们 现在需要大约40毫秒才能呈现 400个字母。
编辑:正如你们建议只在VBO缓冲区中分配大量数据并用glBufferSubData
填充VBO一样,我试了一下,没有任何改变。我和以前一样
我有一个分配std::vector
的空间的想法,但它也没有帮助。
答案 0 :(得分:0)
我看到的一个问题是你为每个呈现的帧执行此操作:
glBufferData(GL_ARRAY_BUFFER, Vert_and_TexCoords.size() * sizeof(Vec4f) + Colors.size() * sizeof(Color3f), 0, GL_STREAM_DRAW);
每次渲染时都要分配内存。根据给定的信息,我假设您这样做是因为每次渲染文本时文本的数量都会发生变化。我不是每帧都分配这个,而是尝试创建一个更大的固定缓冲区,并使用glbuffersubdata()来填充所需的位。我认为这应该比每帧重新分配缓冲区更快。这只是您可以尝试的一种优化。
编辑:我的另一个建议是,不是每个字符发送3个浮点数作为1种颜色,也许你应该使用颜色索引。伪代码示例:
Color 1 = 1.0f, 0.0f, 0.0f // red
Color 2 = 0.0f, 1.0f, 0.0f // green
// Text format = [color index] [character] ... and so on
String = 2 'a' 1 'b' 1 'c' 2 'd'
This will render 'a' and 'd' as green; and 'b'/'c' will be rendered as red.
然后,您的片段着色器将使用颜色索引根据索引在字符中着色。这将是一个非常小的优化,这将使您的代码更复杂。但它会显着减小缓冲区的大小。这也可以帮助您提高性能