OpenGL优化网格绘图(VAO?没有索引?)

时间:2015-03-19 16:40:36

标签: c++ opengl

好一些超时后我继续研究OpenGL3.2 +,现在我对如何优化这样的事情感到困惑:

// Verts
glBindBuffer(GL_ARRAY_BUFFER, VertBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * size, verts, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(VERTEX_COORD_ATTRIB);
glVertexAttribPointer(VERTEX_COORD_ATTRIB,3,GL_FLOAT, GL_FALSE, sizeof(float) * floatsPerVertex, 0);

// Textures
glBindBuffer(GL_ARRAY_BUFFER, TexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * texsize, tex, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(TEXTURE_COORD_ATTRIB);
glVertexAttribPointer(TEXTURE_COORD_ATTRIB, 2, GL_FLOAT, GL_FALSE, sizeof(float) * TexCoords2D, 0);

//add light color info
glBindBuffer(GL_ARRAY_BUFFER, ColorBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * colorsize, lightcolor, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(COLOR_ATTRIB);
glVertexAttribPointer(COLOR_ATTRIB, 4, GL_FLOAT, GL_FALSE, sizeof(float) * ColorInfo, 0);

// Draw
glDrawArrays(GL_TRIANGLES, 0, size);

// Clean up
glDisableVertexAttribArray(VERTEX_COORD_ATTRIB);
glDisableVertexAttribArray(TEXTURE_COORD_ATTRIB);
glDisableVertexAttribArray(COLOR_ATTRIB);

让我们假设这是针对几个网格完成的,目前每个网格总是像这样被推动,绑定,缓冲和绘制。有人说,这肯定不是有效的方法。

现在,当阅读(很多)教程时,我总是看到的一件事是建议使用VAO来改进它,现在我很难理解 - 每个单独的教程似乎也参考索引绘图。虽然这个方法在使用像2个四边形这样非常简单的例子时似乎非常好,但我现在想知道如何创建一个真实复杂网格的索引?或者只是假设这是可用的(由.obj文件或其他东西)。 另外,我很困惑VAO是否总是需要一个索引,还是可以不使用它?如果是这样,它甚至没有意义,因为我读到优化利用了解索引? 你看到这里有很多混乱,我意识到这可能是一个愚蠢的问题:)

然而,我想要最终实现的是,不是像这样推动每个网格,而是在显卡的内存中缓冲每个网格一次,然后从缓冲区重绘它。 我不知道VAO甚至是正确的方法,但我读到的每个教程似乎都将VAO作为下一步。

2 个答案:

答案 0 :(得分:2)

首先,您应该使用glDrawArrays()将您的GRAM写入与绘图调用中的glBufferData()分开。这会显着降低您的性能,因为您在每次绘图调用时都基本将数据从RAM复制到GRAM。

为此,您可以使用VAO:

//设置缓冲区

glBindVertexArray(VertexArrayIndex);

glBindBuffer(GL_ARRAY_BUFFER, VertBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * size, verts, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(VERTEX_COORD_ATTRIB);
glVertexAttribPointer(VERTEX_COORD_ATTRIB,3,GL_FLOAT, GL_FALSE, sizeof(float) * floatsPerVertex, 0);

// Textures
glBindBuffer(GL_ARRAY_BUFFER, TexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * texsize, tex, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(TEXTURE_COORD_ATTRIB);
glVertexAttribPointer(TEXTURE_COORD_ATTRIB, 2, GL_FLOAT, GL_FALSE, sizeof(float) * TexCoords2D, 0);

//add light color info
glBindBuffer(GL_ARRAY_BUFFER, ColorBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * colorsize, lightcolor, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(COLOR_ATTRIB);
glVertexAttribPointer(COLOR_ATTRIB, 4, GL_FLOAT, GL_FALSE, sizeof(float) * ColorInfo, 0);

glBindVertexArray(0);

//你的绘图电话

glBindVertexArray(VertexArrayIndex);
 glDrawArrays(GL_TRIANGLES, 0, size);
glBindVertexArray(0);

如果你想绘制非常大的网格物体(它们的大小比图形卡上可用的GRAM大),你应该有兴趣将数据分成小块。将所有数据放在一个大数组中可能会导致一些讨厌的内存分配和渲染问题(相信我 - 我已经在那里;)。)

答案 1 :(得分:1)

我建议您的下一步应该是将顶点属性转换为结构而不是单独的数组。这样,你只使用一个数组对象,GPU更喜欢这种内存布局。

除此之外:

您是否被编入索引在很大程度上取决于您的数据;它不是快速性能的要求,但它可以提供帮助;另一种选择是使用三角形条带,这也减少了顶点数据的数量。如果在单个数组对象中有多个网格,则可以简单地将顶点属性指针更改为从数组对象中的不同位置开始,以绘制不同的网格。那么你就不会在数组对象之间切换太多了。

这些决定中的大多数应该由您的约束和性能测量决定!