前言
上一篇文章我们啰哩啰嗦的介绍了环境的搭建,这篇文章我们将继续啰哩啰嗦的认识且编写出第一个Shader。
本文目标
认识并且编写出第一个最简单的Shader。
正文
1.渲染管线
在解释Shader之前,我们需要了解一下OpenGL的渲染管线,下图是OpenGL的渲染管线示意图。
OpenGL渲染管线示意图OpenGL的渲染管线主要包括:
1.准备数据。
2.由Vertex Shader进行数据处理(Vertex Shader主要进行几何位置的处理,比如现在有一个三角形,它有三个顶点,Vertex Shader负责在空间里处理这些点的位置)。
3.顶点后处理,即Vertex Post-Processing阶段(主要包括Clipping,顶点坐标归一化和viewport变换)。
4.Primitive组装(比如3点组装成一个3角形)。
5.光栅化成一个个像素。
6.使用Fragment Shader来处理这些像素(处理像素的颜色等等)。
7.采样处理(主要包括Scissor Test, Depth Test, Blending, Stencil Test等)。
2.什么是Shader
上图中的淡蓝色区域是可以编程的阶段,从图中我们不难发现我们有两个可以编程的阶段,分别是Vertex Shader和Fragment Shader,所以我们可以理解Shader为可编程管线的算法片段。
有的朋友可能不太理解管线是什么意思,从图中我们可以看出,渲染图像的流程就像流水线一样,想象一下你在一条流水线上工作,黄色区域是机器自动操作流程,蓝色区域是我们手动加工的流程。
3.GPU的工作流程
因为OpenGL是需要跑在GPU上的,所以我们需要稍微了解一下GPU的工作流程,方便于我们理解后面学习的内容。
首先GPU是并行的,它拥有成千上百个核,每个核都可以处理顶点,GPU会把我们的顶点数据载入到这些核进行处理,所以它同时处理的顶点数据是它拥有核的个数。
现实中我们可能知道玩大型的游戏需要一个好的显卡,现在我们模糊的了解了为什么需要好的显卡,因为图像在屏幕上显示需要经过大量的计算。
4.编写Shader
编写Shader需要用到一种叫做GLSL(全称OpenGL Shader Language)的语言,这是一种专门为GPU设计的语言,它跟C语言有些类似,可以放在GPU里并运行。
通过上面的解析,我们已经知道有两个阶段可以编程,因此我们需要建立两个Shader文件,分别以vsh和fsh结尾,其中vsh里面写Vertex Shader,fsh里面写Fragment Shader。
- 删掉项目里已经存在的Shader.vsh和Shader.fsh里的代码。
- 修改Shader.vsh代码如下。
attribute vec3 position;
void main()
{
gl_Position = vec4(position,1.0);
}
- 修改Shader.fsh代码如下。
void main()
{
gl_FragColor = vec4(1.0);
}
5.Shader代码的解释
上面的代码是最简单的Shader程序,我们可以看到所有的Shader程序都有一个main
函数,这跟我们C语言是一样的。
其中在vsh文件中我们看到出现了attribute
和vec3
,vec4
这样的关键字,在GLSL中这样的关键字还有很多,在这里我们暂时不解释,以后用到再解释具体的含义,这里我们先解释一下attribute
和vec
。
attribute
只会在Vertex Shader中出现,这是外部传递进来的数据,通常用来保存点的位置。
vec3
用来保存3个浮点数的矢量,vec4
用来保存4个浮点数的矢量,同理还有vec2
用来保存2个浮点数的矢量。
上面我们的变量名字为position这是一个vec3
的变量,我们以后会给它传递点的位置,也就是点的xyz坐标。
在main函数里我们给gl_Position
赋值,因为Vertex Shader是用来处理几何信息,也就是点的位置,所以它必须被赋值。它是vec4
类型的,至于为什么不是vec3
,因为牵扯到矩阵转换,这里不做解释,有兴趣的同学可以自行搜索一下。
同理在Fragment Shader中,我们给gl_FragColor
函数赋值,就是简单的rgba表示,只不过这里的范围是0.0~1.0。
PS:vec4(1.0)
等同于vec4(1.0,1.0,1.0,1.0)
,vec4(position,1.0)
相当于vec4(x,y,z,1.0)
,这是构造器写法,大家可以自行搜索。
结束
在本文中我们已经了解了什么是Shader以及实现了一个最简单的Shader,通过这个最简单的Shader我们看清了它的模样,OpenGL的大门已经为我们打开。
网友评论