Unity Shader 噪声消融特效 - 剑灵死亡特效

Posted Sooda

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity Shader 噪声消融特效 - 剑灵死亡特效相关的知识,希望对你有一定的参考价值。

噪声是个很神奇的东西,以前接触的时候就是在自动生成地图上,因为噪声本来就近自然所以,很多特效也是基于噪声的。

前几篇文章介绍了纹理和光照,这回其实也就是用这么多。就是光照加一个噪声的法线纹理。

你可能就玩过一款游戏,剑灵,游戏中怪物死亡的时候会有一种消融的效果。让我们来看一看是怎么实现的。

下面三个图片分别是BurnAmount = 0、BurnAmount = 0.25、BurnAmount = 0.5时的效果。

  

这里我们用两个Pass来处理这个效果

  • 第一个Pass:渲染模型的正常颜色和消融的混合颜色
  • 第二个Pass:处理消融的阴影,如不特殊处理则影子不会有消融效果。

下面给出代码(有必要的注释)

  1 Shader "Shader/Shader"
  2 {
  3     Properties
  4     {
  5         _MainTex ("Main Tex", 2D) = "white" {}
  6         // 法线贴图
  7         _BumpMap ("Bump Map", 2D) = "bump" {}
  8         // 噪声贴图
  9         _BurnMap ("Burn Map", 2D) = "white" {}
 10         // 控制消融程度
 11         _BurnAmount ("Burn Amount", Range(0, 1)) = 0
 12         // 控制模型烧焦效果的线宽
 13         _LineWidth ("Burn Line Width", Range(0.0, 0.2)) = 0.1
 14         // 烧焦边缘的颜色
 15         _BurnColor ("Burn Color", Color) = (1, 0, 0, 1)
 16     }
 17     SubShader
 18     {
 19         Tags { "RenderType"="Opaque" "Queue"="Geometry" }
 20 
 21         Pass
 22         {
 23             Tags { "LightMode"="ForwardBase" }
 24             
 25             // 所有面都不被剔除,因为消融的时候应该可以看到物体的内部。
 26             Cull Off
 27 
 28             CGPROGRAM
 29             #pragma vertex vert
 30             #pragma fragment frag
 31             // 为得到正确的光照设置的编译指令
 32             #pragma multi_compile_fwdbase
 33 
 34             #include "Lighting.cginc"
 35             #include "AutoLight.cginc"
 36 
 37             sampler2D _MainTex;
 38             sampler2D _BumpMap;
 39             sampler2D _BurnMap;
 40             float4 _MainTex_ST;
 41             float4 _BumpMap_ST;
 42             float4 _BurnMap_ST;
 43             fixed _BurnAmount;
 44             fixed _LineWidth;
 45             fixed4 _BurnColor;
 46 
 47             struct a2v
 48             {
 49                 float4 vertex : POSITION;
 50                 float3 normal : NORMAL;
 51                 float2 texcoord : TEXCOORD0;
 52                 fixed4 tangent : TANGENT;
 53             };
 54 
 55             struct v2f
 56             {
 57                 float4 pos : SV_POSITION;
 58                 float2 uvMainTex : TEXCOORD0;
 59                 float2 uvBumpMap : TEXCOORD1;
 60                 float2 uvBurnMap : TEXCOORD2;
 61                 // 切线视图的光照方向
 62                 float3 lightDir : TEXCOORD3;
 63                 float3 worldPos : TEXCOORD4;
 64                 // Shader 阴影宏:用于对阴影纹理采样的坐标
 65                 // 参数:一个可用的差值寄存器的索引值,用世界的顶点坐标。即5(从0开始)
 66                 SHADOW_COORDS(5)
 67             };
 68 
 69             v2f vert(a2v v)
 70             {
 71                 v2f o;
 72 
 73                 o.pos = UnityObjectToClipPos(v.vertex);
 74 
 75                 o.uvMainTex = TRANSFORM_TEX(v.texcoord, _MainTex);
 76                 o.uvBumpMap = TRANSFORM_TEX(v.texcoord, _BumpMap);
 77                 o.uvBurnMap = TRANSFORM_TEX(v.texcoord, _BurnMap);
 78 
 79                 TANGENT_SPACE_ROTATION;
 80                 o.lightDir = mul(rotation, ObjSpaceLightDir(v.vertex));
 81                 o.worldPos = UnityObjectToWorldDir(v.vertex);
 82 
 83                 // 阴影宏:在顶点着色器中计算上一步中声明的阴影纹理坐标
 84                 TRANSFER_SHADOW(o);
 85 
 86                 return o;
 87             }
 88 
 89             fixed4 frag(v2f i) : SV_Target
 90             {
 91                 // 取噪声贴图进行采样
 92                 fixed3 burn = tex2D(_BurnMap, i.uvBurnMap);
 93                 // 用于剔除像素点,if (采样结果-消融程度阀值 > 0) 存留 or 丢弃
 94                 clip(burn.r - _BurnAmount);
 95 
 96                 fixed3 albedo = tex2D(_MainTex, i.uvMainTex).rgb;
 97 
 98                 fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
 99 
100                 fixed3 tangentLightDir = normalize(i.lightDir);
101                 fixed3 tangentNormal = UnpackNormal(tex2D(_BumpMap, i.uvBumpMap));
102                 fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(tangentLightDir, tangentNormal));
103 
104                 // 阴影宏:计算阴影值,最后与漫反射的颜色叠加
105                 UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);
106 
107                 // smoothsetp(e1,e2,x)平滑过度函数
108                 // 原理:if (x < e1) 结果 = 0
109                 // if (x > e2) 结果 = 1
110                 // if (e1 < x < e2) 结果 = 3 * pow(x, 2) - 2 * pow(x, 3)
111                 // t = 0时,该像素为正常的模型颜色
112                 // t = 1时,该像素位于消融的边界处
113                 fixed t = 1 - smoothstep(0.0, _LineWidth, burn.r - _BurnAmount);
114 
115                 // 最终颜色,在消融和正常中差值,系数为t
116                 fixed3 finalColor = lerp(ambient + diffuse * atten, _BurnColor, t);
117 
118                 return fixed4(finalColor, 1);
119             }
120             ENDCG
121         }
122 
123         // 此Pass是处理阴影的,我们需要按照正常的Pass的处理来剔除片元或进行顶点动画。以便阴影可以和物体正常渲染的结果相匹配。
124         Pass
125         {
126             // 光照模式定义为阴影
127             Tags { "LightMode"="ShadowCaster" }
128 
129             CGPROGRAM
130             #pragma vertex vert
131             #pragma fragment frag
132             // 处理阴影的编译指令
133             #pragma multi_compile_shadowcaster
134             
135             #include "UnityCG.cginc"
136 
137             fixed _BurnAmount;
138             sampler2D _BurnMap;
139             float4 _BurnMap_ST;
140 
141             struct a2v
142             {
143                 float4 vertex : POSITION;
144                 float2 texcoord : TEXCOORD0;
145                 float3 normal : NORMAL;
146                 float4 tangent: TANGENT;
147             };
148 
149             struct v2f
150             {
151                 // 定义阴影投射需要定义的变量
152                 V2F_SHADOW_CASTER;
153                 float2 uvBurnMap : TEXCOORD0;
154             };
155             
156             v2f vert (a2v v)
157             {
158                 v2f o;
159 
160                 // 填充V2F_SHADOW_CASTER定义的变量
161                 TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
162                 o.uvBurnMap = TRANSFORM_TEX(v.texcoord, _BurnMap);
163 
164                 return o;
165             }
166             
167             fixed4 frag (v2f i) : SV_Target
168             {
169                 fixed3 burn = tex2D(_BurnMap, i.uvBurnMap);
170                 
171                 clip(burn - _BurnAmount);
172 
173                 // 让Unity完成阴影投射
174                 SHADOW_CASTER_FRAGMENT(i)
175             }
176             ENDCG
177         }
178     }
179 }

本文引自Unity Shader 入门精要

以上是关于Unity Shader 噪声消融特效 - 剑灵死亡特效的主要内容,如果未能解决你的问题,请参考以下文章

游戏开发实战教你在Unity中实现模型消融化为灰烬飘散的效果(ShaderGraph | 消融 | 粒子系统 | 特效)

游戏开发实战教你在Unity中实现模型消融化为灰烬飘散的效果(ShaderGraph | 消融 | 粒子系统 | 特效)

游戏开发实战教你在Unity中实现模型消融化为灰烬飘散的效果(ShaderGraph | 消融 | 粒子系统 | 特效)

小功能⭐️Unity2018 Shader Graph——全息影像物体消融

小功能⭐️Unity2018 Shader Graph——全息影像物体消融

小功能⭐️Unity2018 Shader Graph——全息影像物体消融