《Unity3D高级编程之进阶主程》第七章,Shader(三) - 渲染管道

SubShader模块

SubShader相当于子Shader的意思,SubShader在Shader中可以有很多个,每个SubShader都可以针对一种设备,但不是所有SubShader都会被采用。当Unity去展示一个模型时,会从第一个SubShader开始寻找是否匹配当前的设备,如果不匹配则与下一个SubShader继续匹配,直到找到能够匹配该设备为止。如果所有的SubShader都没有匹配上,则会使用 Fallback 标签的Shader。

===

格式如下:

SubShader
{
   [Tags]
   [CommonState]
   [Pass1] Pass { [Name and Tags] [RenderSetup] }
    [Pass2] Pass { [Name and Tags] [RenderSetup] }
    [Pass3] Pass { [Name and Tags] [RenderSetup] }
    […]
}
Fallback name  or Fallback Off

SubShader中可以定义了Tag标签,以及与Pass共同拥有的状态(Common State)。

Pass代表了一个渲染管道,每次通过Pass进行渲染都是通过一次完整渲染管道。

当一个SubShader被设备选中进行渲染时,定义的每个Pass都会渲染该物体一次,如果有很多灯光相互作用的话可能不止一次。通过Pass渲染一次会承担相当大的代价,所以我们在编写Shader Pass时需要小心,尽量减少Pass的使用,尽量将Pass数量最小化。

建议只有在我们无法使用单个Pass达到效果时,才启用多个Pass进行Shader编程。

所有在SubShader块中的渲染状态都可以在Pass中进行特殊化,也就是说定义在SubShader中的渲染状态是所有Pass公有的渲染状态,同时Pass可以定义自己的个性化的渲染状态。

比如以下例子:

SubShader
{
    Lighting Off
    Pass
    {
        Cull Front
    }
    Pass
    {
        Cull Back
    }
}
Fallback Diffuse

上述例子中 SubShader 设置了一个共同的渲染状态(Common State)就是把灯光影响关掉,灯光不再影响着色,第一个Pass中使用了独立的渲染状态是,裁切模型前半部分,第二个Pass中也使用了独立的渲染状态,裁切模型模型后半部分,然后他们共同拥有Common State是关闭灯光效果,所以第一个Pass就有了两个状态,一个是关闭灯光效果,第二个是裁切前半部分模型,而第二个Pass的也有两个状态,一个是关闭灯光效果,另一个是裁切后半部分模型。

SubShader最后还有一个Fallback标识,代表了当所有SubShader都对设备无效时,则选择备用的Shader作为替代。而当你认为无法替代,或者无需替代的时候可以关闭Fallback的功能 Facllbck off 。

在上面的例子中,Fallback “Diffuse”表示了,当所有SubShader都无法起作用的时候漫反射Diffuse替代当前Shader。

SubShader本身并不复杂,但里有几个重要的模块,以及这些模块中的标签和用途可能会稍微繁琐一些,下面我们要详细讲一讲Pass块的格式和属性内容。

渲染管道

提到渲染管道,不得不提到渲染管线流程,一整个渲染管线流程分八个阶段。

阶段1, 指定几何对象

这个阶段引擎在选择某些几何对象作为渲染目标。

理论上是一次抓取一个几何对象,但一般引擎都有批处理优化功能,一次抓取一批相同材质球的几何物体进行渲染。

阶段2,顶点处理

主要工作就是“变换三维顶点坐标”和“光照计算”。

顶点变换或坐标系变换包括:

3D中有以下几种空间:

    1,Object space,模型坐标

    模型空间也叫本地空间或者建模空间,这是我们定义物体三角形的坐标系,当一个建模人员创建一个物体的三维模型的时候,他选择了一个方便的方向、比例和位置来保存模型的组成顶点,当前物体的模型、空间和其他模型没用任何关系。

    2,World space,世界坐标;

    世界空间的目的就是给你的场景中的物体提供一个绝对的参考。

    3,Eye space,视觉空间(视锥裁剪)

    以摄像机为基准,以摄像机的位置为原点,摄像机朝向Z轴正方向,右边X轴为正方向,上边为Y轴正方向,之所以设置这个坐标系,主要是为了方便投影及裁剪操作。

    ###### 4,Clip and Project space,摄影,裁剪空间坐标(也叫屏幕坐标)

    该空间即世界空间的物体被投影到相应的投影上面之后,继而进行的裁剪操作所在的空间。

    Eye space坐标转换到Clip and Project space坐标的过程其实就是一个投影、剪裁、映射的过程。

除了坐标转换和光照计算,第2阶段还做了纹理坐标变换(纹理矩阵),材质状态纹理坐标生成。

这个阶段所接收到的数据则是每个顶点的属性特征,输出则是变换后的顶点数据。

这个阶段也是Shader里,vertex fragment着色器编程中 vertex 顶点转换函数的处理阶段,vetex顶点函数就在这个阶段编写顶点的变化。

阶段3,图元装配

在顶点处理之后,顶点的全部属性都已经被确定 在这个阶段顶点将会根据应用程序送往的图元规则.

阶段4,图元处理(裁剪 消隐)

将图元与用户定义的裁剪平面和模型投影矩阵所建立的视景比较,裁剪且丢弃位于视景和裁剪平面外部的图元,不再予以处理。

若是采用透视投影,那么将会对每个顶点的x,y,z坐标分别乘以透视矩阵。

接着由视口变换将顶点坐标变换至窗口坐标。视口变换,即把投影变换后的顶点X,Y坐标,根据用户设定的视口参数,变换到屏幕上对应的坐标。

最后执行消隐操作,把那些被遮挡的部分进行消除。

消隐操作,即隐藏面消除,即使经过了裁剪操作,对于每个物体,摄像机只能看到正对着摄像机的一面,对背对着摄像机的一面是看不到的。

这一步的任务就是把看不到的这一面消除掉,以免继续处理,影响计算机的性能和效率。

为了确定一个多边形是正对着还是背对着摄像机,就要用到我们在输入集合阶段指定多边形时的顶点顺序了,默认情况下,D3D规定按顺时针指定的三角形属于正面,逆时针为背面。确定顺时针还是逆时针,可以用如下方法:

    给出两个向量:E0=V1-V0 E1=V2-V0 对E0和E1进行叉乘操作N=E0XE1,如果N指向摄像机,则为正面,否则为背面。
阶段5,栅格化

三维模型经过了顶点变换已经投影到了二维平面上,而且被装配成图元了,但是屏幕是一个一个细细小小的像素格子组成的,对于一个图片,电脑是怎么知道应该把它搞到哪几个像素上去显示的呢?这就是光栅化。说白了就是,把想看见的图片,搞成像素能显示的。光栅化工作告诉了显卡,哪个格子是你这个图元应该画上的哪个不是。

传递过来的图元数据,在此将会被分解成更小的单元并对应帧缓冲区的各个像素,这些单元被称之为片元。一个片元可能包含窗口大小,深度,颜色,纹理坐标等属性。

片元的属性是图元上顶点数据等经过插值而确定的,比如颜色,深度等。

顶点属性的插值计算,在输入集合阶段用户指定的一系列的多边形,以三角形为例,每个三角形由三个顶点组成,每个顶点包含一系列的属性,如坐标,法线,纹理坐标等等,在经过顶点着色阶段,视口变换后,这个顶点在屏幕上都有对应的坐标。但为了显示该三角形,仅仅三个顶点显然是不够的,为了计算该三角形所覆盖的屏幕上每个像素的属性,要进行正确的插值计算,计算结果填充到片元中去。

阶段6,片元处理

这个阶段首先对片元上纹理,通过纹理坐标取得纹理内存中相对应的颜色。

再进行雾化,通过片元与当前视点位置的距离修改颜色。

最后颜色汇总,将纹理,主定义的颜色,雾化的颜色,次颜色光照阶段计算的颜色汇总一起。

这个阶段就是vertex fragment着色器编程中 fragment 片元转换函数的处理阶段,fragment 片元函数通过这个阶段的编程对片元进行修改。

阶段7,像素操作(Pixel Operation)

所有的片元的测试都在这里进行,包括:

    像素所有权测试 -> 裁剪测试 -> alpha测试 -> 模板测试 -> 深度测试 -> 混合 -> 抖动显示 -> 逻辑操作
阶段8,帧缓冲区(Frame Buffer)

执行帧缓冲的写入等操作,写入帧缓冲区,等待最后产生了显示出来的像素。

渲染管线的整个过程如下图所示:

render pipe

上图中 vertex框就是可编程部分的 vertex 函数,它可以修改顶点部分的数据来表现个性化的效果,fragment框也是一样,是 fragment 函数的调用点,修改通过这个fragment函数可以修改片元数据达到需要的效果。

Unity3D在渲染管线各阶段中所用到的功能,和我们前面所描述的阶段有很相似的地方,如下图所示:

render pipe

上图所要表达的功能和阶段,正是我们要在Shader章节中讲解和说明的部分。

参考资料

    1,渲染管线流程 作者:不详

    2,【图形学】渲染管道 作者:阵雷

感谢您的耐心阅读

Thanks for your reading

  • 版权申明

    本文为博主原创文章,未经允许不得转载:

    《Unity3D高级编程之进阶主程》第七章,Shader(三) - 渲染管道

    Copyright attention

    Please don't reprint without authorize.

  • 微信公众号