当我在 mesh/face 中实现索引时,为什么 return 出现 OpenGl 错误?
when I implement indices into a mesh/face, why does it return an OpenGl error?
所以我有一个程序可以根据给定的顶点数据生成块网格。我已经让它在没有索引的情况下工作,但是在尝试将它们包含到我的程序中时,它 returns OpenGL 错误 1285.
我对不同的函数调用了 arraybuffer 和 vao,但它们看起来像这样:
void Chunk::_loadArrayBuffers()
{
glGenBuffers(1, &_trianglesID);
glGenBuffers(1, &_uvsID);
glGenBuffers(1, &_normalsID);
glGenBuffers(1, &_IndiceID);
glBindBuffer(GL_ARRAY_BUFFER, _trianglesID);
glBufferData(GL_ARRAY_BUFFER,
_triangles.size() * 3 * sizeof(GLfloat),
_triangles.data(),
GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, _uvsID);
glBufferData(GL_ARRAY_BUFFER,
_uvs.size() * 2 * sizeof(GLfloat),
_uvs.data(),
GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, _normalsID);
glBufferData(GL_ARRAY_BUFFER,
_normals.size() * 3 * sizeof(GLfloat),
_normals.data(),
GL_STATIC_DRAW);
if (_indices.size() * 3 > 0)
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _IndiceID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
_indices.size() * 3 * sizeof(GLfloat),
_indices.data(),
GL_STATIC_DRAW);
}
}
void Chunk::_makeVAO()
{
glGenVertexArrays(1, &_VAO);
glBindVertexArray(_VAO);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _trianglesID);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, _uvsID);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, _normalsID);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindVertexArray(0);
}
对于每个网格,我将每个三角形的顶点数据存储到多个 glm::vec3s 中,本质上是一个大小为 3 的向量。我的 rectangle/face 创建函数如下所示:
void Chunk::_addRectangle(glm::vec3 center, glm::vec3 height, glm::vec3 width, unsigned tex_num)
{
if (glm::length(height) == 0 || glm::length(width) == 0)
throw std::runtime_error("width or height should not be 0");
glm::vec3 corner1 = center - (height / 2.0) - (width / 2.0);
glm::vec3 corner2 = center - (height / 2.0) + (width / 2.0);
glm::vec3 corner3 = center + (height / 2.0) + (width / 2.0);
glm::vec3 corner4 = center + (height / 2.0) - (width / 2.0);
glm::vec3 normal = glm::cross(height, width);
glm::vec2 uv1;
glm::vec2 uv2;
glm::vec2 uv3;
glm::vec2 uv4;
if (fabs(normal[1]) == 1.0)
{
uv1 = glm::vec2(1.0 / _tex_atlas_width, 1);
uv2 = glm::vec2(1.0 / _tex_atlas_width, 0);
uv3 = glm::vec2(0, 0);
uv4 = glm::vec2(0, 1);
}
else
{
uv1 = glm::vec2(1.0 / _tex_atlas_width, height[1]);
uv2 = glm::vec2(1.0 / _tex_atlas_width, 0);
uv3 = glm::vec2(0, 0);
uv4 = glm::vec2(0, height[1]);
}
float add = (1.0 / double(_tex_atlas_width)) * tex_num;
uv1.x += add;
uv2.x += add;
uv3.x += add;
uv4.x += add;
// triangle 1
_triangles.push_back(corner3);
_triangles.push_back(corner2);
_triangles.push_back(corner1);
_normals.push_back(normal);
_normals.push_back(normal);
_normals.push_back(normal);
_uvs.push_back(uv1);
_uvs.push_back(uv2);
_uvs.push_back(uv3);
_indices.push_back(glm::vec3(nrOfIndices + 0, nrOfIndices + 1, nrOfIndices + 2));
// triangle 2
//_triangles.push_back(corner1);
_triangles.push_back(corner4);
//_triangles.push_back(corner3);
_normals.push_back(normal);
_normals.push_back(normal);
_normals.push_back(normal);
_uvs.push_back(uv3);
_uvs.push_back(uv4);
_uvs.push_back(uv1);
_indices.push_back(glm::vec3(nrOfIndices + 2, nrOfIndices + 3, nrOfIndices + 0));
nrOfIndices += 4;
}
一切正常,直到我尝试添加索引。它出什么问题了?我仔细检查了索引的顺序,它们似乎是正确的,所以我猜这是我加载索引的方式的错误,但我无法通过在 learnopengl 和其他网站上找到的内容来弄清楚opengl 文档。谢谢!
GL_ELEMENT_ARRAY_BUFFER
表示在 Vertex Array Object. See Index buffers 中。
说明
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _IndiceID);
将_IndiceID
关联到当前顶点数组对象。
在指定元素数组缓冲区之前,您必须绑定顶点数组对象:
glGenVertexArrays(1, &_VAO);
glBindVertexArray(_VAO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _IndiceID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
_indices.size() * 3 * sizeof(GLuint),
_indices.data(),
GL_STATIC_DRAW);
请注意,GL_ARRAY_BUFFER
也在 VAO 的状态向量中说明,但是当调用 glVertexAttribPointer
时会发生这种情况。
当调用 glVertexAttribPointer
时,当前绑定到目标 GL_ARRAY_BUFFER
的缓冲区将关联到具有指定索引的顶点属性。
造成GL_ELEMENT_ARRAY_BUFFER
和GL_ARRAY_BUFFER
的行为差异,因为一个VAO只能引用1个索引(元素)缓冲区,但它可以引用多个数组缓冲区。每个属性(索引)都可以关联到不同的缓冲区。
此外,索引的数据类型必须是整数。可能的数据类型分别为 (unsigned
) char
、short
int
,它们对应于 OpenGL 枚举常量 GL_UNSIGNED_BYTE
、GL_UNSIGNED_SHORT
或 GL_UNSIGNED_INT
。参见 glDrawElements
更改索引向量并使用 glm::ivec3
而不是 glm::vec3
std::vector<glm::ivec3> _indices;
_indices.push_back(glm::ivec3(nrOfIndices + 2, nrOfIndices + 3, nrOfIndices + 0));
glDrawElements(GL_TRIANGLES, _indices.size()*3, GL_UNSIGNED_INT, nullptr);
所以我有一个程序可以根据给定的顶点数据生成块网格。我已经让它在没有索引的情况下工作,但是在尝试将它们包含到我的程序中时,它 returns OpenGL 错误 1285.
我对不同的函数调用了 arraybuffer 和 vao,但它们看起来像这样:
void Chunk::_loadArrayBuffers()
{
glGenBuffers(1, &_trianglesID);
glGenBuffers(1, &_uvsID);
glGenBuffers(1, &_normalsID);
glGenBuffers(1, &_IndiceID);
glBindBuffer(GL_ARRAY_BUFFER, _trianglesID);
glBufferData(GL_ARRAY_BUFFER,
_triangles.size() * 3 * sizeof(GLfloat),
_triangles.data(),
GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, _uvsID);
glBufferData(GL_ARRAY_BUFFER,
_uvs.size() * 2 * sizeof(GLfloat),
_uvs.data(),
GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, _normalsID);
glBufferData(GL_ARRAY_BUFFER,
_normals.size() * 3 * sizeof(GLfloat),
_normals.data(),
GL_STATIC_DRAW);
if (_indices.size() * 3 > 0)
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _IndiceID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
_indices.size() * 3 * sizeof(GLfloat),
_indices.data(),
GL_STATIC_DRAW);
}
}
void Chunk::_makeVAO()
{
glGenVertexArrays(1, &_VAO);
glBindVertexArray(_VAO);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _trianglesID);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, _uvsID);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, _normalsID);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindVertexArray(0);
}
对于每个网格,我将每个三角形的顶点数据存储到多个 glm::vec3s 中,本质上是一个大小为 3 的向量。我的 rectangle/face 创建函数如下所示:
void Chunk::_addRectangle(glm::vec3 center, glm::vec3 height, glm::vec3 width, unsigned tex_num)
{
if (glm::length(height) == 0 || glm::length(width) == 0)
throw std::runtime_error("width or height should not be 0");
glm::vec3 corner1 = center - (height / 2.0) - (width / 2.0);
glm::vec3 corner2 = center - (height / 2.0) + (width / 2.0);
glm::vec3 corner3 = center + (height / 2.0) + (width / 2.0);
glm::vec3 corner4 = center + (height / 2.0) - (width / 2.0);
glm::vec3 normal = glm::cross(height, width);
glm::vec2 uv1;
glm::vec2 uv2;
glm::vec2 uv3;
glm::vec2 uv4;
if (fabs(normal[1]) == 1.0)
{
uv1 = glm::vec2(1.0 / _tex_atlas_width, 1);
uv2 = glm::vec2(1.0 / _tex_atlas_width, 0);
uv3 = glm::vec2(0, 0);
uv4 = glm::vec2(0, 1);
}
else
{
uv1 = glm::vec2(1.0 / _tex_atlas_width, height[1]);
uv2 = glm::vec2(1.0 / _tex_atlas_width, 0);
uv3 = glm::vec2(0, 0);
uv4 = glm::vec2(0, height[1]);
}
float add = (1.0 / double(_tex_atlas_width)) * tex_num;
uv1.x += add;
uv2.x += add;
uv3.x += add;
uv4.x += add;
// triangle 1
_triangles.push_back(corner3);
_triangles.push_back(corner2);
_triangles.push_back(corner1);
_normals.push_back(normal);
_normals.push_back(normal);
_normals.push_back(normal);
_uvs.push_back(uv1);
_uvs.push_back(uv2);
_uvs.push_back(uv3);
_indices.push_back(glm::vec3(nrOfIndices + 0, nrOfIndices + 1, nrOfIndices + 2));
// triangle 2
//_triangles.push_back(corner1);
_triangles.push_back(corner4);
//_triangles.push_back(corner3);
_normals.push_back(normal);
_normals.push_back(normal);
_normals.push_back(normal);
_uvs.push_back(uv3);
_uvs.push_back(uv4);
_uvs.push_back(uv1);
_indices.push_back(glm::vec3(nrOfIndices + 2, nrOfIndices + 3, nrOfIndices + 0));
nrOfIndices += 4;
}
一切正常,直到我尝试添加索引。它出什么问题了?我仔细检查了索引的顺序,它们似乎是正确的,所以我猜这是我加载索引的方式的错误,但我无法通过在 learnopengl 和其他网站上找到的内容来弄清楚opengl 文档。谢谢!
GL_ELEMENT_ARRAY_BUFFER
表示在 Vertex Array Object. See Index buffers 中。
说明
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _IndiceID);
将_IndiceID
关联到当前顶点数组对象。
在指定元素数组缓冲区之前,您必须绑定顶点数组对象:
glGenVertexArrays(1, &_VAO);
glBindVertexArray(_VAO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _IndiceID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
_indices.size() * 3 * sizeof(GLuint),
_indices.data(),
GL_STATIC_DRAW);
请注意,GL_ARRAY_BUFFER
也在 VAO 的状态向量中说明,但是当调用 glVertexAttribPointer
时会发生这种情况。
当调用 glVertexAttribPointer
时,当前绑定到目标 GL_ARRAY_BUFFER
的缓冲区将关联到具有指定索引的顶点属性。
造成GL_ELEMENT_ARRAY_BUFFER
和GL_ARRAY_BUFFER
的行为差异,因为一个VAO只能引用1个索引(元素)缓冲区,但它可以引用多个数组缓冲区。每个属性(索引)都可以关联到不同的缓冲区。
此外,索引的数据类型必须是整数。可能的数据类型分别为 (unsigned
) char
、short
int
,它们对应于 OpenGL 枚举常量 GL_UNSIGNED_BYTE
、GL_UNSIGNED_SHORT
或 GL_UNSIGNED_INT
。参见 glDrawElements
更改索引向量并使用 glm::ivec3
而不是 glm::vec3
std::vector<glm::ivec3> _indices;
_indices.push_back(glm::ivec3(nrOfIndices + 2, nrOfIndices + 3, nrOfIndices + 0));
glDrawElements(GL_TRIANGLES, _indices.size()*3, GL_UNSIGNED_INT, nullptr);