定义
OpenGL着色语言(OpenGL Shading Language)是用来在OpenGL中着色编程的语言,也即开发人员写的短小的自定义程序,他们是在图形卡的GPU (Graphic Processor Unit图形处理单元)上执行的,代替了固定的渲染管线的一部分,使渲染管线中不同层次具有可编程性。比如:视图转换、投影转换等。GLSL(GL Shading Language)的着色器代码分成2个部分:Vertex Shader(顶点着色器)和Fragment(片断着色器),有时还会有Geometry Shader(几何着色器)。负责运行顶点着色的是顶点着色器。它可以得到当前OpenGL 中的状态,GLSL内置变量进行传递。GLSL其使用C语言作为基础高阶着色语言,避免了使用汇编语言或硬件规格语言的复杂性。
GLSL结构
#version version_number
in type in_variable_name;
in type in_variable_name;
out type out_variable_name;
uniform type uniform_name;
void main()
{
...
out_variable_name = weird_stuff_we_processed;
}
main
类似C语言的
入口函数
GLSL
定义in
和out
关键字来保证数据的传输,比如顶点着色器想将顶点颜色传给片段着色器着色器,就只需要在顶点着色器中定义out vec4 vertextColor
,然后在片段器中定义in vec4 vertextColor
就可以在片段着色器中使用顶点的颜色了。
- 在之前绘制三角形的时候也看见过一点着色器代码,在运行顶点着色器的时候,我们需要通过外部告诉顶点着色器相关的顶点属性,所以这时候就需要看另一个关键词了
layout(location=0)
,比如你想从外面接收顶点的位置的信息:layout(location = 0) in vec3 aPos;
,这时候你就可以在代码中使用glVertexAttribPointer
查询并设置相关属性。0
表示你的顺序id,如果你想给顶点着色器传其他参数,就可以新增layout(location = 0) in ? ?;
,以下为示例代码:
const char* vertexShaderSource = "#version 330 core\n"
"layout(location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
"gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\n";
Uniform
关键词,也是一种从CPU向GPU发送数据的方式,并且Uniform
为全局变量,所以需要保证在着色其为独一无二的变量,它可以在着色其的任何阶段进行访问,并会一直保存他们的数据,如果在着色器代码中定义了Uniform
千万记得在OpenGL
中使用它,不然会被GLSL
自动删除,造成不知名错误.。
OpenGL
中设置Uniform
变量,首先使用glGetUniformLocation
查询变量所在的位置值,然后就可以通过glUniform1f
设置其变量。在设置Uniform
时,可以不使用glUseProgram
,但是如果在更新Uniform
时,就需要调用后才能更新。针对不同的变量类似,也有其他的设置函数,比如glUniform3fv
、glUniform4fv
,示例代码如下:
void SetFloat(const char* name, float value)
{
const unsigned int loc = glGetUniformLocation(ShaderProgram, name);
glUniform1f(loc,value);
}
void Shader::SetVector3(const char* name, glm::vec3 vec3)
{
const unsigned int loc = glGetUniformLocation(ShaderProgram, name);
glUniform3fv(loc, 1, glm::value_ptr(vec3));
}
void SetVector4(const char* name, glm::vec4 vec4)
{
const unsigned int loc = glGetUniformLocation(ShaderProgram, name);
glUniform4fv(loc, 1, glm::value_ptr(vec4));
}
void Shader::SetMatrix4(const char* name, glm::mat4 matrix)
{
unsigned int loc = glGetUniformLocation(ShaderProgram, name);
glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(matrix));
}
- 设置
Uniform
的函数表,格式glUniform
+n
+类型
,(n:1~4, 矩阵例外
序号 |
类型 |
解释 |
示例 |
0 |
f |
float值 |
glUniform1f |
1 |
i |
int值 |
glUniform1i |
2 |
ui |
无符号int值 |
glUniform1ui |
3 |
fv |
float向量值 |
glUniform4fv |
4 |
Matrix2fv |
2*2矩阵 |
glUniformMatrix2fv |
5 |
Matrix3fv |
3*3矩阵 |
glUniformMatrix3fv |
6 |
Matrix4fv |
4*4矩阵 |
glUniformMatrix4fv |
GLSL支持变量
序号 |
变量 |
解释 |
0 |
int |
整型 |
1 |
float |
浮点型 |
2 |
double |
双精度浮点型 |
3 |
uint |
无符号整型 |
4 |
vecn |
包含n个float分量的默认向量(n表示可以有1、2、3或者4个数量) |
5 |
bvecn |
包含n个bool分量的默认向量(n表示可以有1、2、3或者4个数量) |
6 |
iecn |
包含n个int分量的默认向量(n表示可以有1、2、3或者4个数量) |
7 |
uvecn |
包含n个uint分量的默认向量(n表示可以有1、2、3或者4个数量) |
8 |
dvecn |
包含n个double分量的默认向量(n表示可以有1、2、3或者4个数量) |
设置三角形的顶点颜色
const float vertices[18] = {
-0.5f, -0.5f, 0.0f, 1.0f,0.0f,0.0f,
0.5f, -0.5f, 0.0f, 0.0f,1.0f,0.0f,
0.0f, 0.5f, 0.0f, 0.0f,0.0f,1.0f
};
- 在顶点着色器中新增顶点颜色的输入,颜色变量的属性位置更改为
1
,并定义一个vertexColor
向片段着色器输出顶点颜色
const char* vertexShaderSource = "#version 330 core\n"
"layout(location = 0) in vec3 aPos;\n"
"layout(location = 1) in vec3 aColor;\n"
"out vec3 vertextColor;\n"
"void main()\n"
"{\n"
"gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"vertextColor =aColor;\n"
"}\n";
- 将片段着色器中定义一个颜色变量接收顶点着色器传过来的顶点颜色,并将最终的输出颜色改为顶点的颜色
const char* fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"
"in vec3 vertextColor;\n"
"void main()\n"
"{\n"
" FragColor = vec4(vertextColor,1.0);\n"
"}\n";
- 使用
glVertexAttribPointer
更新顶点数据
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3*sizeof(float)));
glEnableVertexAttribArray(1);
- 运行截图