产生原因 OpenGL是按照CS结构设计的,当OPENGL需要数据的时候,必须从客户机内存传递到服务器,如果客户机和服务器属于不同的计算机,这样的数据效率缓慢,并且有时是冗余的 |
做法: 1.创建缓冲区对象 glGenBuffers(NUM_BUFFER,buffers); 2.激活缓冲区对象 glBindBuffer(target,buffer); GL_ARRAY_BUFFER //坐标,颜色 等 GL_ELEMENT_ARRAY_BUFFER //索引坐标 GL_TEXTURE_BUFFER//纹理缓冲 …… 3.用数据分配和初始化缓冲区对象 glBufferData(target,size,data,usage) usage: #define GL_STREAM_DRAW 0x88E0 #define GL_STREAM_READ 0x88E1 #define GL_STREAM_COPY 0x88E2 #define GL_STATIC_DRAW 0x88E4 #define GL_STATIC_READ 0x88E5 #define GL_STATIC_COPY 0x88E6 #define GL_DYNAMIC_DRAW 0x88E8 #define GL_DYNAMIC_READ 0x88E9 DRAW: 客户机指定了用于渲染的数据 READ:从OPENGL缓冲区读取数据值,并且在应用程序中用于各种鱼渲染不直接相关的计算过程 COPY:从OPENGL缓冲区读取数据值,作为用于渲染的数据 STREAM:缓冲区对象中数据需要经常更新,但是作为绘图或其他操作使用较少 STATIC:缓冲区数据只指定1次,但是这些数据使用频率非常高 DYNAMIC:缓冲区数据常常更新,并且使用频率也很高 4.激活顶点数组 5.为顶点数组指定数据,这里指定的数据在服务器存储的内存地址 |
glGenBuffers(NUM_BUFFER,buffers); glBindBuffer(GL_ARRAY_BUFFER,buffers[VERTICES]); glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW); glVertexPointer(3,GL_FLOAT,0,0); glEnableClientState(GL_VERTEX_ARRAY); glBindBuffer(GL_ARRAY_BUFFER,buffers[COLOR]); glBufferData(GL_ARRAY_BUFFER,sizeof(colors),colors,GL_STATIC_DRAW); glColorPointer(3,GL_FLOAT,0,0); glEnableClientState(GL_COLOR_ARRAY); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,buffers[INDICES]); glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(indices),indices,GL_STATIC_DRAW); |
缓冲区数据更改 方法1: glBufferSubData(Glenum target,GLintptr offset,Glsizeiptr size,const Glvoid* data) 用data指向数据更新target相关联的当前绑定缓冲区的对象中offset开始的size个字节数据 方法2: 使用glMapBuffer返回一个指向缓冲区对象的指针,可以在这个缓冲区写入新值。在完成了对缓冲区对象的数据更新之后,可以调用glUnmapBuffer(target)取消都这个缓冲区的映射。 |
数据在缓冲区对象向之间复制 void glCopyBufferSubData(GLenum readbuffer,GLenum writebuffer,GLinrptr readoffset,GLinrptr writeoffset,Glsizeiptr size) |
Glvoid* glMapBuffer(target,access) target:当前绑定缓冲区对象的数据存储 accrss: GL_READ_ONLY GL_WRITE_ONLY GL_WRITE_READ_ONLY |
glIsBuffer 查看缓冲区是否已被绑定 glDeleteBuffers 清空缓冲区对象 glUnmapBuffer(target) 对数据存储访问之后,调用取消对这个缓冲区的映射 |
#include "header.h" #define VERTICES 0 #define COLOR 1 #define INDICES 2 #define NUM_BUFFER 3 GLuint buffers[NUM_BUFFER]; float quard=0; GLfloat vertices[][3]={{0,0,50},//0 {100,0,50},//1 {100,100,50},//2 {0,100,50},//3 {0,0,-50},//4 {100,0,-50},//5 {100,100,-50},//6 {0,100,-50}//7 }; GLfloat colors[][3]={{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}, {0.3,0.4,0.5}, {0.5,0.6,0.7}}; GLubyte indices[][4]={{3,2,1,0},{7,6,5,4},{7,4,0,3},{6,5,1,2},{7,3,2,6},{0,4,5,1}}; void display(void) { glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glLoadIdentity(); glRotatef(quard,1,1,0); glDrawElements(GL_QUADS,24,GL_UNSIGNED_BYTE,0); glFlush(); glutSwapBuffers(); } void rotate() { quard+=0.1; glutPostRedisplay(); } void mouse(int button,int state,int x,int y) { switch(button) { case GLUT_LEFT_BUTTON: if(GLUT_DOWN==state) { glutIdleFunc(rotate); }else { //glutIdleFunc(0); } } } void init() { glClearColor(0.0,1.0,0.0,0.0); glClearDepth(1.0); glViewport(0,0,600,480); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-300,300,-100,380,-100,100); glMatrixMode(GL_MODELVIEW); glewInit(); glGenBuffers(NUM_BUFFER,buffers); glBindBuffer(GL_ARRAY_BUFFER,buffers[VERTICES]); glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW); glVertexPointer(3,GL_FLOAT,0,0); glEnableClientState(GL_VERTEX_ARRAY); glBindBuffer(GL_ARRAY_BUFFER,buffers[COLOR]); glBufferData(GL_ARRAY_BUFFER,sizeof(colors),colors,GL_STATIC_DRAW); glColorPointer(3,GL_FLOAT,0,0); glEnableClientState(GL_COLOR_ARRAY); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,buffers[INDICES]); glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(indices),indices,GL_STATIC_DRAW); } int main(int argc,char** argv) { glutInit(&argc,argv); glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB); glutInitWindowSize(600,480); glutInitWindowPosition(100,100); glutCreateWindow("缓冲区对象"); init(); glutDisplayFunc(display); glutMouseFunc(mouse); glutMainLoop(); return 0; }