精灵批次只绘制第一个精灵
Spritebatch only drawing first sprite
我已经实现了一个OpenGL精灵批处理,但是当对多个精灵使用相同的纹理时,它只绘制第一个精灵。例如:如果我使用它来渲染字符串"Hello"的字形,它只会渲染"H"。
我的着色器非常简单:
片段:
#version 150 core
uniform sampler2D tex;
in vec2 Texcoord;
out vec4 outColor;
void main()
{
outColor = texture(tex, Texcoord);
}
顶点:
#version 150 core
in vec3 position;
in vec2 texCoords;
out vec2 Texcoord;
void main()
{
Texcoord = texCoords;
gl_Position = vec4(position, 1.0f);
}
它们编译、链接和验证没有任何错误。
我的精灵批处理代码也非常简单。以下是我初始化精灵批处理的方法:
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);
}
相关文章:
- 为什么它只打印双链接列表的第一个值,而我的程序却崩溃了
- std::find,返回所有找到的值的替代方法,而不仅仅是存在重复的向量的第一个值
- 如何仅读取文本文件中的第一个值
- 在C++中,如何在第一个"system()"结束后执行第二个"system()"?
- 查找不在标准中的第一个值::设置<int>最小-最大值
- C++:忽略第一个 cin.ignore 之后的输入
- 在C++中打印多个矢量的第一个值
- C++去除前x个元素的有效方法,在不改变向量大小的情况下将第x+1个元素推到第一个
- C++第一个cout将不会打印
- 我们可以在第一个else-if条件结束后使用另一个else-if条件吗
- OpenGL:第二个VBO破坏了第一个VBO
- 为什么第一个Dynamic_cast没有投射到基类?
- OpenGL 2D游戏只绘制第二个精灵纹理而不是第一个
- C++ 为什么程序只读取第一个值
- 在我的第一个C++程序中需要一些帮助(简单)
- 为什么我的代码在第一个 if 语句处中断?
- 是否可以从另一个类对象调用一个类函数而不继承第一个类
- 无法使我的第一个Windows OpenGL窗口抬起并运行
- 将参数初始化为构造函数,而不是第一个
- 无法在硬件模式下创建 SGX 安全区 - "invalid launch token"即使文档将无效的启动令牌指定为第一个