Вместо создания новых данных массива вершин для каждого символа, используйте одинаковые данные для всех символов.Добавьте матрицу модели в код шейдера:
in vec2 vertexCoord;
uniform mat4 projMatrix;
uniform mat4 modelMatrix;
void main()
{
// [...]
gl_Position = projMatrix * modelMatrix * vec4(vertexCoord.xy, 0.0, 1.0);
}
Для каждого символа рисуется прямоугольник от (0, 0) до (1, 1).Установите матрицу модели для каждого глифа, которая
- масштабирует символ до его размера
GLfloat w = ch.Size.x * scale;
GLfloat h = ch.Size.y * scale;
glm::mat4 scaleM = glm::scale(glm::mat4(1.0f), glm::vec3(w, h, 1.0f));
- перемещает символ на позицию в тексте (
char_x
увеличивается для каждого символа)
GLfloat xrel = char_x + ch.Bearing.x * scale;
GLfloat yrel = (ch.Size.y - ch.Bearing.y) * scale;
glm::mat4 transRelM = glm::translate(glm::mat4(1.0f), glm::vec3(xrel, yrel, 0.0f));
GLfloat angle_rad = atan2(dir.y, dir.x);
glm::mat4 rotateM = glm::rotate(glm::mat4(1.0f), angle_rad, glm::vec3(0.0f, 0.0f, 1.0f));
- перемещает текст в его начало
glm::mat4 transOriginM = glm::translate(glm::mat4(1.0f), glm::vec3(x, y, 0.0f));
Окончательная матрица модели:
glm::mat4 modelM = transOriginM * rotateM * transRelM * scaleM;
Примените это к своему коду, но не обязательно, чтобы при каждом вызове * 1030 обновлялся буфер массива вершин.,Достаточно один раз инициировать буфер:
void TextRender::RenderText(std::string text, GLfloat x, GLfloat y, GLfloat scale, glm::vec3 color, QMatrix4x4 projMatrix, glm::vec3 dir)
{
QOpenGLFunctions_4_5_Core *f = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_4_5_Core>();
TextRender::_program->bind();
f->glEnable(GL_BLEND);
f->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
f->glUniform3f(f->glGetUniformLocation(TextRender::_program->programId(), "textColor"), color.x, color.y, color.z);
TextRender::_program->setUniformValue(_program->uniformLocation("projection"), projMatrix);
f->glActiveTexture(GL_TEXTURE0);
f->glBindVertexArray(TextRender::VAO);
GLfloat vertices[6][4] = {
{ 0.0, 1.0, 0.0, 0.0 },
{ 0.0, 0.0, 0.0, 1.0 },
{ 1.0, 0.0, 1.0, 1.0 },
{ 0.0, 1.0, 0.0, 0.0 },
{ 1.0, 0.0, 1.0, 1.0 },
{ 1.0, 1.0, 1.0, 0.0 }
};
// Update content of VBO memory
f->glBindBuffer(GL_ARRAY_BUFFER, TextRender::VBO);
f->glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices); // Be sure to use glBufferSubData and not glBufferData
f->glBindBuffer(GL_ARRAY_BUFFER, 0);
GLfloat angle_rad = atan2(dir.y, dir.x);
glm::mat4 rotateM = glm::rotate(glm::mat4(1.0f), angle_rad, glm::vec3(0.0f, 0.0f, 1.0f));
glm::mat4 transOriginM = glm::translate(glm::mat4(1.0f), glm::vec3(x, y, 0.0f));
// Iterate through all characters
std::string::const_iterator c;
GLfloat char_x = 0.0f;
for (c = text.begin(); c != text.end(); c++)
{
Character ch = TextRender::Characters[*c];
GLfloat w = ch.Size.x * scale;
GLfloat h = ch.Size.y * scale;
GLfloat xrel = char_x + ch.Bearing.x * scale;
GLfloat yrel = (ch.Size.y - ch.Bearing.y) * scale;
// Now advance cursors for next glyph (note that advance is number of 1/64 pixels)
char_x += (ch.Advance >> 6) * scale; // Bitshift by 6 to get value in pixels (2^6 = 64 (divide amount of 1/64th pixels by 64 to get amount of pixels))
glm::mat4 scaleM = glm::scale(glm::mat4(1.0f), glm::vec3(w, h, 1.0f));
glm::mat4 transRelM = glm::translate(glm::mat4(1.0f), glm::vec3(xrel, yrel, 0.0f));
glm::mat4 modelM = transOriginM * rotateM * transRelM * scaleM;
QMatrix4x4 qtModelM(glm::value_ptr(modelM));
TextRender::_program->setUniformValue(_program->uniformLocation("modelMatrix"), qtModelM);
// Update VBO for each character
// Render glyph texture over quad
f->glBindTexture(GL_TEXTURE_2D, ch.TextureID);
// Render quad
f->glDrawArrays(GL_TRIANGLES, 0, 6);
}
f->glBindVertexArray(0);
f->glBindTexture(GL_TEXTURE_2D, 0);
f->glDisable(GL_BLEND);
TextRender::_program->release();
}
Если используется Математика OpenGL (GLM) для вычисления матрицы (в единственном числе используется метод glm::vec3
, так что это должно быть в порядке).Конечно, то же самое можно сделать с помощью Qt QMatrix4x4
(это было бы очень похоже).
В любом случае, для математики glm вы должны включить:
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>