标签:顶点数组-解引用数组
法线向量
物体的法线向量定义了他的表面在空间中的方向。具体地说定义了他相对于光源的方向。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_ARRAY
和GL_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