【UnityShader】【DissolveEffect】
最终效果
逻辑思路
为达到不规则溶解效果,使用噪声图采样,噪声图r值介于0-1,r值从小到大逐渐删除片元。
Shader面板
Shader "Custom/DissolveEffect"
{
Properties
{
_Diffuse("Diffuse", Color) = (1, 1, 1, 1)
_DissolveColor("Dissolve Color", Color) = (0, 0, 0, 0)
_DissolveEdgeColor("Dissolve Edge Color", Color) = (1, 1, 1, 1)
_MainTex("Base 2D", 2D) = "white"{}
_DissolveMap("DissolveMap", 2D) = "white"{}
_DissolveThreshold("DissolveThreshold", Range(0, 1)) = 0
_ColorFactor("ColorFactor", Range(0, 1)) = 0.7
_DissolveEdge("DissolveEdge", Range(0, 1)) = 0.8
}
CGINCLUDE
#include "Lighting.cginc"
uniform fixed4 _Diffuse;
uniform fixed4 _DissolveColor;
uniform fixed4 _DissolveEdgeColor;
uniform sampler2D _MainTex;
uniform float4 _MainTex_ST;
uniform sampler2D _DissolveMap;
uniform float _DissolveThreshold;
uniform float _ColorFactor;
uniform float _DissolveEdge;
struct v2f
{
float4 pos : SV_POSITION;
float3 worldNormal : TEXCOORD0;
float2 uv : TEXCOORD1;
};
v2f vert(appdata_base v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
o.worldNormal = mul(v.normal, (float3x3)unity_WorldToObject);
return o;
}
fixed4 frag(v2f i) : SV_Target
{
//噪声图采样
fixed4 dissolveValue = tex2D(_DissolveMap, i.uv);
//丢弃小于_DissolveThreshold的片元
clip(dissolveValue.r - _DissolveThreshold);
/*使用clip(x)替换 Discards the current pixel, if any component of x is less than zero.
if(dissolveValue.r < _DissolveThreshold)
{
discard;
}
*/
//光照计算
fixed3 worldNormal = normalize(i.worldNormal);
fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
fixed3 lambert = saturate(dot(worldNormal, worldLightDir));
fixed3 albedo = lambert * _Diffuse.xyz * _LightColor0.xyz + UNITY_LIGHTMODEL_AMBIENT.xyz;
fixed3 color = tex2D(_MainTex, i.uv).rgb * albedo;
//边缘颜色
float percentage = _DissolveThreshold / dissolveValue.r;
float lerpEdge = sign(percentage - _ColorFactor - _DissolveEdge);
fixed3 edgeColor = lerp(_DissolveEdgeColor.rgb, _DissolveColor.rgb, saturate(lerpEdge));
float lerpOut = sign(percentage - _ColorFactor);
fixed3 colorOut = lerp(color, edgeColor, saturate(lerpOut));
return fixed4(colorOut, 1);
}
ENDCG
SubShader
{
Tags{"RenderType" = "Opaque"}
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
ENDCG
}
}
FallBack "Diffuse"
}