前言
- 最近高精项目是真的忙到吃💩,学习时间都压榨得所剩无几了。
- 之前虽然用Unity内置的Shader写过一些简单的shader,但涉及到别人的项目or教程or虚幻,用连连看的也不在少数,所以还是找时间学起了Shader Graph
- 本篇实现的是一个简单的消融特效,基本都是完全参照油管BracKeys的
效果预览
- 教程里使用的是猴子模型
原教程的注意点
- 油管上教程原本是用PBRShader的,但那是Unity刚推出2018版本才存在的东西,本质上是光照模型;如果你要自己新建一个这样的Shader,在18之后的版本换成Lit Shader Graph即可
- 如果你使用和作者一样的Unity版本,会发现导入工程后猴子的模型无法显示,这可能是因为就版本的Unity对Blender的模型转换需要依赖更远古的Blender版本;如果你要解决这个问题,要么下远古版本的Blender,要么下个新的Blender,然后用20的Unity版本打开工程(我就是)
- 作者原工程使用的Settings目录在20版本的Unity上是有坑的(19可能也有?):
.setting
后缀的文件导到新版本上是会直接什么都看不见的,但PostProcessProfile却不会有任何报错;- 神奇的事情就在于Package Manager补上PostProcess的插件后没有任何报错,却也没有任何效果,经过一番查阅才发现PostProcess已经不兼容新版Unity的URP渲染管线了,可即便如此,插件主页几乎没有任何这方面的提示。。
- 如果PostProcess不生效的情况下,你会发现消融边缘的光一点都不亮,就像下面这样:
- 而如果PostProcess正常进行后处理的情况下,你会发现消融的边缘光非常亮,并且背景色也有变化:
- 这个问题本质上就是三方开发的PostProcess已经被URP内置替代了,具体操作步骤可见B站的一个教程
- 新版本上把原本的一些设置项打得更散了,但本质上还是一个东西:
Surf Shader实现
-
其实之前也看过Surf Shader的实现方式,但在这里就不多说了,直接贴个效果:
-
当时的代码:
Shader "Custom/Dissolve"
{
Properties
{
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_Normal("Normal", 2D) = "bump" {}
_NormalScale("NormalScale", Range(0,5)) = 1
_Glossiness ("Smoothness", Range(0,1)) = 0.5
_Metallic ("Metallic", Range(0,1)) = 0.0
_DisolveTex("DisolveTex",2D) = "white"{}
_Threshold("Threshold",Range(0,1)) = 0
// 消融得边缘长度
_EdgeLength("EdgeLength", Range(0,0.2)) = 0.1
// 烧着贴图
_BurnTex("BurnTex", 2D) = "white"{}
// 颜色强度
_BurnInstensity("BurnInstensity", Range(0,5)) = 1
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
// Physically based Standard lighting model, and enable shadows on all light types
#pragma surface surf Standard fullforwardshadows
// Use shader model 3.0 target, to get nicer looking lighting
#pragma target 3.0
sampler2D _MainTex;
sampler2D _Normal;
half _NormalScale;
sampler2D _DisolveTex;
half _Threshold;
sampler2D _BurnTex;
half _EdgeLength;
half _BurnInstensity;
struct Input
{
float2 uv_MainTex;
float2 uv_Normal;
float2 uv_DisolveTex;
};
half _Glossiness;
half _Metallic;
fixed4 _Color;
// Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
// See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
// #pragma instancing_options assumeuniformscaling
UNITY_INSTANCING_BUFFER_START(Props)
// put more per-instance properties here
UNITY_INSTANCING_BUFFER_END(Props)
void surf (Input IN, inout SurfaceOutputStandard o)
{
// Albedo comes from a texture tinted by color
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
o.Normal = UnpackScaleNormal(tex2D(_Normal, IN.uv_Normal),_NormalScale);
o.Albedo = c.rgb;
float cutout = tex2D(_DisolveTex, IN.uv_DisolveTex).r;
clip(cutout - _Threshold);
float temp = saturate((cutout - _Threshold) / _EdgeLength);
fixed4 edgeColor = tex2D(_BurnTex,float2(temp,temp));
fixed4 finalColor = _BurnInstensity * lerp(edgeColor, fixed4(0,0,0,0), temp);
o.Emission = finalColor.rgb;
// Metallic and smoothness come from slider variables
o.Metallic = _Metallic;
o.Smoothness = _Glossiness;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
- 但上面的代码其实还有各种问题,比如把模型换成一个正方形,侧面的烧着贴图就没法显示等,具体的就不赘述了。
噪音贴图
- 噪音贴图的作用是通过在不规则的贴图上进行UV采样,从而使得每个片元的透明度都不一样,从而让物体不同的位置的A通道都不规则,我们可以通过更改
Surface
看到这个效果:
当然,更改Surface只是为了方便理解,实际还是使用Opaque使物体不透明才能更好看到效果
- 看完效果后,我们变回
Opaque
,之后通过控制Alpha Clip Threshold
就可以得到最初步的消融效果: - 我们还可以添加时间轮询的节点来轮询播放以便于我们调试:
添加消融边缘光
- 为了方便调试,我们首先是要先关闭
噪音纹理->Alpha
的输入: - 然后增加
Step
节点,Step
的作用就是“当In值>=Edge时,才会输出1”,可以把它当作一个开关,当In全部>=Edge时,物体就会完全变为白色: - 这里的白色后续其实就是替换成消融边缘光的颜色;不过在此之前,我们尝试把噪声纹理的输出重新链接的Alpha,就会发现我们又回到起点了,跟上面搞完噪音贴图的时候没啥区别:
- 但实际上是有区别的,目前看起来没区别主要是因为变白的部分刚好也被剔除掉了而已:
- 而我们要实现边缘光,其实就相当于把白色那层再“外拓”下:
- 而目前无论是变白部分还是剔除部分,都来自与噪声纹理的输出,我们无论是减小噪音纹理输出,还是增大Step的In等都可以实现类似的效果,比如减少噪音纹理输出:
- 又比如增大Step的In:
- 最后,我们把颜色加上去:
最后
- 把Shader套到猴子模型上,基本大功告成:
- 最后为了方便shader参数从外部调试,可以将部分再shader里写死的入参参数化:
- 对了,不要忘了我们目前是还没勾上双面渲染的,勾上后如下图所示: