着色器是运行在GPU的小程序,为图形渲染管线某个特定部分而运行。着色器是一种把输入转化为输出的程序。相互之间不能通信,只有输入输出的联系。
GLSL
GLSL是为图形计算量身定制的,包含针对向量和矩阵操作的有用特性。
声明版本、输入输出变量、uniform、main;
着色器入口点都是main函数。
顶点着色器每个输入变量也叫顶点属性。
数据类型
向量
vecn 包含n个float分量的默认向量
bvecn 包含n个bool分量的向量
ivecn 包含n个int分量的向量
uvecn 包含n个unsigned int分量的向量
dvecn 包含n个double分量的向量
输入与输出
in out
uniform
从CPU向GPU中着色器发送数据的方式,但是uniform和顶点属性不同。
区别:
1、uniform是全局的,变量在每个着色器程序对象都是唯一的;
2、无论设置成什么,会一直保存数据,直到被重置或更新。
如果你声明了一个uniform却在GLSL代码中没用过,编译器会静默移除这个变量,导致最后编译出的版本中并不会包含它,这可能导致几个非常麻烦的错误,记住这点!
在游戏循环的每一次迭代中(所以他会逐帧改变)更新这个uniform,否则三角形就不会改变颜色。下面我们就计算greenValue然后每个渲染迭代都更新这个uniform:
while(!glfwWindowShouldClose(window))
{
// 输入
processInput(window);
// 渲染
// 清除颜色缓冲
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// 记得激活着色器
glUseProgram(shaderProgram);
// 更新uniform颜色
float timeValue = glfwGetTime();
float greenValue = sin(timeValue) / 2.0f + 0.5f;
int vertexColorLocation = glGetUniformLocation(shaderProgram, "ourColor");
glUniform4f(vertexColorLocation, 0.0f, greenValue, 0.0f, 1.0f);
// 绘制三角形
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
// 交换缓冲并查询IO事件
glfwSwapBuffers(window);
glfwPollEvents();
}
更多属性
在片段着色器中进行的所谓片段插值(Fragment Interpolation)的结果。当渲染一个三角形时,光栅化(Rasterization)阶段通常会造成比原指定顶点更多的片段。光栅会根据每个片段在三角形形状上所处相对位置决定这些片段的位置。
基于这些位置,它会插值(Interpolate)所有片段着色器的输入变量。比如说,我们有一个线段,上面的端点是绿色的,下面的端点是蓝色的。如果一个片段着色器在线段的70%的位置运行,它的颜色输入属性就会是一个绿色和蓝色的线性结合;更精确地说就是30%蓝 + 70%绿。
自己的着色器类
自己写一个类,来从硬盘读取着色器,编译链接,错误检测;
代码就不贴了,就是将之前的封装了起来!