【问题标题】:openGL 3.3 - VBO drawing with glDrawArrays / glDrawElementsopenGL 3.3 - 使用 glDrawArrays / glDrawElements 绘制 VBO
【发布时间】:2013-07-20 17:26:34
【问题描述】:

我将 VC++2010 与 GLFW3 和 GLEW 用于 openGL。我制作了一个 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() 方法绑定。 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);
}

我可以加载一个网格:

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 循环中我这样做:

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 个四边形,我遇到了访问冲突 0x000005。

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

谁能给我一个提示?

【问题讨论】:

  • 顺便说一句,最好使用在一个地方(pos,norm,...)包含一个顶点的 VBO,而不是使用多个 VBO。无论如何,我不喜欢你使用不推荐使用的函数(如glPushMatrixetc),最好使用着色器,自己的矩阵等......在我个人看来,这在一切都设置好时减少了错误的来源,也许甚至消除了这个错误。
  • 好的,我已经剪掉了那堵文字墙……感谢 cmets。我对openGL比较陌生,不幸的是我对着色器一无所知......我想稍后再做。首先,我想要可以运行和显示某些东西的代码。
  • @user2602528 实际上,您在上面所做的事情与新技术之间存在一些差异,因此如果您让上面的代码工作,那么您仍然需要学习很多差异。恕我直言,这没有意义,尤其是有一些很好的教程(db-in.com/blog/2011/01/all-about-opengl-es-2-x-part-13)。
  • 感谢 cmets ......你说得对,我正在将 openGL 3.3 函数与不推荐使用的东西混合在一起。感谢 Felix K. 获取链接,如果有人读到此链接,我将获得更多 OpenGL 3.3 教程 [1] [链接] (mbsoftworks.sk/index.php?page=tutorials&series=1) [2] [链接] (opengl-tutorial.org) [3] [链接] (@ 987654326@) 我也认为是 [4] [链接] (ogldev.atspace.co.uk/index.html)
  • 还有this one 3.3。

标签: c++ opengl drawing vbo


【解决方案1】:

不要使用std::vector&lt;VBOMesh2&gt;,因为向量对值进行操作。如果你已经实现~VBOMesh2 来删除你的数组,你可能正在绘制悬空指针(即indices[0])。使用VBOMesh2std::vector&lt;VBOMesh2*&gt; 的简单数组。

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

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

您需要决定是否要使用索引网格,您的问题并不清楚。如果你这样做,你需要使用glDrawElements。但是,您的顶点和法线数据的大小不合适。但我怀疑你知道这一点。看起来您首先为索引网格实现了代码,当它不起作用时,您尝试将其转换为非索引网格。

【讨论】:

  • 当我使用 glDrawElements() - 绘制索引网格时,我用另一种方法填充我的数组(顶点、法线和索引)(我不复制冗余点)。附:你的最后一句话是绝对正确的,这就是发生的事情。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-06-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多