码迷,mamicode.com
首页 > 编程语言 > 详细

顶点数组以及解引用单个数组

时间:2015-08-27 15:31:45      阅读:179      评论:0      收藏:0      [点我收藏+]

标签:顶点数组-解引用数组

法线向量
物体的法线向量定义了他的表面在空间中的方向。具体地说定义了他相对于光源的方向。OpenGL使用法线向量确定了这个物体各个顶点所接受的光照。在定义物体的几何形状时,同时也定义了他的法线向量。可以使用glNormal*()函数,把当前法线向量设置为这个函数所标示的值,以后调用glVertex*()时,就会把当前法线向量分配给所指定的顶点。每个顶点尝尝具有不同的法线,所以需要交替调用这个函数。

glBegin(GL_POLYGON);
glNormal3fv(n0);
glVertex3fv(v0);
glNormal3fv(n1);
glVertex3fv(v1);
glNormal3fv(n2);
glVertex3fv(v2);
glNormal3fv(n3);
glVertex3fv(v3);
glEnd();

由于法线向量只表示方向,因此长度无关紧要。法线可以指定为任意长度,但是在执行光照计算之前,需要向量单位化。如果模型只涉及旋转和移动,法线向量就可以保证规范化。如果进行了不规则的变换,在变换之后OpenGL会自动对法线向量进行规范化。为了启用这个功能调用glEnable(GL_NORMALIZE);如果提供了单位长度的法线,并且只进行均匀缩放,就可以使用glEnable(GL_RESCALE_NORMAL),用一个常量因子对法线缩放,恢复单位长度。
顶点数组
OpenGL需要大量的函数调用才能完成对几何图元的渲染,以及共享顶点的冗余处理问题。使用顶点数组,允许只用少数几个数组指定大量与顶点相关的数据,并用少量函数调用访问这些数据,把数据放在顶点数组可以提高应用程序的性能。
使用顶点数组对几何图元进行渲染需要三个步骤:
1. 激活最多可达8个数组,每个数组用于存储不同类型的数据:顶点坐标,表面法线,RGBA颜色,辅助颜色,颜色索引,雾坐标,纹理坐标以及多边形边界坐标。
2. 把数据放入数组中。这些数组是通过它们的内存地址(指针)进行访问的。在客户机服务器模型中,这些数组存储在客户机的地址空间中,除非使用缓冲区对象,这时候数据存储在服务器内存中。
3. 用这些数据绘制几何图形。OpenGL通过指针从所有的被激活数组中获取数据。在客户机-服务器模型中,数据被传输到服务器地址空间中。有三种方式完成这个任务:
1. 访问单独数组元素
2. 创建一个单独数组元素的列表
3. 线性的处理数组元素
启用数组:
调用glEnableClientState()函数,激活选择的数组,在实践中同时可激活数组只有6个,有些数组不能同时激活,例如显示模式可以支持RGBA或颜色索引,但是不能同时支持这两种。
Void glEnableClientState(GLenum array)array参数是一个符号常量。
例如需要使用光照,可能需要为每个顶点定义一条法线向量,这种情况下使用顶点数组时候,需要同时激活表面法线数组以及顶点坐标数组

glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);

如果在某个时刻需要关闭光照,需要调用glDisable()函数来关闭光照状态,在关闭光照状态之后,还需要停止更改表面法线状态的值,因为这种做法完全浪费
调用 gldisableClientState(GL_NORMAL_ARRAY);
指定数组数据:
用一条命令指定客户空间中的一个数组。共有8个函数可以用来指定数组,每个函数用于指定一个不同类型的数组。以glVertexpointer为例

void glVertexPointer(GLint size,GLenum type,GLsize stride,const Glvoid* pointer);

指定了需要访问的空间坐标数据。Size是每个顶点的坐标数量,必须是2,3,4.stride是连续顶点之间的字节偏移量,如果为0,数组中顶点便是紧密相连。type指定了数组中每个坐标的数据类型。Pointer是数组包含的第一个顶点的第一个坐标的内存地址。
使用顶点数组表示RGBA颜色和顶点坐标。RGB浮点值以及与它们对应的整型坐标值被加载到GL_COLOR_ARRAYGL_VERTEX_ARRAY数组中。

static GLint vertices[]={
        25,25,
        100,325,
        175,25,
        175,325,
        250,25,
        325,325
    };

    static GLfloat colors[] ={1.0,0.2,0.2,
                              0.2,0.2,1.0,
                              0.8,1.0,0.2,
                              0.75,0.75,0.75,
                              0.35,0.35,0.35,
                              0.5,0.5,0.5
    };
    glEnableClientState(GL_COLOR_ARRAY);
    glEnableClientState(GL_VERTEX_ARRAY);

    glColorPointer(3,GL_FLOAT,0,colors);
    glVertexPointer(2,GL_INT,0,vertices);

跨距
Gl*Pointer()函数的stride参数告诉OpenGL如何访问指针数组中的数据。他的值应该是两个连续的指针元素之间的字节数量。如果顶点的RGB值和顶点坐标存储在同一个数组中,如下所示

static GLfloat intertwined[]=
    {
        1.0,0.2,1.0,100.0,100.0,0.0,
        1.0,0.2,0.2,0.0,200.0,0.0,
        1.0,1.0,0.2,100.0,300.0,0.0,
        0.2,1.0,0.2,200.0,300.0,0.0,
        0.2,1.0,1.0,300.0,200.0,0.0,
        0.2,0.2,1.0,200.0,100.0,0.0
    };

如果只想引用数组中的颜色值或者顶点坐标则需要跳跃读取

glColorPointer(3,GL_FLOAT,6*sizeof(GLfloat),&intertwined[0]);
glVertexPointer(3,GL_FLOAT,6*sizeof(GLfloat),&intertwined[3]);

如果stride为0,数组中数据是一致的只包含颜色值,或者顶点坐标等。
3解引用和渲染
在顶点数组内容被解引用之前,数组一直保存在客户端,他们的内容很容易进行修改。在这一步骤中,数组中数据被提取,接着发送到服务器,然后发送到图形处理管线进行渲染。可以从单个数组元素提取数据,也可以从一个有序的数组元素列表中提取。
解引用单个数组

Void glArrayElement(Glint ith);

获取当前所有已启用数组的的第ith个顶点的数据
对于顶点坐标数组,对应的函数是glVertex[size][type]v(),其中size和type由glvertexPointer()函数定义的。其它启用的数组类似。
glArrayElement通常在glBegin()glEnd()之间调用,下面程序使用取自启用的顶点数组的第3,4,6个顶点绘制一个三角形。

void Init()
{
    glClearColor(0.0,0.0,0.0,0.0);
    glShadeModel(GL_FLAT);
}
void myDisplay()
{
    static GLint vertices[]={
        25,25,
        100,325,
        175,25,
        175,325,
        250,25,
        325,325
    };

    static GLfloat colors[] ={1.0,0.2,0.2,
                              0.2,0.2,1.0,
                              1.0,1.0,1.0,
                              1.0,1.0,1.0,
                              0.35,0.35,0.35,
                              1.0,1.0,1.0
    };

    glEnableClientState(GL_COLOR_ARRAY);
    glEnableClientState(GL_VERTEX_ARRAY);

    glColorPointer(3,GL_FLOAT,0,colors);
    glVertexPointer(2,GL_INT,0,vertices);

    glBegin(GL_TRIANGLES);
    glArrayElement(2);
    glArrayElement(3);
    glArrayElement(5);
    glEnd();
    glFlush();

    glColor3fv(colors +(2*3));
    glVertex2iv(vertices +(2*2));

}

void reshape(int w,int h)
{
    glViewport(0,0,(GLsizei) w,(GLsizei) h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0.0,(GLdouble) w,0.0,(GLdouble) h);

}


int _tmain(int argc, _TCHAR* argv[])
{

    glutInit(&argc,(char**)argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
    glutInitWindowPosition(100,100);
    glutInitWindowSize(400,400);
    glutCreateWindow("绘制三角形");
    Init();
    glutDisplayFunc(&myDisplay);
    glutReshapeFunc(reshape);
    glutMainLoop();
    return 0;
}

运行结果生成一个白色的三角形
glColor3fv(colors +(2*3));
glVertex2iv(vertices +(2*2));
glColor3fv(colors +(3*3));
glVertex2iv(vertices +(3*2));
glColor3fv(colors +(5*3));
glVertex2iv(vertices+(5*2));

等价于解引用函数的那三行代码,由于glArrayElement()对于每个顶点只调用一次,因此他可能会减少函数的调用数量,从而提高程序总体性能。在绘图期间不要修改数组元素内容。

版权声明:本文为博主原创文章,未经博主允许不得转载。

顶点数组以及解引用单个数组

标签:顶点数组-解引用数组

原文地址:http://blog.csdn.net/fatestay_dc/article/details/48026155

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!