Kevin

游戏开发闲谈

导航

顶点缓冲区

几个概念
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 0  
vao 定义结束 bind 0
vbo 在vao 内部 不能bind0

posted on 2015-04-29 21:23  iamkevin  阅读(1954)  评论(0编辑  收藏  举报