最近一直在学习Unity的shader,从一开始的UnityShader入门精要,到现在ShaderGraph可以说是对的Shader认识也在加深。想彻底理解Shader不是一件容易的事。我们必须对计算机图形学有一定的知识储备,并充分掌握线性代数的矩阵操作。所以我们刚刚开始入门Shader只有这样,我们才会非常困难Unity的Shader更重要的是要掌握正确的学习方法。
第一步也是最困难的部分,因为渲染管道的知识往往与计算机图形学有关,如果我们直接接触渲染管道,我们往往看起来很困惑。因此,我们建议从计算机图形学开始,同时学习计算机图形学来了解渲染装配线。掌握渲染装配线,我们可以编写Shader更得心应手。
当我们对渲染流水线有了初步的了解时,我们就可以开始了解具体情况Shader编写过程。
Unity2018年版本后,推出了可编程渲染管道工具ShaderGraph,着色器的创建和编辑可以通过可视化界面拖动来实现
官方介绍:
Shader Graph 使您能够直观地构建着色器。您不需要编写代码,而是在图形框架中创建和连接节点。Shader Graph 为不熟悉着色器创建的用户提供反映您变化的即时反馈非常简单。
Shader Graph 渲染管道只与可编写脚本相匹配 (SRP) 兼容性,即高清度渲染管道 (HDRP) 通用渲染管道 (URP)。这两个 SRP 在 Unity 2018.1 及更高版本中可用。传统的内置渲染管线不支持 Shader Graph。
有渲染流水线Shader我们可以在写作的基础上Shader Graph如鱼得水Shader创作了。
首先我们来了解一下Shader Graph基本操作。
1、创建Shader Graph的shader。
右键直接创建项目窗口Shader Graph
2.基本操作:
属性创建
节点的设置
Shader的属性设置
Target Setings :渲染管道代表支持。
其他的Shader设置相当于管道中标准材料的设置。
3.现在我们将以实例的形式对待它ShaderGraph进行学习。
通过观察材料的性能,我们发现整个材料呈现出流动的特性,材料的中部呈现出透明的效果。因此,我们可以控制半透明条状图Alpha通道并且让其上下方向进行流动,这样我们就能实现全息Shader的效果。
因为使用了透明效果,所以我们必须正确使用Shader进行设置。
将其Surface Type修改为Transparent。
首先,我们在这里引入我们需要使用的纹理Sample Texture 2D承载纹理。
我们用这种纹理来控制它Alpha因此,连接到通道Alpha通道上。为了达到他的流动效果,我们必须让这张照片移动。所以我们必须处理这张照片UV。
Tiling And Offset纹理可以控制UV,只要实时改变纹理的偏移,纹理就能从上到下流动。
在ShaderGraph常有中动效Time实现节点时,他乘以速度变量,然后输出到Offset这样就能达到纹理的流动效果。
将Screen Position输出到Tiling And Offset 的UV此时,整个屏幕图像是一个接口UV,因此,纹理可以根据屏幕空间进行UV从上到下统一流动。
在这种着色器案例中,我们应用了菲涅尔、法线混合、深度贴图、顶点变化等效果。
首先我们进行基础的颜色与法线配置。
我们用菲涅尔来分层颜色。
菲涅尔:通过视角的方向和订点线的方向计算。当视角处理面片时,返回0平行于面片时,返回1,用于从不同的角度观察不同的颜色
输出菲涅尔Lerp用于控制两种不同颜色的显示。
然后我们实现了法线的效果。
我们使用世界空间UV当我们复制多个法线时,控制法线的填充Plane他也可以无缝衔接。
这样,我们就完成了整个海面的基本纹理,海面已经有了波纹的流动效果。
下面我们需要实现的是海浪起伏的效果。
波浪的起伏是通过定点的转换来实现的。我们需要定期设置顶点的起伏。我们可以在这里使用它SampleNoise,不同的是,我们需要正确Sample的UV设置已经达到了规律起伏的效果。
我们需要让SampleNoise呈现条状分布效果,然后我们与顶点PositionY方向相乘,
这样顶点就可以有规律的起伏。
首先我们将postionY分量单独提取用于后期计算。下一步,我们将Position的XZ提取重量充当SampleNoise的UV,为了呈现条状效果,我们需要Position的XZ分量分离乘以不同的系数。然后输出到UV最后,为了实现现它Noise我们的偏移效果是Postion最后从结果中加入常量,使其产生偏移的移动效果。
Position节点充当UV。我们可能会想,为什么模型的每个顶点都充当了UV原因是顶点的位置不是直接充当的UV的。我的理解是:Shader模型的每个顶点位置都会相减,每个顶点的位置都会相减,周围的区域会充满纹理UV,所以这就是为什么当我们旋转的时候Plane时,noise填充后被挤压。
水平放置
垂直放置
平面旋转会导致UV这种差异归因于我们采用异Position的XZ分量充当UV,当Plane旋转后,每个顶点的X或Z会处于同一值,相减后等于零,UV当某个值为零时,会导致平铺压缩。
创建出Noise后,我们将Noise与顶点的Y分量相乘,最终实现顶点变换。
同时,我们的门也应该处理颜色。我们使海浪高于亮色,海量低谷为暗色。我只需要Noise与BaseColor可以相乘,但为了避免Noise对于零时引起的全黑色,我们对Noise限制输出。
我们限制为0.4-1.
最后,我们实现了海浪的高光效果。
最后,泡沫和水面下的半透明效果要通过深度贴图来实现。
深度地图:我们需要知道Unity屏蔽的实现是通过深度来实现的。一般来说,顶点距离相机的距离。对于统一视角方向的顶点,深度小的会对深度大的有屏蔽作用。
实现深度透明效果可以概括为一个常规,即我们将Screen PositonW重量加上一定的深度偏移,然后使用Screen Depth 减去顶点的深度,然后通过One Minus转正,再用Clamp限制0-1,最后乘以所需的颜色或效果。
深度处理:
泡沫效果: 泡沫效果与深色相同,但我们为它们设置不同的深度偏移。
这样我们就实现了深度透明效果,我们可以通过Depth Offset的值来控制水面透明的程度。
最终ShaderGraph: