Apo*_*ate 8 c++ opengl 3d vbo opengl-3
我正在尝试更新我以前使用OpenGL 2.x样式顶点数组的引擎来使用OpenGL 3.x,这意味着更新到VAO/VBO.我想我并没有正确地约束VBO.阅读下面的更多信息或跳到代码,找到我做错了什么.
我的网格类的快速概述看起来像这样:
啮合
MeshNode
MeshObject
如果我绘制一个只有一个MeshObject的MeshNode,它似乎画得很好.当我绘制一个具有多个MeshObjects的MeshNode时,我得到的东西就是我想要绘制的模型的一般形状,但有点乱码.
我已经通过gDEbugger检查了Visual Studio调试器中的顶点数据和VBO数据,它看起来都很好,所以我非常确定从文件加载到VBO中的加载工作正常.
我使用gDEbugger强制它为所有顶点而不是三角形绘制点,并且它具有单个MeshObject的形状,这使我相信我只是没有正确地绑定到不同的VBO.好像它试图用不同的索引绘制,但每次都是相同的顶点.
VertexData如下所示:
struct VertexData
{
enum
{
NUM_TEXCOORDS = 1,
};
vector3 vertex;
vector3 normal;
vector2 texCoord[NUM_TEXCOORDS];
};
Run Code Online (Sandbox Code Playgroud)
相关的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);
}
}
Run Code Online (Sandbox Code Playgroud)
相关的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);
}
Run Code Online (Sandbox Code Playgroud)
我的网格类的快速概述看起来像这样:
我认为你的场景图层次结构有点混乱.全部Node场景图的需求是变换的列表中,Node儿童和网格的列表,在该画Node.它不应该有元素缓冲区或VAO; 这些在概念上是网格数据的一部分.
实际上,你的问题源于最后一点.顶点数组对象包含通过glVertexAttrib(I)Pointer调用设置的状态.这意味着,每次MeshObject::initVBOs在同一个MeshNode中调用时,都会覆盖前一个调用所设置的数据集.
每个网格都需要自己的VAO,而不是节点.网格可以共享索引数据,这是你似乎正在做的事情(尽管如果你担心有太多的缓冲区,它们也应该为它们的顶点数据共享相同的缓冲区对象).但VAO必须与众不同.多个VAO可以引用相同的元素缓冲区.