Итак, я пытался изучить OpenGL из learnopengl.com
, и сейчас я занимаюсь темой рендеринга текста, и я подумал о том, чтобы объединить текстуры масштабируемых шрифтов в моей программе в одну большую текстуру, но по какой-то причине я получаю исключение до н.э. glCopyImageSubData(...).
Сначала я пытаюсь измерить, насколько большой должна быть текстура, а затем копирую текстуры, которые я уже создал, в одну большую текстуру, и я довольно долго играл с этой функцией, но не могу найти решение.
Вот оригинальный код с текстурой, используемой для каждого лица.
Я пытался создать fbo
и прикрепить к нему текстуру, но после исследования я обнаружил, что эта функция мне гораздо понятнее, поэтому я решил использовать ее вместо этого.
Итак, я добавил xoffset
в структуру символов:
struct Character {
GLuint textureID;
glm::ivec2 size;
glm::ivec2 bearing;
GLuint advance;
GLuint xoffset;
};
Я добавляю это смещение к каждой грани в первом цикле for:
Character character = {
texture,
glm::ivec2(face->glyph->bitmap.width, face->glyph->bitmap.rows),
glm::ivec2(face->glyph->bitmap_left, face->glyph->bitmap_top),
face->glyph->advance.x,
font_texture_width
};
font_texture_width += character.size.x;
characters.insert(std::pair<GLchar, Character>(c, character));
А потом я пытаюсь вставить каждую текстуру лица в fontTexture:
glGenTextures(1, &fontTexture);
glBindTexture(GL_TEXTURE_2D, fontTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED,
font_texture_width, 100, 0, GL_RED, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
std::cout << glGetError();
for (GLubyte c = 0; c < 128; ++c)
glCopyImageSubData( characters[c].textureID, GL_TEXTURE_2D, 0, 0, 0, 0,
fontTexture, GL_TEXTURE_2D, 0, characters[c].xoffset, 0, 0,
characters[c].size.x, characters[c].size.y, 0);
Вот модифицированная функция renderText:
void renderText(Shader &s, std::string text, GLfloat x, GLfloat y, GLfloat scale, glm::vec3 color)
{
s.use();
s.setVec3("textColor", color);
glActiveTexture(GL_TEXTURE0);
glBindVertexArray(VAO);
std::string::const_iterator c;
glBindTexture(GL_TEXTURE_2D, fontTexture);
for (c = text.begin(); c != text.end(); ++c)
{
Character ch = characters[*c];
GLfloat xpos = x + ch.bearing.x * scale;
GLfloat ypos = y - (ch.size.y - ch.bearing.y) * scale;
GLfloat w = ch.size.x * scale;
GLfloat h = ch.size.y * scale;
GLfloat vertices[6][4] = {
{ xpos + characters[*c].xoffset, ypos + h, 0.0, 0.0 },
{ xpos + characters[*c].xoffset, ypos, 0.0, 1.0 },
{ xpos + w + characters[*c].xoffset, ypos, 1.0, 1.0 },
{ xpos + characters[*c].xoffset, ypos + h, 0.0, 0.0 },
{ xpos + w + characters[*c].xoffset, ypos, 1.0, 1.0 },
{ xpos + w + characters[*c].xoffset, ypos + h, 1.0, 0.0 }
};
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDrawArrays(GL_TRIANGLES, 0, 6);
x += (ch.advance >> 6) * scale;
}
glBindVertexArray(0);
glBindTexture(GL_TEXTURE_2D, 0);
}
Исключение выдается там, где я звоню glCopyImageSubData
Вот вся моя программа: https://pastebin.com/vAeeX3Xh
EDIT:
Теперь я понял, что было бы лучше использовать glTexSubImage2D, а не так, как это выглядит (вместо этого блока кода с glCopyImageSubData:
glGenTextures(1, &fontTexture);
glBindTexture(GL_TEXTURE_2D, fontTexture);
glTexImage2D(
GL_TEXTURE_2D,
0,
GL_RED,
face->glyph->bitmap.width * 250,
face->glyph->bitmap.rows * 250,
0,
GL_RED,
GL_UNSIGNED_BYTE,
NULL
);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
for (GLubyte c = 0; c < 128; ++c)
{
if (FT_Load_Char(face, c, FT_LOAD_RENDER))
{
std::cout << "ERROR::FREETYPE: Failed to load Glyph" << std::endl;
continue;
}
glTexSubImage2D(GL_TEXTURE_2D, 0, characters[c].xoffset, 0, characters[c].size.x, characters[c].size.y, GL_RED, GL_UNSIGNED_BYTE, face->glyph->bitmap.buffer);
}
Теперь, когда я рендерил эту текстуру, она выглядит так:
https://imgur.com/a/A0gDy6T