Unity Shader Graph学习笔记

Shader 在 Unity 2018 之前都是需要写代码编辑的, Unity 2018 推出了 Shader Graph 插件, Shader Graph可以通过可视化界面拖拽就可以实现着色器的创建和编辑。 后续学习 Shader 的相关笔记都会放在这里,实现了基础的PBR Shader、水面效果、溶解(带边缘溶解)效果、积雪效果等,通过这些 Shader 的学习对 Shader Graph 中基本的 Node 有所了解。

URP工程相关

使用 Universal RP 插件可以将普通3D项目转化为URP的项目,在 Project Setting里面设置一下:

先在 Graphics 中设置渲染管线为UniversalRenderPipeline,然后在 Edit -> Render Pipeline -> Universal Render Pipeline -> Upgrade Project Materials to UniversalRP Materials ,其实就是更新材质球,就把项目中的 Materials 全部更新为URP渲染管线了。

渲染流程

MVP 矩阵

跟渲染有关的三个矩阵:MVP矩阵,MVP矩阵分别是模型矩阵、观察矩阵和投影矩阵。

  • 模型矩阵 M:模型空间到世界空间的转换矩阵
  • 观察矩阵 V:世界空间到相机空间的转换矩阵
  • 投影矩阵P:相机空间到裁剪空间,判断顶点是否在可见范围内,若在可见范围内即渲染出来,若不在范围内则将该顶点剔除掉

模型空间、世界空间、观察空间

模型空间(笛卡尔右手坐标系):每个模型有独立的坐标空间,移动或旋转的时候,模型空间以模型为原点;

世界空间:世界空间可以被用于描述绝对位置,通常把世界空间的原点放置在游戏空间的中心;

观察空间:以摄像机为原点的坐标空间;

完整的渲染流程分为下面三个阶段

应用程序阶段【CPU】:负责准备渲染所需要的信息,包含光照信息,顶点信息,材质信息,等等。

几何阶段【GPU】:负责对顶点进行计算,将顶点转换到齐次裁剪空间。

光栅化阶段【GPU】:负责将顶点和图元转换到像素,并且计算出最后的像素颜色信息,写入帧缓存。

其实这部份内容在学习OpenGL的时候已经学习过了,只不过对于Unity Editor用的是DX。其中的曲面细分着色器和几何着色器,用得其实比较少的,不是深入使用不用暂时考虑它们。

顶点数据信息来自CPU,所以Unity里对MeshRenderer和MeshFilter赋值,调整灯光方向和设置,还有烘焙之类的,就是为显卡渲染阶段做准备。在渲染开始之前都是由CPU计算和装配,这部分的耗时大部分的情况下远大于GPU的耗时,所以渲染性能优化实际上主要是在这个阶段的,而不是后面的几何阶段和光栅化阶段。

那主要的耗时在哪里呢?主要是CPU要收集需要渲染的对象,并且创建对应的渲染数据包,发送给GPU。所以渲染优化很多时候侧重点还是在于解决CPU 瓶颈问题。

Shader Demo

通过Shader Graph可以很方便的通过GUI的方式来完成Shader的编写,下面来看看实际效果:

纹理+白平衡控制的Shader

输入参数:主颜色、纹理、色温、色调,Texture2D输入需要接入纹理采样器Sample Texture2D,后面用乘法Node和白平衡的Node即可,所以主要是掌握输入参数以及白平衡、乘法节点的使用:

这样通过此Shader创造出来的Material就可以选择主颜色、纹理、色温、色调了。

PBR Shader

下面都属于是PBR Shader(物理Shader)的内容:

1、基础贴图,BaseColor,Texture2D的输入都需要使用sample Texture2D 采样器;

2、法线贴图:Normal属性 表面细节(如凹凸、凹槽和划痕)添加到模型;

3、金属度贴图:Metallic属性,金属越高,漫反射越低;

4、光滑度:Smoothness属性,float类型;

5、自发光贴图:Emission 属性:材质发光属性用于控制材质表面发光的颜色和强度。

6、环境光屏蔽贴图:Ambient Occlusion属性;

SubShader 操作

多个Node可以重组成一个新的Shader,即SubShader操作

SubShader需要注意的点:

1、输入与输出参数需要标注清楚,一看就知道是什么意思;

2、内部过于复杂的时候需要Group Selection操作注释成一个Node组,并说明功能;

边缘光 Shader

1、其实主要还是基础贴图、法线贴图、金属度贴图;

2、自发光的菲尼尔效果:发光强度、发光颜色,形成的颜色通过Add函数与自发光贴图形成综合效果;

边缘溶解效果 Shader

1、片元着色器勾选Alpha Clip开启Alpha通道,设置Alpha通道的阈值;

2、溶解效果取样方式可以使用噪声图Simple Noise,噪声图输出附加到Alpha通道上;

3、此时改变Alpha通道的阈值,即可实现溶解效果;

溶解边缘效果制作方法

噪声图是类似于高度图一样存在一个中心点,先把整体高度提高,再按照原来的高度降低曲线进行裁切就可以得到一个比原来要慢一些的边缘;

其实溶解边缘效果是基于自发光做的,首先根据噪声图的输出+Alpha通道的值+边缘宽度通过Step函数得到溶解边缘,再加上颜色,输入到Fragment的自发光贴图即可得到溶解边缘的效果

这里说下step函数/Node的作用:通过step函数可以替代if-else的关系,使用场景就是需要对不同渲染区域进行判定,比如通过透明度判断是否是处于边缘等场景;

积雪效果 Shader

积雪效果的实现原理:

1、计算标定垂直方向与表面法线方向的夹角,即两个向量的点积运算,如果超过某个阈值就进行颜色混合;

2、Fresnel Effect 菲涅尔效果,边缘柔化;

3、Normalize 节点做归一化处理;

4、Dot Product 这个就是实现积雪效果最重要的节点:点积计算节点;

5、ReMap节点-1~1转化为0~1

6、OneMinus 1-原值节点;

7、Step:通过step函数可以替代if-else的关系,使用场景就是需要对不同渲染区域进行判定,比如通过透明度判断是否是处于边缘等场景;

水面效果 Shader

首先这一部分学习的Node主要是:

1、Time 时间函数,比如水波纹和水面起伏的时候都要Time作为驱动;

2、Split分割x y z w,Combine组合x y z w,需要对其中某一个单独处理时比较有用;

3、Add、Subtract、Multiply 加减乘函数,纹理叠加就是使用了Add函数;

4、Position Node即表示顶点着色器的Position属性,同时Normal、Tangent也是同样的表示;

5、Simple Noise 即噪声图,边缘溶解效果即是使用了噪声图;

6、Gradient Noise 即梯度噪声,用来产生单个方向的噪声,比如水面起伏就需要对Y轴坐标用到此噪声;

7、Tiling And Offset 用于UV偏移的场景;

8、Lerp函数用于线性插值,其实就是A、B混合,然后用T表示其混合比例,比如颜色混合的时候指定比例;

9、Scene Depth场景深度,如果选择了Eye模式,则表示视空间深度;

10、先用一个scene depth节点(采样模型为eye),减去Screen Position节点的A通道值(mode为raw),如果结果为0,表示物体和其他物体相交的在边缘,否则不在边缘

水里扭曲特效实现方式

Screen Position相当于已经渲染完毕的顶点,拿到这个进行处理后再交给顶点着色器;

全部Shader Demo链接: https://plastichub.unity.cn/zouchanglin/Shader-Demo