一. 顶点数组对象(Vertex Array Object, VAO)
(1)什么是 VAO?
VAO 是一个状态对象,它记录了顶点属性配置的状态,比如:
- 使用哪个 VBO
- 每个
glVertexAttribPointer是怎么设置的 - 哪些属性启用/禁用(
glEnableVertexAttribArray)
VAO 是一个记录“顶点输入布局”的容器,保存你告诉 GPU 如何读取顶点数据的信息。
(2)为什么需要 VAO?
OpenGL 3.3 之后,VAO 是必需的。在早期版本中,OpenGL 会自动记录你的配置,但现代 OpenGL 强制你显式指定这些状态,这样可以:
- 避免错误
- 提高性能(因为切换 VAO 比重复配置更快)
- 实现更清晰的渲染流程
(3)VAO 的创建与使用
unsigned int VAO;
glGenVertexArrays(1, &VAO); //生成VAO
glBindVertexArray(VAO); //绑定VAO(激活)
//以下这段期间的配置会被VAO记录
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, (void*)0);
glEnableVertexAttribArray(0); //启用顶点属性数组
//解绑 VAO(可选)
glBindVertexArray(0);
之后,只需要绑定这个 VAO,就可以直接渲染:
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
(4)顶点属性(Input Vertex Attribute)
顶点属性是 GPU 渲染管线中,每个顶点附带的数据。例如:
| 属性名称 | 常见维度 | 类型 | 说明 |
|---|---|---|---|
| Position | vec3 (x, y, z) | float | 顶点坐标 |
| Normal | vec3 | float | 法线方向 |
| TexCoord | vec2 | float | 纹理坐标 |
| Color | vec4 | float 或 byte | 顶点颜色 |
二. 顶点缓冲对象(Vertex Buffer Object, VBO)
(1)什么是 VBO?
VBO 是显存(GPU memory)中的一块缓冲区,用于存储顶点数据。
通俗来讲:VBO 就是“把顶点数据从 CPU 传到 GPU 的容器”。
这种数据可以包括:
- 顶点位置(vec3)
- 颜色(vec3 或 vec4)
- 法线(vec3)
- 纹理坐标(vec2)
- 自定义属性(如骨骼权重、实例索引等)
(2)为什么需要 VBO?
在旧的 OpenGL(如 immediate mode)中,数据是每帧用 glVertex3f() 之类的函数传输的,非常慢。
现代 OpenGL 把数据一次性上传到 GPU(VBO),GPU 可以直接访问,速度极快。
(3)如何使用 VBO?
创建VBO
unsigned int VBO;
glGenBuffers(1, &VBO); // 生成一个缓冲对象 ID
绑定VBO(告诉 OpenGL:我现在操作的是这个缓冲)
glBindBuffer(GL_ARRAY_BUFFER, VBO);
上传数据到GPU
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
参数解释:
GL_ARRAY_BUFFER:类型为顶点数据sizeof(vertices):数据大小(单位是字节)vertices:CPU 端的原始数据GL_STATIC_DRAW:数据使用频率(静态绘制,通常不改动)
完整流程代码
float vertices[] = {
0.5f, 0.5f, 0.0f, // 顶点 1
-0.5f, 0.5f, 0.0f, // 顶点 2
-0.5f, -0.5f, 0.0f // 顶点 3
};
unsigned int VBO;
glGenBuffers(1, &VBO); // 创建
glBindBuffer(GL_ARRAY_BUFFER, VBO); // 绑定
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); // 上传数据
三. VAO 和 VBO 的关系
| 项目 | VBO(Vertex Buffer Object) | VAO(Vertex Array Object) |
|---|---|---|
| 功能 | 存储顶点数据(如位置、颜色、法线) | 存储“如何读取”这些数据的方式 |
| 作用对象 | 实际的 GPU 缓冲区数据 | 属性格式和状态(指针、启用等) |
| 是否必须 | 是,数据载体 | 是,OpenGL 3.3+ 中必须先绑定 VAO 才能绘制 |
| 生命周期 | 一般只创建一个大型 VBO 可复用 | 每种绘制结构一般创建一个 VAO |

Leave a comment