Shader介绍
-
Shader(着色器程序), 一种运行在GPU端的,类C语言,用于处理顶点数据以及决定像素片元最终着色。
-
Shader对三角形数据的处理,分为顶点处理与片元处理,分别称为VertexShader与FragmentShader
GLSL语言
Graphic Library Shader Language的简写,着色器是使用一种叫GLSL的类C语言写成的。GLSL是为图形计算量身定制的,它包含一些针对向量和矩阵操作的有用特性。
GLSL语言特点:
- GLSL程序本质是一种将输入转化为输出的程序
- GLSL程序是一种非常独立的程序,彼此之间无法通信,只能通过输入输出相互承接。
Shader的编译与链接
Shader的编译相关代码
使用的API
| API | 介绍 |
|---|---|
| glCreateShader | 创建某一种shader程序(vs或者fs),并返回句柄 |
| glShaderSource | 给Shader程序注入源代码 |
| glCompileShader | 对Shader程序进行编译 |
void prepareShader()
{
// 1, vertexShader与fragmentShader的代码
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"
"}\0";
const char* fragmentShaderSource =
"#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
" FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\n\0";
// 2, 创建Shader
GLuint vertex, fragment;
vertex = glCreateShader(GL_VERTEX_SHADER);
fragment = glCreateShader(GL_FRAGMENT_SHADER);
// 3, 为Shader程序输入shader代码
glShaderSource(vertex, 1, &vertexShaderSource, nullptr);
glShaderSource(fragment, 1, &fragmentShaderSource, nullptr);
int success = 0;
char infoLog[1024];
// 4, Shader代码编译
glCompileShader(vertex); // 编译vertexShader
glGetShaderiv(vertex, GL_COMPILE_STATUS, &success); // 获取上一步vertexShader的编译是否成功
if (!success) { // success为0说明编译出错,为1没有错误
glGetShaderInfoLog(vertex, 1024, nullptr, infoLog); // 获取vertexShader编译的错误信息
std::cout << "Error: VERTEX SHADER COMPILE ERROR :" << infoLog << std::endl;
}
glCompileShader(fragment); // 编译fragmentShader
glGetShaderiv(fragment, GL_COMPILE_STATUS, &success); // 获取上一步fragmentShader的编译是否成功
if (!success) { // success为0说明编译出错,为1没有错误
glGetShaderInfoLog(fragment, 1024, nullptr, infoLog); // 获取fragmentShader编译的错误信息
std::cout << "Error: FRAGMENT SHADER COMPILE ERROR :" << infoLog << std::endl;
}
}
Shader链接相关代码
使用的API
| API | 介绍 |
|---|---|
| glCreateProgram | 创建最终可执行程序对象,返回句柄 |
| glAttachShader | 将编译好的Shader程序附着到program上 |
| glLinkProgram | 将program里面附着的程序进行链接,使之成为一个完整的shader可执行程序 |
void prepareShader()
{
// 1, vertexShader与fragmentShader的代码
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"
"}\0";
const char* fragmentShaderSource =
"#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
" FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\n\0";
// 2, 创建Shader
GLuint vertex, fragment;
vertex = glCreateShader(GL_VERTEX_SHADER);
fragment = glCreateShader(GL_FRAGMENT_SHADER);
// 3, 为Shader程序输入shader代码
glShaderSource(vertex, 1, &vertexShaderSource, nullptr);
glShaderSource(fragment, 1, &fragmentShaderSource, nullptr);
int success = 0;
char infoLog[1024];
// 4, Shader代码编译
glCompileShader(vertex); // 编译vertexShader
glGetShaderiv(vertex, GL_COMPILE_STATUS, &success); // 获取上一步vertexShader的编译是否成功
if (!success) { // success为0说明编译出错,为1没有错误
glGetShaderInfoLog(vertex, 1024, nullptr, infoLog); // 获取vertexShader编译的错误信息
std::cout << "Error: VERTEX SHADER COMPILE ERROR :" << infoLog << std::endl;
}
glCompileShader(fragment); // 编译fragmentShader
glGetShaderiv(fragment, GL_COMPILE_STATUS, &success); // 获取上一步fragmentShader的编译是否成功
if (!success) { // success为0说明编译出错,为1没有错误
glGetShaderInfoLog(fragment, 1024, nullptr, infoLog); // 获取fragmentShader编译的错误信息
std::cout << "Error: FRAGMENT SHADER COMPILE ERROR :" << infoLog << std::endl;
}
// 5, 创建一个program
GLuint program = 0;
program = glCreateProgram();
// 6, 将vs与fs编译好的结果放到program里
glAttachShader(program, vertex);
glAttachShader(program, fragment);
// 7, 执行program的链接操作,形成最终可执行shader程序
glLinkProgram(program);
glGetProgramiv(program, GL_LINK_STATUS, &success); // 检测链接的状态
if (!success) { // success为0说明编译出错,为1没有错误
glGetProgramInfoLog(vertex, 1024, nullptr, infoLog); // 获取program链接的错误信息
std::cout << "Error: PROGRAM LINK ERROR :" << infoLog << std::endl;
}
// 清理
glDeleteShader(vertex);
glDeleteShader(fragment);
}
进行绘制
使用的API
| API | 介绍 |
|---|---|
| glUseProgram | 设置绘制的时候所使用的Shader程序 |
| glBindVertexArray | 设置绘制的时候所使用的VAO几何信息 |
| glDrawArrays | 向GPU发起绘制渲染指令 |
void render()
{
GL_CALL(glClear(GL_COLOR_BUFFER_BIT)); // 画布清理
// 绑定program
glUseProgram(program);
// 绑定vao
glBindVertexArray(vao);
// 发出绘制指令
glDrawArrays(GL_TRIANGLES, 0, 3);
}