目录
典型着色器结构
数据类型
顶点着色器特性
片段着色器特性
从顶点着色器向片段着色器发送数据
从CPU中的应用向GPU中的着色器发送数据
GLSL规范:https://www.khronos.org/registry/OpenGL/specs/gl/GLSLangSpec.1.20.pdf
GLSL是类C语言
着色器是各自独立的小程序,但是最终各个着色器是要link到一起构成一个整体程序的
#version version_number
in type in_variable_name;
in type in_variable_name;
out type out_variable_name;
uniform type uniform_name;
int main()
{
// 处理输入并进行一些图形操作
...
// 输出处理过的结果到输出变量
out_variable_name = weird_stuff_we_processed;
}
GLSL中包含了C的基本数据类型int float double uint bool,还包含了两个容器类型向量(Vector)和矩阵(Matrix),由于向量可以是一维的,所以直接使用向量和矩阵两个数据类型即可。
顶点着色器的每个输入变量叫做顶点属性。
能声明的顶点属性是有限制的,一般由硬件来决定。
OpenGL确保至少有16个包含4分量的顶点属性可用。
顶点着色器的输入是从顶点数据中直接接收数据,即从VBO中直接接收数据,
下面代码定义的顶点数据vertices[]将会通过VBO,传输给顶点着色器的输入vec3 posVertex
static const float vertices[] ={
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
-0.5f, 0.5f, 0.0f
};
glGenBuffers(1,&VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof (vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3* sizeof (float),(void*)0);
glEnableVertexAttribArray(0);
//顶点着色器程序
#version 330
layout(location = 0) in vec3 posVertex;
void main()
{
gl_Position = vec4(posVertex, 1.0f);
}
片段着色器必须要定义一个vec4的输出,因为片段着色器需要生成一个最终输出的颜色。如果在片段着色器中定义输出颜色,OpenGL会把物体渲染为黑色或者白色。
在link着色器的时候,当类型和名字都一样的时候,OpenGL就会把两个变量链接到一起
//顶点着色器
#version 330 core
layout (location = 0) in vec3 aPos; // 位置变量的属性位置值为0
out vec4 vertexColor; // 为片段着色器指定一个颜色输出
void main()
{
gl_Position = vec4(aPos, 1.0); // 注意我们如何把一个vec3作为vec4的构造器的参数
vertexColor = vec4(0.5, 0.0, 0.0, 1.0); // 把输出变量设置为暗红色
}
/*************************************************************/
//片段着色器
#version 330 core
out vec4 FragColor;
in vec4 vertexColor; // 从顶点着色器传来的输入变量(名称相同、类型相同)
void main()
{
FragColor = vertexColor;
}
OpenGL通过将着色器中变量定义前加入uniform关键字,来声明改变量中的数据可以从CUP传入。
uniform特性:
uniform的使用:
在一个着色器中添加uniform
关键字至类型和变量名前来声明一个GLSL的uniform
#version 330 core
out vec4 FragColor;
//1.在OpenGL程序代码中设定这个变量
uniform vec4 ourColor;
void main()
{
FragColor = ourColor;
}
/******************************************************************/
float greenValue = (sin(timeValue) / 2.0f) + 0.5f;
//2.获取uniform "ourColor"的位置
int vertexColorLocation = glGetUniformLocation(shaderProgram, "ourColor");
//3.更新ourColor前必须调用glUseProgram
glUseProgram(shaderProgram);
//4.通过glUniform4f更新GPU中的数据
glUniform4f(vertexColorLocation, 0.0f, greenValue, 0.0f, 1.0f);