GLSL通过 vertex shader来处理每一个顶点的数据,例如确定顶点在模型变换,视图变换,投影变换后的空间坐标,纹理坐标,光线参数等。
vertex shader的代码运行在GPU上,相当于每一个GPU为每个顶点数据单独开一个线程来执行vertex shader,进行并行计算。
vertex shader需要两种基本的输入数据,一种是初始化后的各个顶点的原始空间坐标,这种变量用in 修饰,称为Attribute。Attribute除了包含顶点坐标,还可以包含其他信息,例如温度,密度等根据具体应用场景而定的一些属性,还可以包括纹理坐标,法向量等。需要让每一个vertex shader线程能够找到它要处理的顶点的相关Attribute,这个过程一般在OpenGL 的init 过程中实现,步骤为:
1,创建一个顶点数组对象VAO, VAO 用来管理顶点数组。调用函数glGenVertexArrays()和glBindVertexArray();
2,创建一个VERTEX_ARRAY_BUFFER,对buffer进行初始化,里面存储了顶点的Attribute等相关信息。调用glGenBuffers 和glBindBuffer,并且通过glBufferData() 初始化。
3,利用属性的索引值,调用使相应的顶点属性数组可用:glEnableVertexAttributeArray(),并且利用索引值指定该属性对应的buffer的位置。
4,如果要调用DrawElement来使用顶点的索引绘制,还需要创建一个GL_ELEMENT_ARRAY_BUFFER。
在绑定或激活顶点数组对象以后,接下来所开辟的Attribute Buffer 由该顶点数组对象管理。
代码示例:
glGenVertexArrays(1, &vaoID);
glGenBuffers(1, &vboVerticesID);
glGenBuffers(1, &vboIndicesID);
glBindVertexArray(vaoID);
glBindBuffer (GL_ARRAY_BUFFER, vboVerticesID);
//pass quad vertices to buffer object
glBufferData (GL_ARRAY_BUFFER, sizeof(vertices), &vertices[0], GL_STATIC_DRAW);
//enable vertex attribute array for position
glEnableVertexAttribArray(shader["vVertex"]);
glVertexAttribPointer(shader["vVertex"], 2, GL_FLOAT, GL_FALSE,0,0);
//pass quad indices to element array buffer
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndicesID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), &indices[0], GL_STATIC_DRAW);
第二种 vertex shader需要的基本的输入数据是用uniform修饰的,这种数据对于不同的顶点而言是一致的,不能由vertex shader修改,例如所有顶点共同需要的模型变换,视图变换,投影变换矩阵。
uniform块里面的变量也是在GPU 内存空间,要对其赋值和修改需要使用Buffer,步骤为:
一,创建一个与uniform块大小一致的buffer。
1,得到uniform 块的索引uboIndex;
2,根据uboIndex获取uniform块的大小uboSize;
3,利用uboSize 创建buffer;
二,向buffer赋值,对其初始化
1,得到uniform块中每个变量的索引indeces;
2,利用indeces获取每个变量的偏移地址,内存大小与类型
3,利用上述值对buffer进行操作,以赋值;
三,将buffer与uniform关联起来
1,创建buffer对象,得到其索引ubo;
2,利用uniform块的索引与buffer对象的索引,将二者关联;调用glBindBufferBase(GL_UNIFORM_BUFFER,uboIndex,ubo)。