相关主题:顶点缓冲区,显示列表
下载:vertexArray.zip, vertexArray2.zip
glBegin(GL_TRIANGLES); // 使用12个三角形绘制立方体
// front face =================
glVertex3fv(v0); // v0-v1-v2
glVertex3fv(v1);
glVertex3fv(v2);
glVertex3fv(v2); // v2-v3-v0
glVertex3fv(v3);
glVertex3fv(v0);
// right face =================
glVertex3fv(v0); // v0-v3-v4
glVertex3fv(v3);
glVertex3fv(v4);
glVertex3fv(v4); // v4-v5-v0
glVertex3fv(v5);
glVertex3fv(v0);
// top face ===================
glVertex3fv(v0); // v0-v5-v6
glVertex3fv(v5);
glVertex3fv(v6);
glVertex3fv(v6); // v6-v1-v0
glVertex3fv(v1);
glVertex3fv(v0);
... // 绘制另外3个面
glEnd();
使用顶点数组减少了函数调用的次数和共享顶点的冗余使用。因此,你可以提高渲染的性能。现在将解释使用顶点数组的3个不同的OpenGL函数:glDrawArrays(),glDrawElements()和glDrawRangeElements()。虽然更好的方式是使用顶点缓冲区对象(VBO)或显示列表。
初始化
OpenGL提供了glEnableClientState()和glDisableClientState()来激活或禁用6个不同类型的数组,还有6个函来操作这6个数组,因此,OpenGL可以在你的应用程序中访问这6个数组。
GLfloat vertices[] = {...}; // 36 个顶点的坐标
...
// 激活顶点数组
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertices);
// 绘制一个立方体
glDrawArrays(GL_TRIANGLES, 0, 36);
// 绘制完成后禁用顶点数组
glDisableClientState(GL_VERTEX_ARRAY);
GLfloat vertices[] = {...}; // 8个顶点坐标
GLubyte indices[] = {0,1,2, 2,3,0, // 索引数组
0,3,4, 4,5,0,
0,5,6, 6,1,0,
1,6,7, 7,2,1,
7,4,3, 3,2,7,
4,7,6, 6,5,4};
...
// 激活顶点数组
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertices);
// 绘制立方体
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, indices);
// 禁用顶点数组
glDisableClientState(GL_VERTEX_ARRAY);
和glDrawElements()比较类似,glDrawRangeElements()也可以在数组中跳跃访问。然而,glDrawRangeElements()还有两个额外的参数(开始和结束位置的索引)来指定顶点的范围。通过添加这个范围限制,OpenGL可以只获得访问有限范围的顶点的来优先渲染,这样可能提高性能。
在glDrawRangeElements()中的额外的参数是开始(start)和结束(end)位置的索引,OpenGL预取end-start+1个顶点数据。索引数组中的值必须在start和end之间。注意并不是start和end之间的所有顶点都必须被引用到,但是如果你指定了一个稀疏的范围,那样将会导致为那些不需要使用的顶点进行的没必要的处理。
GLfloat vertices[] = {...}; // 8个顶点坐标
GLubyte indices[] = {0,1,2, 2,3,0, // 前一半 (18 个顶点)
0,3,4, 4,5,0,
0,5,6, 6,1,0,
1,6,7, 7,2,1, // 后一半 (18 个顶点)
7,4,3, 3,2,7,
4,7,6, 6,5,4};
...
// 激活顶点数组
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertices);
// 绘制前面一半的图形 6 - 0 + 1 = 7 个顶点被使用
glDrawRangeElements(GL_TRIANGLES, 0, 6, 18, GL_UNSIGNED_BYTE, indices);
// 绘制后面一半的图形 7 - 1 + 1 = 7 个顶点被使用
glDrawRangeElements(GL_TRIANGLES, 1, 7, 18, GL_UNSIGNED_BYTE, indices+18);
// 禁用顶点数组
glDisableClientState(GL_VERTEX_ARRAY);
注意glDrawRangeElements()只有在OpenGL 1.2版本或更高版本上才可以使用。
例子:
这个例子程序使用4种不同的方式渲染一个立方体:立即模式,glDrawArrays(),glDrawElemennts(),glDrawRangeElements()。