openGL 3.3 - 使用glDrawArrays / glDrawElements进行VBO绘图

时间:2013-07-20 17:26:34

标签: c++ opengl drawing vbo

我正在使用带有GLFW3的VC ++ 2010和用于openGL的GLEW。我已经制作了一个OBJ-Loader来加载三角网格。在某些时候,我在VBOMesh2对象中填充以下数组。

GLfloat *vertices;
GLfloat *normals;
GLuint *indices;

结果,我得到了我用于VBO的数据:

  • 顶点:顶点= [v0x,v0y,v0z,v1x,v1y,v1z,...]
  • (已排序)法线:法线= [n0x,n0y,n0z,n1x,n1y,n1z,...]
  • 指数:inices = {face0i0,face0i1,face0i2,face1i0,face1i1,face1i2,...]

下一步是使用VBOMesh2对象中的init() - 方法绑定Buffers。 vertexVBOID,normalsVBOID和indexVBOID是GLuint。

void VBOMesh2::init(void)
{
    vertexVBOID = 0;
    glGenBuffers(1, &vertexVBOID);
    glBindBuffer(GL_ARRAY_BUFFER, vertexVBOID);
    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*numFaces*3*3, vertices, GL_STATIC_DRAW);

    normalsVBOID = 0;
    glGenBuffers(1, &normalsVBOID);
    glBindBuffer(GL_ARRAY_BUFFER, normalsVBOID);
    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*numFaces*3*3, normals, GL_STATIC_DRAW);

    indexVBOID = 0;
    glGenBuffers(1, &indexVBOID);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexVBOID);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*numFaces*3, indices, GL_STATIC_DRAW);

}

好的......我画的是:

void VBOMesh2::draw(void)
{
    glEnableClientState(GL_VERTEX_ARRAY);
    glBindBuffer(GL_ARRAY_BUFFER, vertexVBOID);
    glVertexPointer(3, GL_FLOAT, sizeof(float)*3, 0);

    glEnableClientState(GL_NORMAL_ARRAY);
    glBindBuffer(GL_ARRAY_BUFFER, normalsVBOID);
    glNormalPointer(GL_FLOAT, sizeof(float)*3, 0);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexVBOID);

    glPushMatrix();
    glTranslatef(x, y, z);
    glRotatef(rx, 1, 0, 0);
    glRotatef(ry, 0, 1, 0);
    glRotatef(rz, 0, 0, 1);

    glDrawArrays(GL_TRIANGLES, indices[0], numIndices);

    glPopMatrix();

    glDisableClientState(GL_NORMAL_ARRAY);
    glDisableClientState(GL_VERTEX_ARRAY);
}

我可以加载一个Mesh:

OBJLoader objLoader;
MeshData meshData;
objLoader.loadFile("temp/quad_smooth.obj");
meshData = objLoader.getMeshData();
VBOMesh2 tmpMesh(meshData);

并使用:

绘制它(在openGL-Loop中)
tmpMesh.draw();

我得到以下结果:

one Quad

精彩!

现在我想,让我们用以下代码绘制500个四边形:

OBJLoader objLoader;
MeshData meshData;
objLoader.loadFile("temp/quad_smooth.obj");
meshData = objLoader.getMeshData();

for(int i = 0; i < 500; i++)
{
   VBOMesh2 tmpMesh(meshData);

   meshes.push_back(tmpMesh);
   meshes[i].init();

 // Do stuff for position and rotation like meshes[i].setX(x); and so on
}

在openGL-loop中我做:

for(int i = 0; i < meshes.size(); i++) 
{
   meshes[i].draw();
}

顺便说一句。网格是一个向量:

vector<VBOMesh2> meshes;

我得到了以下结果:

500 Quads

哦不!!!!

现在我不知道为什么我的网格(不是全部,但有些)被打破......或者我做错了......代码可以渲染一个四边形而没有任何可视化错误,但是当我使用相同的meshData(来自oneQuad的相同数据)创建500个四边形时,我得到了破坏的四边形....

而不是使用

glDrawArrays(GL_TRIANGLES, indices[0], numIndices);

我试过

glDrawElements(GL_TRIANGLES, numIndices, GL_UNSIGNED_INT, 0);

因为我已经填充了数组顶点,法线,索引与其他方法(我可以发布,如果有必要),但我有同样的问题...我可以绘制一个四边形没有错误,但当我尝试为了绘制500个Quads,我获得了访问冲突0x000005。

顺便说一下。我为我的图形卡更新了我的驱动程序(但问题仍然存在)

有人能给我一个暗示吗?

1 个答案:

答案 0 :(得分:0)

不要使用std::vector<VBOMesh2>,因为vector对值进行操作。如果您已实现~VBOMesh2删除数组,则可能正在绘制悬空指针(即indices[0])。使用VBOMesh2std::vector<VBOMesh2*>的简单数组。

glDrawArrays(GL_TRIANGLES, indices[0], numIndices);

这不是你绘制索引网格的方式。第二个参数是先前使用glVertexPointerglNormalPointer绑定的数组的偏移量。在你的情况下,它应该总是0。

您需要决定是否要使用索引网格,您的问题不明确。如果您这样做,则需要使用glDrawElements。但是,顶点和普通数据的大小不正确。但我怀疑你知道这一点。有点看起来你首先为索引网格实现了代码,当它不起作用时你试图将它转换为非索引网格。