原帖地址:http://ogldev.atspace.co.uk/www/tutorial10/tutorial10.html
OpenGL提供了几个draw函数: 之前用的 glDrawArrays() 称作ordered draws(顺序的draw调用),如果指定draw体元为线,则顶点缓冲中按排列顺序,每2个顶点解释为线,如果体元为三角形,每三个顶点解释为三角形,在这里并没有共享的概念,比如要渲染一个四边形,就要画2个三角形,需要6个顶点。通过indexed draws,我们能实现顶点的共享,就是除了顶点缓冲外,我们会再定义一个索引缓冲,索引缓冲的值是顶点在定点缓冲中的索引值。
下面是ordered draw的例子,此时将产生v0-v1-v2, v3-v4-v5,v6-v7-v8的三角形:
下面是indexed draw的例子,此时将产生v4-v0-v1,v5-v2-v1,v6-v1-v7的三角形:
主要代码:
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);
为了使用顶点共享,我们将渲染一个旋转的金字塔,共四个三角形,需要四个顶点。
我们沿着y轴向下俯视,我们能够得到下面俯视图:
unsigned int Indices[] = { 0, 3, 1,
1, 3, 2,
2, 3, 0,
0, 2, 1 };
索引缓冲中有12个索引,定义了四个三角形,它的值都是顶点缓冲中对应顶点的索引值。注意:我们渲染的金字塔并不是对称的。
glGenBuffers(1, &IBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices), Indices, GL_STATIC_DRAW);
上面的三行代码,用来创建索引缓冲对象,指定类型名,并绑定到索引缓冲,注意它和顶点缓冲的区别:用GL_ELEMENT_ARRAY_BUFFER替代了GL_ELEMENT_ARRAY_BUFFER。
glDrawElements(GL_TRIANGLES, 12, GL_UNSIGNED_INT, 0);
最后用glDrawElements代替glDrawArrays,该函数的第一个参数是体元类型,第二个参数是索引的数量,第三个参数是索引的类型GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT等等,GPU会根据这个类型来读取索引值,如果我们的索引顶点不多,可以用范围较小的类型,这样可以提高效率,否则的话就用范围较大的类型。最后一个变量是在索引缓冲中的偏移,在我们程序中,我们是从起始位置开始,所以是0。
程序执行后界面如下,四面体将绕y轴旋转: