В настоящее время я ищу узкие места в своем коде, и, оказывается, GUI является одним из них. Ну, на самом деле не GUI, а динамический текст, который там нарисован.FreeType OpenGL dynamic Text = abysmal performance
Initialization
if (FT_Init_FreeType(&m_FreeType))
throw Helpers::ExceptionWithMsg("Could not init freetype lib");
if (FT_New_Face(m_FreeType, "res\\fonts\\FreeSans.ttf", 0, &m_FontFace))
throw Helpers::ExceptionWithMsg("Could not open font");
m_ShaderID = ... // Loads the corresponding shader
m_TextColorLocation = glGetUniformLocation(m_ShaderID, "color");
m_CoordinatesLocation = glGetAttribLocation(m_ShaderID, "coord");
glGenBuffers(1, &m_VBO);
FT_Set_Pixel_Sizes(m_FontFace, 0, m_FontSize);
glyph = m_FontFace->glyph;
glGenTextures(1, &m_Texture);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_Texture);
// We require 1 byte alignment when uploading texture data
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// Linear filtering usually looks best for text
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// Clamping to edges is important to prevent artifacts when scaling
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glUseProgram(m_ShaderID);
glUniform4f(m_TextColorLocation, m_TextColor.x, m_TextColor.y, m_TextColor.z, m_TextColor.w);
glUseProgram(0);
Что я делаю: я инициализировать FreeType, получить шрифт, инициализировать шейдер и все формы.
Затем я создаю vbo для текстурыCoordinates, устанавливаю пиксели для шрифта, получаю глиф.
Теперь я создаю текстуру, активирую ее, привязываю ... Я хочу установить все параметры, а затем униформу, которая никогда не изменится.
Rendering:
glUseProgram(m_ShaderID);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_Texture);
// Linear filtering usually looks best for text
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// Set up the VBO for our vertex data
glEnableVertexAttribArray(m_CoordinatesLocation);
glBindBuffer(GL_ARRAY_BUFFER, m_VBO);
glVertexAttribPointer(m_CoordinatesLocation, 4, GL_FLOAT, GL_FALSE, 0, 0);
GLfloat cursorPosX = m_X;
GLfloat cursorPosY = m_Y;
for (size_t i = 0; i < m_Text.size(); ++i)
{
// If Loading a char fails, just continue
if (FT_Load_Char(m_FontFace, m_Text[i], FT_LOAD_RENDER))
continue;
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, glyph->bitmap.width, glyph->bitmap.rows, 0, GL_ALPHA, GL_UNSIGNED_BYTE, glyph->bitmap.buffer);
// Calculate the vertex and texture coordinates
GLfloat x2 = cursorPosX + glyph->bitmap_left * m_SX;
GLfloat y2 = -cursorPosY - glyph->bitmap_top * m_SY;
GLfloat w = glyph->bitmap.width * m_SX;
GLfloat h = glyph->bitmap.rows * m_SY;
PointStruct box[4] =
{
{ x2, -y2, 0, 0 },
{ x2 + w, -y2, 1, 0 },
{ x2, -y2 - h, 0, 1 },
{ x2 + w, -y2 - h, 1, 1 }
};
// Draw the character on the screen
glBufferData(GL_ARRAY_BUFFER, sizeof box, box, GL_DYNAMIC_DRAW);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
// Advance the cursor to the start of the next character
cursorPosX += glyph->advance.x/64 * m_SX;
cursorPosY += glyph->advance.y/64 * m_SY;
}
glDisableVertexAttribArray(m_CoordinatesLocation);
glDeleteTextures(1, &m_Texture);
glDisable(GL_BLEND);
glUseProgram(0);
Установка шейдера и прочее очевидна.
Для каждого вызова рендеринга я активирую текстуру, привязываю ее, активирую VBO. Я храню свою текстуру. В этом случае я перебираю каждый символ в тексте, загружая его с помощью FT_LOAD_CHAR. Затем я указываю текстуру с glTexImage2D, вычисляю координаты вершин и текстур и рисую все.
Это кажется очень неэффективным, но я не вижу возможности улучшить производительность и, тем не менее, иметь читаемый текст.
Я хотел установить параметры текста только один раз в init -> все символы - это поля.
Я хотел установить GL_DYNAMIC_DRAW для GL_STATIC_DRAW ... не так много. Что еще я могу сделать?
Текст, который я визуализирую, является динамическим, он меняет (или может меняться) каждый кадр, поэтому я как бы застрял.
Я запрашиваю выполнение этого материала с запросом. Если я не выдаю динамический текст, он очень низок, но если я создам динамический текст, он становится очень высоким ... в этом проходе не так много, просто рисует графический интерфейс.
Что действительно беспокоит меня
Одна вещь, которую я действительно не понимаю (может быть солнечный день ...)
Если я не установлю линейной фильтрации в методе визуализации,() Я получаю странные кубики-глифы, но почему? OpenGL - это конечный автомат, параметры текстуры устанавливаются на привязку к текущей. Итак, если я устанавливаю фильтр Min и Mag в GL_LINEAR в инициализации, почему этого недостаточно?
Если я удаляю эти 2 строки в рендере, я получаю лучшую производительность по запросу (гораздо более низкие номера), но он не нарисовал ничего читаемого.
О вашем втором вопросе (глифы?), Ваша текстура, вероятно, не завершена. Поиск «полнота текстуры opengl». –