- OpenGL多边形填充函数
矩形函数
glRect* (x1, y1, x2, y2);
星号(*)代表的后缀可以是i(整数)、s(短整数)、f(浮点型)、d(双精度浮点)、v(向量)。矩形的边平行于坐标轴,多边形的边按照顶点序列(x1, y1)、(x2, y1)、(x2, y2)、(x1,y2)来形成,然后返回到第一顶点(x1, y1)。
6种不同的符号常量下的图元填充函数
GL_POLYGON可以产生单个多边形,一个多边形的顶点集至少包含三个顶点,否则什么也不显示。
GL_TRIANGLES可以显示分开的三角形区域:最开始的3个坐标定义第一个三角形的三个顶点,之后3个顶点定义下一个三角形的顶点,以此类推。如果最后不足3个坐标则忽略多余的数据。
GL_TRIANGLE_STRIP可以产生连续的三角形:最开始3个坐标定义第一个三角形的三个顶点,第2-4个坐标定义第二个三角形的顶点,以此类推。N个顶点可以产生N-2个三角形。
GL_TRIANGLE_FAN可以产生“扇形”分布的三角形,其中第一个顶点坐标被所有的三角形共享,第2、3个顶点与它产生第一个三角形,第3、4个顶点与它产生第二个三角形,以此类推。N个顶点可以产生N-2个三角形。
GL_QUADS可以产生单个四边形,至少输入4个顶点,与GL_TRIANGLES产生三角形的规律相同:从头至尾,每4个坐标一组。
GL_QUAD_STRIP将产生连续的四边形。在N≥4时,N个顶点可以产生N/2-1个四边形。我们可以按n=1,n=2,…,n=N/2-1对填充多边形和顶点计数,这样,多边形表中第n个四边形的顶点次序为2n-1、2n、2n+2、2n+1。
- OpenGL顶点数组
顶点数组可以简化复杂场景渲染中多众多函数的重复调用,下面通过绘制单位立方体的例子说明。
假设pt是包含坐标值的顶点数组:
typedef GLint vertex3 [3]; vertex3 pt [8] = { {0, 0, 0}, {0, 1, 0}, {1, 0, 0}, {1, 1, 0}, {0, 0, 1}, {0, 1, 1}, {1, 0, 1}, {1, 1, 1} };
绘制单位立方体的代码为:
glEnableClientState (GL_VERTEX_ARRAY); glVertexPointer (3, GL_INT, 0, pt); GLubyte vertIndex [] = {6, 2, 3, 7, 5, 1, 0, 4, 7, 3, 1, 5, 4, 0, 2, 6, 2, 0, 1, 3, 7, 5, 4, 6}; glDrawElements (GL_QUADS, 24, GL_UNSIGNED_BYTE, vertIndex);
第一条命令激活了OpenGL顶点数组特性。也可以用下面的命令将该特性“关闭”:
glDisableClientState(GL_VERTEX_ARRAY);
glVertexPointer提供对象顶点坐标的位置和格式。此例中,第一个参数指出每个顶点描述中的坐标数目为3,第二个参数表示顶点坐标中的数据类型GL_INT,此外还有GL_BYTE、GL_SHORT、GL_FLOAT和GL_DOUBLE。第三个参数说明连续顶点之间的字节位移。最后一个参数指向包含坐标值的顶点数组。
立方体顶点的所有索引放在数组vertIndex中,其中每一个索引是对应于该顶点值的数组pt的下标。glDrawElements的第一个参数表示绘制多边形的方式,第二个参数指定下标索引数组,也就是vertIndex中的元素数量,第三个参数指定索引值的类型,除例中的GL_UNSIGNED_BYTE之外,还有GL_UNSIGNED_SHORT和GL_UNSIGNED_INT两种。
- 示例代码
代码清单:
#include <GL/glut.h> typedef GLint vertex3 [3]; vertex3 pt [8] = { {0,0,0}, {0,1,0}, {1,0,0}, {1,1,0}, {0,0,1}, {0,1,1}, {1,0,1}, {1,1,1} }; void init(){ glClearColor(1.0, 1.0, 1.0, 0.0); glMatrixMode(GL_PROJECTION); gluOrtho2D(0.0, 200, 0.0, 150); //glOrtho(-1.0, 2.0, -1.0, 2.0, -1.0, 2.0); } void polygon(void){ glClear(GL_COLOR_BUFFER_BIT); glColor3f(1.0, 0.0, 0.0); glRecti(10, 10, 40, 50); glColor3f(0.0, 1.0, 0.0); glBegin(GL_POLYGON); glVertex2i(10, 60); glVertex2i(40, 60); glVertex2i(30, 90); glVertex2i(20, 90); glEnd(); glColor3f(0.0, 0.0, 1.0); glBegin(GL_TRIANGLES); glVertex2i(60, 30); glVertex2i(70, 10); glVertex2i(70, 50); glVertex2i(90, 10); glVertex2i(100, 30); glVertex2i(90, 50); glEnd(); glColor3f(0.0, 1.0, 1.0); glBegin(GL_TRIANGLE_STRIP); glVertex2i(60, 80); glVertex2i(70, 60); glVertex2i(70, 100); glVertex2i(90, 60); glVertex2i(90, 100); glVertex2i(100, 80); glEnd(); glColor3f(0.0, 0.50, 1.0); glBegin(GL_QUAD_STRIP); glVertex2i(110, 80); glVertex2i(120, 20); glVertex2i(130, 70); glVertex2i(140, 10); glVertex2i(160, 70); glVertex2i(160, 10); glVertex2i(190, 90); glVertex2i(180, 20); glEnd(); glFlush(); } void cube(void){ glClear(GL_COLOR_BUFFER_BIT); glColor3f(1.0, 0.0, 0.0); glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_INT, 0, pt); GLubyte vertIndex[] = {6, 2, 3, 7, 5, 1, 0, 4, 7, 3, 1, 5, 4, 0, 2, 6, 2, 0, 1, 3, 7, 5, 4, 6}; glDrawElements(GL_QUADS, 24, GL_UNSIGNED_BYTE, vertIndex); glFlush(); } int main(int argc, char *argv[]) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); glutInitWindowSize(400, 300); glutCreateWindow("Draw Polygon"); init(); glutDisplayFunc(polygon); glutMainLoop(); }