Я недавно отправил вопрос Вот и я сделал как было посоветовал мне @genpfault (Спасибо за это :]). Проблема моя рисование шрифта все еще занимает очень много времени.
Я храню все вершины шрифта и текскорды в одном 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 только один раз и заполнить VBO glBufferSubData
Я попробовал, и ничего не изменилось. Я получаю то же самое время, что и раньше.
У меня была идея выделить пространство std::vector
Но это тоже не помогло.
Одна проблема, которую я вижу, состоит в том, что вы делаете это для каждого кадра, который вы рендерите:
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.
Затем ваш фрагментный шейдер будет использовать индекс цвета, чтобы закрасить символ на основе индекса. Это будет действительно небольшая оптимизация, которая сделает ваш код более сложным. Но это значительно уменьшит размер вашего буфера. Это также может помочь вам улучшить производительность