今天说一说几种简单的图元。 
    所有的几何图元都是根据它们的顶点来描绘的。而顶点就是它们在屏幕上的坐标位置。 
   我喜欢把这几个简单的图元称为点线面。 
   点,可以看到一个顶点; 
   线,就是两个顶点指定的一条有限长度的线段; 
   面,其实更准确讲是一个凸多边形。opengl里所讲的多边形是内部用颜色填充的,视觉上称为面我个人认为是更贴近的。当然,多边形也是由指定的顶点组成的。 
   需要注意的是,要想被opengl按照设计被绘制必须正确的认识到,所谓的多边形是顶点都处于一个平面上,凸多边形。凸多边形不能理解的,请问度娘。。。 
    来看一个例子: 

C++代码  收藏代码
  1. glBegin(GL_POLYGON);  
  2.     glVertex2f(0.0, 0.0);  
  3.     glVertex2f(0.0, 3.0);  
  4.     glVertex2f(4.0, 3.0);  
  5.     glVertex2f(6.0, 1.5);  
  6.     glVertex2f(4.0, 0.0);  
  7. glEnd();  


    先不去关心代码本身,这段代码最终的结果是要指定5个顶点绘制一个凸五边形。注意,不是5条线段而是一个凸五边形的平面。 
    不管是点线面的哪一种,都是需要指定一组顶点的。如何判定顶点指定的开始和结束就是glBegin和glEnd的工作。 

引用
void glBegin(Glenum mode); 
标志着一个顶点数据列表的开始,它描述了一个几何图元。mode参数指定了图元的类型。 
void glEnd(void); 
标志着一个顶点数据列表的结束。


mode设置的不同,代表着将要绘制的图元也不同。下面这个表就是图元的名称和含义: 

  值                                      含义
  GL_POINTS                   单个的点
  GL_LINES                    一对顶点被解释为一条直线
  GL_LINE_STRIP               一系列的连接直线
  GL_LINE_LOOP                和上面相同,但第一个顶点和最后一个顶点彼此相连
  GL_TRIANGLES                3个顶点被解释为一个三角形
  GL_TRIANGLES_STRIP          三角形的连接串
  GL_TRIANGLES_FAN            连接成扇形的三角形系列
  GL_QUADS                    4个顶点被解释为一个四边形
  GL_QUADS_STRIP              四边形的连接串
  GL_POLYGON                  简单的凸多边形的边界



    试想着,如果将glBegin(GL_POLYGON)修改为glBegin(GL_POINTS),绘制出来的将是什么图形呢? 哈哈,那就是5个点而已么。 
    上面那段代码还有一个最为重要的函数,那就是顶点函数只有通过顶点函数指定了绘制图形所需要的顶点,才能去绘制我们需要的图形。 
    下面看一下顶点函数的原形: 

引用
void glVertex[234]{sifd}(TYPE coords); 
glVertex[234]{sifd}(const TYPE *coords); 
指定了一个用于描述几何物体的顶点。可以选择这个函数的适当版本,即可以为一个顶点提供多达4个的坐标(x,y,z,w),也可以只提供2个坐标(x,y)。如果选择的函数版本并没有显式地指定z或者w,z就会当作0,w则默认为1。glVertext*()函数只有当它位于glBegin()和glEnd()之间时才有效。
 
 上一周简简单单的讲了一下简单图形的绘制。按照所讲内容绘制一个20条边的多边形,那需要调用多少函数呢?至少22个。首先调用glBegin(),然后是20个顶点函数,最后调用一个glEnd()函数。再如果,要绘制一个立方体。一个立方体有6个面,一个面有四个顶点,也就是至少要定义26个函数。 
    可是一个立方体按照数学里面的算法是只有8个顶点,如果按照我们绘制多边形的这种方式,每个顶点都指定了3次,才可以将所有的平面绘制完成形成一个立方体。 
    好吧,我承认,我是要说,这显然,太~浪~费~了。OpenGL是不会这么无耻的允许这样浪费的事情存在的,所以大家不用纠结,继续往下看吧。 
    OpenGL提供了顶点数组函数,允许只用少数几个数组指定大量的与顶点相关的数据,并用少量函数调用访问这些数据。 
    使用顶点数组对几何图形进行渲染需要三个步骤: 
   第一,启用数组。 
  
引用
void glEnableClientState(GLenum array) 
    指定了需要启用的数组。array参数可以使用下面这些符号常量:GL_VERTEY_ARRAY、GL_COLOR_ARRAY、GL_SECONDARY_COLOR_ARRAY、GL_INDEX_ARRAY、GL_NORMAL_ARRAY、GL_FOG_COORDINATE_ARRAY、GL_TEXTURE_COORD_ARRAY和GL_EDGE_FLAG_ARRAY

    第一个步骤是使用上面这个函数,激活选择的数组。例如激活顶点坐标数组就是glEnableClientState(GL_VERTEY_ARRAY)。 
    有启用就用禁用,下面这个函数即为禁用函数。 
  
引用
void glDisableClientState(GLenum array) 
指定了需要禁用的数组。它接受的参数与glEnableClientState()函数相同。

    第二,指定数组的数据。 
    共用8个不同的函数指定数组,每个函数用于指定一个不同类型的数组。 
  
引用
void glVertexPointer(GLint size, GLenum type, GLsizei stride,const GLvoid *pointer); 
    指定了需要访问的空间坐标数据。 
    pointer:顶点坐标的内存地址; 
    type:数组数据的类型(GL_SHORT、GL_INT、GL_FLOAT或GL+DOUBLE)。 
    size:顶点的坐标数量,必须为2、3、4. 
    stride:连续顶点之间的字节偏移量。如果为0,则表示顶点是相邻的。 
    其它7个函数如下: 
glColorPointer(GLint size, GLenum type, GLsizei stride,const GLvoid *pointer); 
glSecondaryColorPointer(GLint size, GLenum type, GLsizei stride,const GLvoid *pointer); 
glIndexPointer(GLint size, GLenum type, GLsizei stride,const GLvoid *pointer); 
glNormalPointer(GLint size, GLenum type, GLsizei stride,const GLvoid *pointer); 
glFogCoordPointer(GLint size, GLenum type, GLsizei stride,const GLvoid *pointer); 
glTexCoordPointer(GLint size, GLenum type, GLsizei stride,const GLvoid *pointer); 
glEdgeFlagPointer(GLint size, GLenum type, GLsizei stride,const GLvoid *pointer); 

    附上一个小的例子: 
C++代码  收藏代码
  1. static GLint vertices[] = {25, 25,   
  2.                            100, 325,   
  3.                            175, 25,   
  4.                            175, 325,   
  5.                            250, 25,   
  6.                            325, 325};  
  7. static GLfloat colors[] = {1.0, 0.2, 0.2,   
  8.                            0.2, 0.2, 1.0,   
  9.                            0.8, 1.0, 2.0,   
  10.                            0.75, 0.75, 0.75,   
  11.                            0.35, 0.35, 0.35,   
  12.                            0.5, 0.5, 0.5};  
  13. glEnableClientState(GL_COLOR_ARRAY);  
  14. glEnableClientState(GL_VERTEX_ARRAY);  
  15. glColorPointer(3, GL_FLOAT, 0, color);  
  16. glVertexPointer(2, GL_INT, 0, vertices);  

   第三,解引用和渲染。 
   解引用单个数组元素: 
  
引用
void glArrayElement(GLint ith) 
    获取当前所有已启用数组的一个顶点(第ith个)的数据。对于顶点坐标数组,对应的函数是glVertex[size][type]v(),其中size是【2,3,4】之一。type是[s,i,f,d]之一,size和type都是glVertexPointer()函数定义的。对于其他启动的数组,glArrayElement()分别调用那个glEndgFlagv()、glTexCoord[size[[type]v()、glColor[size][type]v()、glSecondaryColor3[type]v()、glInde[type]v()、glNoramal3[type]v()和glFogCoord[type]v()。如果启用了顶点坐标数组,在其他几个数组(如果启用)相对应的函数被执行之后,glVertex*v()函数在最后执行。

     举例说明:使用第二步骤时启用的顶点数组的第1,2,3顶点绘制一个三角形: 
C++代码  收藏代码
  1. glBegin(GL_TRIANGLES);  
  2. glArrayElement(0);  
  3. glArrayElement(1);  
  4. glArrayElement(2);  
  5. glEnd();  

    上面这段代码与下面的效果相同: 
C++代码  收藏代码
  1. glBegin(GL_TRIANGLES);  
  2. glColor3fv(color);  
  3. glVertex2iv(vertices);  
  4. glColor3fv(color + (1*3));  
  5. glVertex2iv(vertices + (1*2));  
  6. glColor3fv(color + (2*3));  
  7. glVertex2iv(vertices + (2*2));  
  8. glEnd();  

glArrayElement每个顶点还是调用一次,恩,不够简洁么。。再来看一个更简洁点儿的。 
引用

void glDrawElements(GLenum mode, GLsize count, GLenum type, const GLvoid *indices); 
    使用count个元素定义一个几何图元序列,这些元素的索引值保存在indices数组中。type是indices数组中数据的类型。mode参数指定了被创建的是哪种类型的图元。

还是以刚刚的例子继续替换吧,它的效果与刚刚的效果是一样的,还需要重复?需要,好吧。。自己copy去~~: 
C++代码  收藏代码
  1. static GLubyte indices = {0, 1, 2};  
  2. glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, indices);  
posted on 2014-04-18 10:45  归海一刀  阅读(1091)  评论(0编辑  收藏  举报