前言
本节介绍VAO 和 VBO
简写 | 展开 |
---|---|
VAO | Vertex Array Object |
VBO | Vertex Buffer Object |
- Vertex 都是顶点 对[结构体数组]中其中一个对象的称呼
- 都是对象Object --> glGenXXX(纯数字id-对象)
最终要实现:画一个三角形
glDrawArrays(GL_TRIANGLES,0,3);
一、shaders
其中三个叫做shader的需要用户自己写
渲染器 | ||
---|---|---|
vertex shader | 接收顶点 ↓ | 必须自己写 |
shape assmbly | 立刻组装成形状 | |
Geometry shader | 调整或增加顶点 ↓ | 有自动状态 |
光栅化 | 变成像素点 | |
fragment shader | 给像素点上色 ↓ | 必须自己写 |
test and blending | 互相遮挡 |
需要自己写的着色器,本例子要如何处理
着色器 | 操作 |
---|---|
vertex shader | 不调整坐标直接发给下一个着色器 |
Geometry shader | 使用自动化 |
fragment shader | 就是给个橙色就结束 |
二、标准化坐标NDC (Normalized Device Coordinates)
标准化设备坐标 NDC(Normalized Device Coordinates,NDC)
- 所有的坐标:中间是(0,0 , 0) ,x,y,z ∈(-1,1)
- 要求是:vertex shader执行后就是NDC
本例子的NDC坐标 (上图三角坐标)
float verteces[] = {
-0.5f,-0.5f,0.0f,
0.5f,-0.5f,0.0f,
0.0f,0.5f,0.0f
};
三、从内存给显存传数据
如何把点verteces传给显卡呢? 因为verteces=在内存中
- 定点着色器vertext shader
#version 330 core
layout (location = 0) in vec3 aPos;
void main(){
gl_Position = vec4(aPos.x,aPos.y,aPos.z,1.0);
}
解析:
代码 | 说明 |
---|---|
#version 330 core | openGL 3.3 核心模式 |
layout ( location = 0 ) | 从 0 这个位置拿数据,0==Attrib Index? |
in vec3 aPos | 外部数据都给了aPos ,aPos是vec3格式的 |
gl_Postiion | 是vertext shader的全局变量,就是要给后面的数字 |
顶点着色器中VBO VAO
类型 | ||
---|---|---|
1.VBO | Vertex Buffer Object - 顶点数组 | 数组中每个对象都是一个结构体 |
在GPU的显存上缓冲的数据 | 内存中传来的 | |
GL_ARRAY_BUFFER | 因为buffer种类特别多 所以glBindBuffer需要指定类型,才清楚操作那种 | |
2.VAO | Vertex Array Object | 描述结构体 |
数组里每一个项都对应一个属性的解析 | ||
只有一种不用指定类型 |
VAO存在的目的和意义
a. 当VBO 里面只有x,y,z坐标时,每个顶点如下
此时VAO中只有一个Attribute Pointer (3float=坐标)
b.当VBO。 里面有坐标 + 颜色+材质时,每个顶点如下
此时VAO中至少三个Attribute Pointer (3float=坐标 3*float=rgb 1材质)
//创建VBO VAO对象
GLuint VBO, VAO;
//产生openGL对象 glGenXXXX --> 都是int对象
glGenVertexArrays(1,&VAO);
glGenBuffers(1,&VBO);
//绑定VBO和VAO对象
glBindVertexArray(VAO); //-->只有一种类型
glBindBuffer(GL_ARRAY_BUFFER,VBO); // BindBuffer可以操作很多类型,必须指定GL_ARRAY_BUFFER
//如果data不是空的,则使用此数据初始化数据存储,跨域内存-->显存
glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW);
//告知显卡如何解析缓冲力的属性值,
//只有一种属性类型,
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,3*sizeof(float),(void*)0);
//开启VAO管理第一个属性值
glEnableVertexAttribArray(0);
//释放VBO VAO
glBindBuffer(GL_ARRAY_BUFFER,0);
glBindVertexArray(0);
因为buffer有很多种,所以glBindBuffer必须指定类型
但是VAO只有一种,所以不用再指定类型
设置VAO
声明:void glVertexAttribPointer(index,size,type,normalized,stride,offset)
e.g. glVertexArribPointer(0,3,GL_FLOAT,GL_FALSE,3sizeof(float),(void)0);
类型名称 | 说明 | 例子的数据 |
---|---|---|
GLunit index | 第几个属性 | index = 0 |
GLint size | 涉及几个值 | size = 3个 |
GLenum type | 这几个值得类型 | type = GL_FLOAT |
GLboolean normalized | 是否需要将其标准化 | 不需要,因为我已经给标准化了 |
GLsize stride | 下一个同类型间隔 | 这里是3*sizeof(float) |
const void* offiset | 就影响第一,和最前面差多少位置 |
开启Vertex(0)
glEnableVertexAttribArray(0);