我正在尝试更新我的引擎,它曾经使用OpenGL 2.x风格的顶点数组,现在需要更新到VAOs/VBOs以适应OpenGL 3.x。我认为我没有正确地绑定VBO。请阅读下面获取更多信息或跳转到代码并查找我的错误。
我的网格类快速概述如下:
Mesh
- 根MeshNode MeshNode - 变换 - VAO索引 - 索引VBO索引 - 子MeshNode数组 - MeshObjects数组
MeshObject
- 所有从文件加载的单个总网格的顶点和索引数据 - 顶点VBO索引
如果我只用一个MeshObject绘制MeshNode,它似乎可以正常绘制。当我使用多个MeshObjects绘制MeshNode时,我得到的是模型的大致形状,但有些混乱。
我已经检查了Visual Studio调试器中的顶点数据和gDEbugger中的VBO数据,一切看起来都很好,所以我相信从文件加载和加载到VBO是有效的。
我使用gDEbugger强制将所有顶点绘制为点而不是三角形,它具有单个MeshObject的形状,这使我相信我只是没有正确地绑定到不同的VBO。就像每次都尝试使用不同的索引,但是相同的顶点。
顶点数据如下:
我的网格类快速概述如下:
Mesh
- 根MeshNode MeshNode - 变换 - VAO索引 - 索引VBO索引 - 子MeshNode数组 - MeshObjects数组
MeshObject
- 所有从文件加载的单个总网格的顶点和索引数据 - 顶点VBO索引
如果我只用一个MeshObject绘制MeshNode,它似乎可以正常绘制。当我使用多个MeshObjects绘制MeshNode时,我得到的是模型的大致形状,但有些混乱。
我已经检查了Visual Studio调试器中的顶点数据和gDEbugger中的VBO数据,一切看起来都很好,所以我相信从文件加载和加载到VBO是有效的。
我使用gDEbugger强制将所有顶点绘制为点而不是三角形,它具有单个MeshObject的形状,这使我相信我只是没有正确地绑定到不同的VBO。就像每次都尝试使用不同的索引,但是相同的顶点。
顶点数据如下:
struct VertexData
{
enum
{
NUM_TEXCOORDS = 1,
};
vector3 vertex;
vector3 normal;
vector2 texCoord[NUM_TEXCOORDS];
};
相关的MeshNode代码:
void MeshNode::initVAO(void)
{
closeVAO();
unsigned int scan;
//init index data
if (m_meshObjects.size() > 0)
{
glGenVertexArrays(1, &m_meshVAO);
glBindVertexArray(m_meshVAO);
{
//add up the total index count for all the mesh objects in this node
unsigned int indexCount = 0;
for (scan = 0; scan < m_meshObjects.size(); ++scan)
{
indexCount = indexCount + m_meshObjects[scan].getIndices()->size();
}
//make the actual index buffer
glGenBuffers(1, &m_indexVBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_indexVBO);
{
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount * sizeof(unsigned short), NULL, GL_STATIC_DRAW);
//set up VBOs and fill the index buffer with the index data from each mesh object
unsigned int offset = 0;
for (scan = 0; scan < m_meshObjects.size(); ++scan)
{
m_meshObjects[scan].initVBOs(offset);
}
}
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
glBindVertexArray(0);
}
for (scan = 0; scan < m_childMeshNodes.size(); ++scan)
{
m_childMeshNodes[scan]->initVAO();
}
}
void MeshNode::closeVAO(void)
{
if (m_meshVAO != 0)
{
glBindVertexArray(m_meshVAO);
{
glDeleteBuffers(1, &m_indexVBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
glBindVertexArray(0);
glDeleteVertexArrays(1, &m_meshVAO);
m_meshVAO = 0;
m_indexVBO = 0;
}
}
void MeshNode::render(const matrix4 &_parentTransform)
{
matrix4 transform = _parentTransform * m_transform;
if (m_meshObjects.size() > 0)
{
glBindVertexArray(m_meshVAO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_indexVBO);
{
for (unsigned int objectScan = 0; objectScan < m_meshObjects.size(); ++objectScan)
{
m_meshObjects[objectScan].render(transform);
}
}
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
for (unsigned int childScan = 0; childScan < m_childMeshNodes.size(); ++childScan)
{
m_childMeshNodes[childScan]->render(transform);
}
}
相关的 MeshObject 代码:
void MeshObject::initVBOs(unsigned int& _indexOffset)
{
//sub in this section of the index data
m_indexOffset = _indexOffset;
_indexOffset = _indexOffset + m_indices.size();
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, m_indexOffset * sizeof(unsigned short), m_indices.size() * sizeof(unsigned short), &(m_indices[0]));
//init vertex data
glGenBuffers(1, &m_vertexVBO);
glBindBuffer(GL_ARRAY_BUFFER, m_vertexVBO);
{
glBufferData(GL_ARRAY_BUFFER, m_data.size() * sizeof(VertexData), &(m_data[0]), GL_STATIC_DRAW);
glVertexAttribPointer(Shader::POSITION, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (char*)0);
glEnableVertexAttribArray(Shader::POSITION);
glVertexAttribPointer(Shader::NORMAL, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (char*)12);
glEnableVertexAttribArray(Shader::NORMAL);
glVertexAttribPointer(Shader::TEXCOORD0, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (char*)24);
glEnableVertexAttribArray(Shader::TEXCOORD0);
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void MeshObject::closeVBOs(void)
{
glDeleteBuffers(1, &m_vertexVBO);
m_vertexVBO = 0;
}
void MeshObject::render(const matrix4& _transform)
{
m_material->bind(_transform);
glBindBuffer(GL_ARRAY_BUFFER, m_vertexVBO);
{
glEnableVertexAttribArray(Shader::POSITION);
glEnableVertexAttribArray(Shader::NORMAL);
glEnableVertexAttribArray(Shader::TEXCOORD0);
glDrawRangeElements(GL_TRIANGLES, m_indexOffset, m_indexOffset + m_indices.size(), m_indices.size(), GL_UNSIGNED_SHORT, (char*)0);
glDisableVertexAttribArray(Shader::POSITION);
glDisableVertexAttribArray(Shader::NORMAL);
glDisableVertexAttribArray(Shader::TEXCOORD0);
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
}