顶点缓冲区
几个概念
vao --> vertex array object
vbo --> vertex buffer object
ibo --> index buffer object
绘制三角形为例
几种方式
1. 多个vbo 一个vao
2. 一个vbo一个vao
3. 一个vbo一个ibo一个vao
其中 前两个是只用顶点缓冲区 第三个是用索引缓冲区
分别介绍
1.利用定点缓冲区
1.1多个vbo一个vao
特点:位置信息和颜色信息分两个vbo
例子:
1 //位置数组 2 float positionData[] = { 3 -0.8f, -0.8f, 0.0f, 4 0.8f, -0.8f, 0.0f, 5 0.0f, 0.8f, 0.0f }; 6 7 //颜色数组 8 float colorData[] = { 9 1.0f, 0.0f, 0.0f, 10 0.0f, 1.0f, 0.0f, 11 0.0f, 0.0f, 1.0f }; 12 13 14 // 两个vbo一个负责上传位置信息到gpu一个负责上传颜色信息到gpu 15 GLuint vboHandles[2]; 16 glGenBuffers(2, vboHandles); 17 GLuint positionBufferHandle = vboHandles[0]; 18 GLuint colorBufferHandle = vboHandles[1]; 19 20 //绑定位置VBO以供使用 21 glBindBuffer(GL_ARRAY_BUFFER, positionBufferHandle); 22 //加载定点数据到VBO 23 glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(float), 24 positionData, GL_STATIC_DRAW); 25 26 //绑定颜色VBO以供使用 27 glBindBuffer(GL_ARRAY_BUFFER, colorBufferHandle); 28 //加载颜色数据到VBO 29 glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(float), 30 colorData, GL_STATIC_DRAW); 31 32 // 生成vao 33 glGenVertexArrays(1, &vaoHandle); 34 //绑定vao 35 glBindVertexArray(vaoHandle); 36 37 //绑定已经在gpu的位置数据到位置vbo上 38 glBindBuffer(GL_ARRAY_BUFFER, positionBufferHandle); 39 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (GLubyte *) NULL); 40 glEnableVertexAttribArray(0);//顶点坐标 41 42 //绑定已经在gpu的颜色数据到颜色vbo上 43 glBindBuffer(GL_ARRAY_BUFFER, colorBufferHandle); 44 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (GLubyte *) NULL); 45 glEnableVertexAttribArray(1);//顶点颜色 46 47 对应的draw函数 48 glBindVertexArray(vaoHandle); 49 glDrawArrays(GL_TRIANGLES, 0, 3); 50 glBindVertexArray(0);
1.2一个vbo一个vao
1 // 顶点格式结构体 2 struct Vertex { 3 float x, y, z; 4 float r, g, b; 5 Vertex(float _x, float _y, float _z, float _r, float _g, float _b) 6 { 7 x = _x; y = _y; z = _z; 8 r = _r; g = _g; b = _b; 9 }; 10 }; 11 // 用一个buffer来存储位置和颜色信息 12 Vertex data[] = { 13 Vertex(-0.8f, -0.8f, 0.0f, 1.0f, 0.0f, 0.0f), 14 Vertex(0.8f, -0.8f, 0.0f, 0.0f, 1.0f, 0.0f), 15 Vertex(0.0f, 0.8f, 0.0f, 0.0f, 0.0f, 1.0f), 16 }; 17 18 //生成vbo 19 GLuint vbo; 20 glGenBuffers(1, &vbo); 21 22 //绑定VBO以供使用 23 glBindBuffer(GL_ARRAY_BUFFER, vbo); 24 //加载数据到VBO 25 glBufferData(GL_ARRAY_BUFFER, 3 * sizeof(Vertex), 26 data, GL_STATIC_DRAW); 27 glBindBuffer(GL_ARRAY_BUFFER, 0); 28 // 把vbo放到vao中去 29 glGenVertexArrays(1, &vaoHandle); 30 glBindVertexArray(vaoHandle); 31 glBindBuffer(GL_ARRAY_BUFFER, vbo); 32 33 // 两次绑定已经在gpu的数据 34 // 第一次是绑定位置信息 35 // 第二次是绑定颜色信息 36 // 这个操作相当于dx的fvf也就是给显卡指定定点格式,只需要指定一个顶点其他的根据index在显卡中自动推导 37 // 单独分析一个顶点格式 前三个float代表位置后面三个float代表颜色所以第二次for循环glVertexAttribPointer的最后一个参数偏移了三个float也就是说从第四个float开始就是颜色信息 38 for (size_t i = 0; i < 2; ++i) 39 { 40 glVertexAttribPointer(i, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLubyte *) (i*sizeof(float) * 3)); 41 glEnableVertexAttribArray(i); 42 } 43 glBindBuffer(GL_ARRAY_BUFFER, 0); 44 45 对应的draw函数 46 glBindVertexArray(vaoHandle); 47 glDrawArrays(GL_TRIANGLES, 0, 3); 48 glBindVertexArray(0);
2.利用索引缓冲区
2.1一个vbo一个ibo一个vao
1 // 顶点格式结构体 2 struct Vertex { 3 float x, y, z; 4 float r, g, b; 5 Vertex(float _x, float _y, float _z, float _r, float _g, float _b) 6 { 7 x = _x; y = _y; z = _z; 8 r = _r; g = _g; b = _b; 9 }; 10 }; 11 /** 12 0----3 13 | \ | 14 | \ | 15 1----2 16 */ 17 // 顶点信息 18 Vertex data[] = { 19 Vertex(-0.8f, 0.8f, 0.0f, 1.0f, 0.0f, 0.0f), // 0 20 Vertex(-0.8f, -0.8f, 0.0f, 0.0f, 1.0f, 0.0f), // 1 21 Vertex(0.8f, -0.8f, 0.0f, 0.0f, 0.0f, 1.0f), // 2 22 Vertex(0.8f, 0.8f, 0.0f, 0.0f, 1.0f, 0.0f), // 3 23 }; 24 25 // 索引信息 26 unsigned short indexData [] = { 27 0, 1, 2, 28 0, 2, 3, 29 }; 30 31 // 上传索引信息的ibo(其实就是vbo,gl里面没有ibo,对等dx的ibo概念) 32 GLuint ibo; 33 glGenBuffers(1, &ibo); 34 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); 35 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData), indexData, GL_STATIC_DRAW); 36 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 37 38 // 上传顶点信息的vao 39 GLuint vbo; 40 glGenBuffers(1, &vbo); 41 glBindBuffer(GL_ARRAY_BUFFER, vbo); 42 glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW); 43 glBindBuffer(GL_ARRAY_BUFFER, 0); 44 45 // 绑定vbo到vao上面 46 glGenVertexArrays(1, &vaoHandle); 47 glBindVertexArray(vaoHandle); 48 glBindBuffer(GL_ARRAY_BUFFER, vbo); 49 50 // 两次绑定已经在gpu的数据 51 // 第一次是绑定位置信息 52 // 第二次是绑定颜色信息 53 // 这个操作相当于dx的fvf也就是给显卡指定定点格式,只需要指定一个顶点其他的根据index在显卡中自动推导 54 // 单独分析一个顶点格式 前三个float代表位置后面三个float代表颜色所以第二次for循环glVertexAttribPointer的最后一个参数偏移了三个float也就是说从第四个float开始就是颜色信息 55 for (size_t i = 0; i < 2; ++i) 56 { 57 glVertexAttribPointer(i, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLubyte *) (i*sizeof(float) * 3)); 58 glEnableVertexAttribArray(i); 59 } 60 61 // 最后绑定ibo 62 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); 63 glBindVertexArray(0); 64 65 对应的draw函数 66 glBindVertexArray(vaoHandle); 67 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0); 68 glBindVertexArray(0);
注意
glVertexAttribPointer 和 glEnableVertexAttribArray的index参数顺序和shader里面attribute的顺序是一致的
结尾 记得- -bindVertexArray 0vao 定义结束 bind 0vbo 在vao 内部 不能bind0