Я реализовал OpenGL spritebatch, но только рисовал первый спрайт при использовании одной и той же текстуры для нескольких спрайтов. Например: если я использую его для отображения глифов для строки "Hello", он отображает только "H".
Мои шейдеры очень просты:
Фрагмент:
#version 150 core
uniform sampler2D tex;
in vec2 Texcoord;
out vec4 outColor;
void main()
{
outColor = texture(tex, Texcoord);
}
Vertex:
#version 150 core
in vec3 position;
in vec2 texCoords;
out vec2 Texcoord;
void main()
{
Texcoord = texCoords;
gl_Position = vec4(position, 1.0f);
}
И они компилируют, связывают и проверяют без каких-либо ошибок.
Мой спрайт-код также довольно прост. Вот как я инициализирую пакет Sprite:
glGenVertexArrays(1, &mVao);
glBindVertexArray(mVao);
// INDEX BUFFER
glGenBuffers(1, &mEbo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mEbo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 0, NULL, GL_STREAM_DRAW);
// VERTEX BUFFER
glGenBuffers(1, &mVbo);
glBindBuffer(GL_ARRAY_BUFFER, mVbo);
glBufferData(GL_ARRAY_BUFFER, 0, NULL, GL_STREAM_DRAW);
// POS ATTRIB
GLint posAttrib;
posAttrib = glGetAttribLocation(mShader.getProgram(), "position");
glEnableVertexAttribArray(posAttrib);
glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), 0);
// TEX ATTRIB
GLint texAttrib;
texAttrib = glGetAttribLocation(mShader.getProgram(), "texCoords");
glEnableVertexAttribArray(texAttrib);
glVertexAttribPointer(texAttrib, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
И, наконец, вот как я рисую:
glBindVertexArray(mVao);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mEbo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLuint), &indices[0], GL_STREAM_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, mVbo);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), &vertices[0], GL_STREAM_DRAW);
glDrawElements(GL_TRIANGLES, (GLsizei)indices.size(), GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
Насколько я могу сказать, OpenGL не вызывает ошибок, vertices
и indices
содержат правильные данные.
Прошу прощения за количество кода, но из-за того, что я не получаю никаких ошибок, у меня нет никаких указаний, где это происходит. Когда я отлаживаю код, я не вижу никаких значений, которые неуместны или неправильны.
РЕДАКТИРОВАТЬ
Код, который я использую для создания векторов вершин и индексов, таков:
for(int i = 0; i < currentSprites.size(); ++i)
{
Sprite* current = currentSprites.at(i);
// 4 * (2 (pos) + 2 (tex))
float verticesArray[16] =
{
// TOP LEFT
current->x,
current->y,
(float)current->textureRect.x / (float)current->texture.w,
(float)current->textureRect.y / (float)current->texture.h,
// TOP RIGHT
current->x + current->w,
current->y,
(float)(current->textureRect.x + current->textureRect.w) / (float)current->texture.w,
(float)current->textureRect.y / (float)current->texture.h,
// BOTTOM RIGHT
current->x + current->w,
current->y + current->h,
(float)(current->textureRect.x + current->textureRect.w) / (float)current->texture.w,
(float)(current->textureRect.y + current->textureRect.h) / (float)current->texture.h,
// BOTTOM LEFT
current->x,
current->y + current->h,
(float)current->textureRect.x / (float)current->texture.w,
(float)(current->textureRect.y + current->textureRect.h) / (float)current->texture.h
};
for(int v = 0; v < 16; v += 4)
{
float zPos = -(float)current->layer / 100.0f;
// Projection matrix
glm::vec4 result = mCamera.getProjectionMatrix() * glm::vec4(verticesArray[v], verticesArray[v+1], zPos, 1.0f); // This is just an orthographic projection matrix
verticesArray[v] = result.x;
verticesArray[v+1] = result.y;
zPos = result.z;
vertices.push_back(Vertex(glm::vec3(verticesArray[v], verticesArray[v + 1], zPos),
glm::vec2(verticesArray[v + 2], verticesArray[v + 3])));
}
static GLuint _indices[6] =
{
0, 1, 3, 3, 1, 2
};
for(int index = 0; index < 6; ++index)
{
indices.push_back(_indices[index]);
}
}
Я думаю, что проблема заключается в вашем индексном буфере. Вы дозируете вершины для всех глифов в один и тот же VBO и рисуете их одним призывом рисования (что является хорошим подходом). Однако для каждого glypgh вы добавляете те же 6 индексов:
static GLuint _indices[6] =
{
0, 1, 3, 3, 1, 2
};
for(int index = 0; index < 6; ++index)
{
indices.push_back(_indices[index]);
}
Таким образом, по сути, ваш код будет рисовать первый квад снова и снова, никогда не используя ни одну из вершин, которые вы добавили после этого.
Вам нужно компенсировать индексы для каждого глифа, который вы рисуете, например:
for(int index = 0; index < 6; ++index)
{
indices.push_back(_indices[index] + 4*i);
}
+4 * i
потому что на глиф приходится 4 вершины. Это исправило это.
indices
и массивыvertices
.