Unity Shader 消融效果

游戏中有一种很常见的效果:角色死亡或者场景烧毁会逐渐消融

消融效果

要实现消融效果,最重要的就是让某些像素显示,某些像素消失

为了实现这种效果

我们就需要标记哪些像素要显示,哪些像素要消失,可以使用噪声图来给每一个像素做标记

由于噪声图的随机性,使得像素的显示和消失显得非常不规则,这也就满足了消融效果的需求

而在 Shader 中 "扣掉" 一个像素,可以使用 clip 函数

在片段着色器中调用 clip(x) 即可丢弃这个像素:其中x为数值,当x小于0.0,则该像素就会被丢弃

Shader

Shader "Effect/Melting"
{
    Properties
    {
        _Color("Color",Color) = (0.5,0.5,0.5,1.0)
        _MainTex("Texture", 2D) = "white" {}
        _EdgeColor("EdgeColor",Color) = (1,0,0,1)
        _Height("Height",float) = 0
    }
        SubShader
        {
            Tags { "RenderType" = "Opaque" }
            LOD 100

            Pass
            {
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                // make fog work
                #pragma multi_compile_fog

                #include "UnityCG.cginc"

                struct appdata
                {
                    float4 vertex : POSITION;
                    float2 uv : TEXCOORD0;
                };

                struct v2f
                {
                    float2 uv : TEXCOORD0;
                    UNITY_FOG_COORDS(1)
                    float3 wPos:TEXCOORD2;
                    float4 vertex : SV_POSITION;
                };

                uniform fixed4 _Color;
                uniform sampler2D _MainTex;
                uniform float4 _MainTex_ST;
                uniform float _Height;
                uniform fixed4 _EdgeColor;

                float3 hash(float3 p)
                {
                    p = float3(dot(p, float3(127.1, 311.7,4560.0)),dot(p, float3(269.5, 183.3,143.15)), dot(p, float3(567.5,613.3,430.4)));
                    return  2.0 * frac(sin(p) * 43758.5453123) - 1.0;
                }

                float perlin(float3 p)
                {
                    float3 i = floor(p);
                    float3 f = p - i;
                    float3 w = f * f * (3.0 - 2.0 * f);
                    float f0 = lerp(lerp(dot(hash(i + float3(0.0, 0.0,0.0)), f - float3(0.0, 0.0,0.0)),dot(hash(i + float3(1.0, 0.0,0.0)), f - float3(1.0, 0.0,0.0)), w.x),lerp(dot(hash(i + float3(0.0, 1.0,0.0)), f - float3(0.0, 1.0,0.0)),dot(hash(i + float3(1.0, 1.0,0.0)), f - float3(1.0, 1.0,0.0)), w.x),w.y);
                    float f1 = lerp(lerp(dot(hash(i + float3(0.0, 0.0,1.0)), f - float3(0.0, 0.0,1.0)),dot(hash(i + float3(1.0, 0.0,1.0)), f - float3(1.0, 0.0,1.0)), w.x),lerp(dot(hash(i + float3(0.0, 1.0,1.0)), f - float3(0.0, 1.0,1.0)),dot(hash(i + float3(1.0, 1.0,1.0)), f - float3(1.0, 1.0,1.0)), w.x), w.y);
                    return lerp(f0,f1,w.z);
                }

                v2f vert(appdata v)
                {
                    v2f o;
                    o.vertex = UnityObjectToClipPos(v.vertex);
                    o.wPos = mul(unity_ObjectToWorld, v.vertex).xyz;
                    o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                    UNITY_TRANSFER_FOG(o,o.vertex);
                    return o;
                }

                fixed4 frag(v2f i) : SV_Target
                {
                    fixed4 col = tex2D(_MainTex,i.uv) * _Color;
                    float p = perlin(i.wPos * 30) - (i.wPos.y - _Height);
                    float e0 = (1 - smoothstep(0, 0.3, p));
                    float e1 = (1 - smoothstep(0, 0.1, p));
                    col = lerp(col,col * _EdgeColor, e0);
                    col = lerp(col, col * _EdgeColor * 2, e1);
                    clip(p);
                    UNITY_APPLY_FOG(i.fogCoord, col);
                    return col;
                }
            ENDCG
            }
        }
}

该 Shader 效果为定向消融效果,也就是朝一定的方向消融的效果

其中

EdgeColor 为消融边缘颜色

Height 为消融效果高度(自上而下消融)

 

 

 

 

 

👉 | Shader 消融效果原文 | 👈

👉 |  以上内容仅为学习参考、学习笔记使用  | 👈

posted @ 2021-12-25 15:24  Mr.Cat~  阅读(659)  评论(0编辑  收藏  举报