Я пытаюсь обновить свой движок, который использовал вершинные массивы в стиле OpenGL 2.x для работы с OpenGL 3.x, что означает обновление до VAO / VBO. Я думаю, что я не привязан к VBO должным образом. Читайте ниже для получения дополнительной информации или перейдите к коду и узнайте, что я делаю неправильно.
Краткий обзор моих классов мешей выглядит примерно так:
Сетка
MeshNode
- преобразование
- индекс VAO
- индекс VBO индекс
- массив дочерних MeshNodes
- массив MeshObjects
MeshObject
- все данные вершин и индексов, загруженные из файла для одного куска общей сетки
- индекс VBO вершины
Если я рисую MeshNode только с одним MeshObject, кажется, что он хорошо рисует. Когда я рисую MeshNode с несколькими объектами MeshObject, я получаю что-то, что является общей формой модели, которую я пытаюсь нарисовать, но немного искажено.
Я проверил данные вершин в отладчике Visual Studio и данные VBO через gDEbugger, и все это выглядит нормально, поэтому я почти уверен, что загрузка из файла и загрузка в VBO работают.
Я использовал gDEbugger, чтобы заставить его рисовать точки для всех вершин вместо треугольников, и он имеет форму одного MeshObject, что заставляет меня поверить, что я просто не привязываюсь к разным VBO должным образом. Как будто он пытается рисовать с разными индексами, но каждый раз с одинаковыми вершинами.
VertexData выглядит так:
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);
}