opengl教程翻译 #10索引绘制

背景知识:

OpenGL提供了几个绘制函数。之前我们所用至今的glDrawArrays()属于“有序绘制”类型。这意味着从特定的偏移位开始扫描顶点缓冲去,然后每X个(1个是点,2个是线,等等)顶点作为一个图元被发出。这是一个很简单的用法,但它的缺点是如果顶点作为N干个图元的共同一部分,则它必须在顶点缓冲中表示N次。也就是,没有共享概念可言。共享是通过“索引绘制”类型的函数提供的。这里除了顶点缓冲区,还有一个索引缓冲区,包含对应到顶点缓冲区的索引值。当扫描索引缓冲区时就相当于在扫描顶点缓冲区--每X个代表一个图元的索引被发出。用共享时你只要简单的重复共享顶点的索引N次即可。共享对应存储效率很重要,因为大多数物件在相同的三角形闭环网络中呈现,而大部分顶点都参与了超过1个三角形。

这是一个有序绘制的例子:

 

如果我们在渲染三角形,GPU会生成一下集合:V0/1/2,V3/4/5,V6/7/8,等等

这是一个索引绘制的例子:

 

这种情况下GPU会生成一下三角形:V2/0/1, V5/2/4, V6/5/7, 等等

在OpenGL使用所以绘制需要生成、填充一个索引缓冲。这个缓冲必须在draw call之前被绑定在顶点缓冲区上,以及使用不同的API。

代码演练:

GLuint IBO;

我们为索引缓冲区添加另一个缓冲对象句柄。

Vertices[0] = Vector3f(-1.0f, -1.0f, 0.0f);

Vertices[1] = Vector3f(0.0f, -1.0f, 1.0f);

Vertices[2] = Vector3f(1.0f, -1.0f, 0.0f);

Vertices[3] = Vector3f(0.0f, 1.0f, 0.0f);

为演示顶点共享我们需要一个更加复杂的网络。许多教程使用注明的旋转立方体演示它。它需要8个顶点和12个三角形。因为我很懒因此使用旋转金字塔代替它。这仅仅只需要4个顶点和4个三角形,而且更容易手动生成...

 

unsigned int Indices[] =

 { 0, 3, 1,

  1, 3, 2,

  2, 3, 0,

  0, 1, 2 };

用一个索引数组填充这个索引缓冲区。每个索引匹配顶点缓冲区中顶点的位置。看着上面的数组和图你可以看到最后一个三角形基本上是金字塔状的当其他三个化妆它的脸。金字塔形不是对称的,但是很容易指定。

glGenBuffers(1, &IBO);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);

glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices), Indices, GL_STATIC_DRAW);

我们用了索引数组创建、填充了索引缓冲。你可以看到创建顶点和索引缓冲的唯一不同是顶点缓冲用GL_ARRAY_BUFFER而索引缓冲用GL_ELEMENT_ARRAY_BUFFER作为缓冲类型。

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);

除了绑定顶点缓冲区我们还必须在绘制之前绑定索引缓冲区。我们再次用GL_ELEMENT_ARRAY_BUFFER作为缓冲类型。

glDrawElements(GL_TRIANGLES, 12, GL_UNSIGNED_INT, 0);

我们使用glDrawElements代替了glDrawArrays。第一个参数是用来渲染的图元类型(同glDrawArrays)。第二个参数是在索引缓冲区中索引的个数,用于图元的生成。下个参数是每个索引的类型。GPU必须被告知每个独立索引的长度,否则它不会知道如何解析缓冲区。在这可能出现的值有GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT。如果你想小一点的类型以便省空间就选择小的索引范围,如果你想大一点的类型则选择大的索引范围。最后一个参数告诉GPU从索引缓冲区的开端到扫描索引的开端之间的偏移。当相同的索引缓冲区包含很多不同对象的索引时很管用。通过指定偏移量和数量你能告诉GPU区渲染哪个对象。在我们的例子中,我们希望在最开端开始所以我们指定为0.注意最后一个参数的类型是GLvoid*,因此如果你指定其他比0大的值你需要置换类型。

猜你喜欢

转载自www.cnblogs.com/alphaGo/p/9208568.html
今日推荐