引言
上一节我们绘制了自己的三角形,今天来聊聊 OpenGL 的着色器。
具体来讲,在经典的渲染情景中通常以顶点和索引缓冲区的形式向 GPU 发送一堆数据,然后我们要做的实际上是在 GPU 上获取数据,然后对其进行处理(主要是通过不同类型的着色器)。
着色器的类型多种多样,但有两种类型的着色器使用得最多:
- 顶点着色器
- 片段着色器
在我们的渲染 API OpenGL 中也被称为像素着色器。
着色器实现
Infinite/Render
目录下新建 Shader.h
:
|
构造函数目前使用字符串传递,在之后我们可能会改为文件流传输。
在相同的目录下新建 Shader.cpp
,快速构造头文件中函数的定义:
|
拷贝示例函数,并且修改为 vertexSrc
和 fragmentSrc
:
Shader::Shader(const std::string& vertexSrc, const std::string& fragmentSrc) |
我们做的第一件事情是创建着色器:
// Create an empty vertex shader handle |
一个小插曲,之前我们使用过的 API 是以 glGen...()
开头的,而现在调用的是 glCreate...()
。
// Send the vertex shader source code to GL |
这部分我们发送顶点着色器源码至 GL,并且正确编译它。
GLint isCompiled = 0; |
这段代码则是检测编译成功还是失败。倘若编译失败,我们获取日志的长度提取信息,输出日志为什么我们的着色器无法编译,最好我们删除着色器。
这里我们加入引擎的报错和断言:
... |
后面的片段着色器其实在做相同的事情,加入引擎自己的调试报错和断言:
// Create an empty fragment shader handle |
然后我们创建程序,它将是我们在 GPU 上运行的两个着色器的组合总线,然后编译并链接程序:
// Vertex and fragment shaders are successfully compiled. |
最后与之前类似,就是检测编译成功与否:
// Note the different functions here: glGetProgram* instead of glGetShader*. |
最后删除着色器文件即可。
返回 Application.h
,加入着色器头文件和着色器:
#pragma once |
最后写入着色器即可:
Application::Application() |
预生成文件
-include "Infinite/vendor/GLFW" |