以下操作只保证在兼容模式下可行,整理来自红宝书
由于OpenGL需要进行大量的函数调用对几何图元进行渲染,为了减少函数调用次数以及相邻多边形的共享顶点的冗余处理,OpenGL提供了顶点数组函数,
1.1使用顶点数组的一般步骤是:激活最多可达八个数组,可用于存储不同类型的数据:顶点坐标、表面发现法线、RGBA颜色、辅助颜色、颜色索引、雾坐标、纹理坐标以及多边形的边界标志
实现函数:
glEnableClientState(GLenum array)
GLenum array可以是:GL_VERTEX_ARRAY,GL_COLOR_ARRAY,GL_INDEX_ARRAY,GL_NORMAL_ARRAY...等等具体可见红宝书第43页内容,如果使用光照,需要为每个顶点定义一条法线向量,需要同时激活表面法线数组和顶点坐标数组
用glDisableClientState()来关闭
1.2把数据放入数组,数组通过指向它们内存位置的指针进行访问
实现函数:
void glVertexPointer(GLint size(每个顶点的坐标数量,必须是2/3/4),GLenum type(GL_SHORT,GL_INT,GL_FLOAT,GL_DOUBLE),GLsize stride(连续顶点之间的字节偏移量,为零时顶点紧密相连),const GLvoid *pointer(数组中第一个顶点第一个坐标的内存地址))
void glIndexPointer(type,stride,pointer)
void NormalPointer(type,stride,pointer)
1.3用这些数据绘制几何图形。OpenGL通过对指针进行解引用,从所有被激活的数组中获取数据,可以访问单独的数组元素,创建一个单独数组元素的列表,线性地处理数组元素,使用混合顶点数组
实现函数:
1.解引用单个数组元素:
void glArrayElement(GLint ith);通常在glBegin,end之间调用,这意味着我们后面基本上用不到它
2.解引用数组元素的一个列表:
void glDrawElements(mode(GL_POLYGON,GL_LINE_LOOP,GL_LINES,GL_POINTS),count,type(GL_UNSIGNED_BYTE,GL_UNSIGNED_SHORT,GL_UNSIGNED_INT),indices)
相当于
glBegin(mode);
for(i=0;i
2.缓冲区中的顶点数组,顶点数组可以减少调用函数的次数,但是数据仍然存储在内存里,每次需要顶点数组时,就会从客户机传输到OpenGL服务器,每帧都要传输数据对性能会造成影响,于是引入了缓冲区对象(buffer object)允许把数据存储在服务器中,并且只传输一次(前提是有足够的内存资源可以保存这些数据)如果需要修改数据,则可以更新存储在服务器中的值
要利用缓冲区对象存储顶点数据有以下几个步骤:
2.1为顶点数据创建缓冲区对象
void glGenBuffers(n,GLuint *buffers)
可以在buffers数组里面返回n个当前未使用的名字,表示缓冲区对象
2.2激活缓冲区对象:
也就是要将其绑定,绑定缓冲区对象表示选择未来的操作(数据初始化、渲染)将影响哪个缓冲区,需要多次调用
实现函数:
void glBindBuffer(GLenum target(GL_ARRAY_BUFFER/GL_ELEMENT_ARRAY_BUFFER),GLuint buffer);
glBuffer干的事情:
(1)当buffer是首次使用的GLuint,就创建一个新的缓冲区,把buffer分配给这个缓冲区对象,作为这个缓冲区对象的
名字->你就有了一个叫buffer的缓冲区
(2)当绑定到一个以前创建的缓冲区对象时,这个缓冲区对象就被激活了
把缓冲区对象绑定到0,OpenGL就会停止使用缓冲区对象
2.3用顶点数据分配和初始化缓冲区对象
实现函数:
void glBufferData(GL_ARRAY_BUFFER(顶点数组)/GL_ELEMENT_ARRAY_BUFFER(索引数据),size(存储相关数据需要的内存),*data(如果是NULL就会把申请的这些内存空间留着以后用),usage(GL_STREAM_DRAW,GL_STREAM_READ,GL_STREAM_COPY,GL_STATIC_DRAW...(我们一般用GL_STATIC_DRAW)));
整体实现代码:
GLuint buffers[NUM_BUFFERS];
GLfloat vertices[]={...}
GLuint indices[]={...}
//对数组创建缓存对象名字
glGenbuffers(NUM_BUFFERS,buffers);
//创建缓存对象
glBindBuffers(GL_ARRAY_BUFFER,buffers[VERTICES]);
//给缓存对象赋值
glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW);
//创建数组指针
glVertexPointer(2,GL_FLOAT,0,BUFFER_OFFSET(0));
glEnableClientState(GL_VERTEX_ARRAY);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,buffers[INDICES]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(indices),indices,GL_STATIC_DRAW);
glDrawElements(GL_QUADS,SIZE_OF_MEMORY,GL_UNSIGNED_INT,BUFFER_OFFSET(0));//BUFFER_OFFSET(0)这里我们写的是NULL,不太清白这个意思,挖个坑先