【Shader】热扭曲实现刀光特效

第一种方式:

// 用于刀光的空气扭曲特效
Shader "Custom/SimpleHeatDistortion" {

    Properties {
        _NoiseTex ("Noise Texture (RG)", 2D) = "white" {}
        _MainTex ("Alpha (A)", 2D) = "white" {}
        _HeatTime  ("Heat Time", range (0,1.5)) = 1
        _HeatForce  ("Heat Force", range (0,1)) = 1
    }

    Category {
        Tags { "Queue"="Transparent+1" "RenderType"="Transparent" }
        Blend SrcAlpha OneMinusSrcAlpha
        AlphaTest Greater .01
        Cull Off Lighting Off ZWrite Off

        SubShader {
            GrabPass { Name "BASE" Tags { "LightMode" = "Always" } }

            Pass {
                Name "BASE"
                Tags { "LightMode" = "Always" }

                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #pragma fragmentoption ARB_precision_hint_fastest
                #include "UnityCG.cginc"

                struct appdata_t {
                    float4 vertex : POSITION;
                    fixed4 color : COLOR;
                    float2 texcoord: TEXCOORD0;
                };

                struct v2f {
                    float4 vertex : POSITION;
                    float4 uvgrab : TEXCOORD0;
                    float2 uvmain : TEXCOORD1;
                };

                float _HeatForce;
                float _HeatTime;
                float4 _MainTex_ST;
                float4 _NoiseTex_ST;
                sampler2D _NoiseTex;
                sampler2D _MainTex;

                v2f vert (appdata_t v)
                {
                    v2f o;
                    o.vertex = UnityObjectToClipPos(v.vertex);
                    #if UNITY_UV_STARTS_AT_TOP
                        float scale = -1.0;
                    #else
                        float scale = 1.0;
                    #endif
                    o.uvgrab.xy = (float2(o.vertex.x, o.vertex.y*scale) + o.vertex.w) * 0.5;
                    o.uvgrab.zw = o.vertex.zw;
                    o.uvmain = TRANSFORM_TEX( v.texcoord, _MainTex );
                    return o;
                }

                sampler2D _GrabTexture;

                half4 frag( v2f i ) : COLOR
                {
                    half4 offsetColor1 = tex2D(_NoiseTex, i.uvmain + _Time.xz*_HeatTime);
                    half4 offsetColor2 = tex2D(_NoiseTex, i.uvmain - _Time.yx*_HeatTime);
                    i.uvgrab.x += ((offsetColor1.r + offsetColor2.r) - 1) * _HeatForce;
                    i.uvgrab.y += ((offsetColor1.g + offsetColor2.g) - 1) * _HeatForce;

                    half4 col = tex2Dproj( _GrabTexture, UNITY_PROJ_COORD(i.uvgrab));
                    col.a = 1.0f;
                    half4 tint = tex2D( _MainTex, i.uvmain);

                    return col*tint;
                }

                ENDCG

            }// End Pass

        }// End SubShader

        // Fallback for older cards and Unity non-Pro
        SubShader {
            Blend DstColor Zero
            Pass {
                Name "BASE"
                SetTexture [_MainTex] { combine texture }
            }
        }
    }
}

第二种方式:

头文件

// 来自博客:http://console-dev.de/
#ifndef GRABPASSDISTORTION_GCINC
#define GRABPASSDISTORTION_GCINC

// _MainTex is the distortion texture and should use "Bypass sRGB Sampling" import setting.
sampler2D _MainTex;

// _MainTex tiling and offset properties.
float4 _MainTex_ST;

// _GrabTexture contains the contents of the screen where the object is about to be drawn.
sampler2D _GrabTexture;

// x=horizontal intensity, y=vertical intensity
// z=horizontal scrolling speed, w=vertical scrolling speed
float4 _IntensityAndScrolling;

// x=near distance at which distortions have full intensity
// y=far distance at which distortions have zero intensity
half2 _DistanceFade;

#if ENABLE_TINT
// Tinting the distorted area
half3 _Tint;
#endif

struct appdata_t
{
    float4 vertex  : POSITION;
    half2 texcoord : TEXCOORD0;
    fixed4 color   : COLOR;
};

struct v2f
{
    float4 vertex  : SV_POSITION;
    fixed4 color   : COLOR;     // a=distortion intensity multiplier
    half4 texcoord : TEXCOORD0; // xy=distort uv, zw=mask uv
    half4 screenuv : TEXCOORD1; // xy=screenuv, z=distance dependend intensity, w=depth
};

// ----------------------------------------------------------------------------
// Helper Functions
// ----------------------------------------------------------------------------
inline float2 Repeat(float2 t, float2 length)
{
    return t - floor(t / length) * length;
}

inline float2 PingPong(float2 t, float2 length)
{
    t = Repeat(t, length * 2);
    return length - abs(t - length);
}

// ----------------------------------------------------------------------------
// Vertex Shader
// ----------------------------------------------------------------------------
v2f vert (appdata_t v)
{
    v2f o = (v2f)0;
    o.vertex = UnityObjectToClipPos(v.vertex);
    o.color  = v.color;

    // texcoord.xy stores the distortion texture coordinates.
    o.texcoord.xy = TRANSFORM_TEX(v.texcoord, _MainTex); // Apply texture tiling and offset.
    o.texcoord.xy += _Time.gg * _IntensityAndScrolling.zw; // Apply texture scrolling.

    // texcoord.zw stores the distortion mask texture coordinates.
    // We don't want to scroll the mask, so we just use the original texture coords.
    o.texcoord.zw = v.texcoord;

    half4 screenpos = ComputeGrabScreenPos(o.vertex);
    o.screenuv.xy = screenpos.xy / screenpos.w;

    // Calculate distance dependend intensity.
    // Blend intensity linearily between near to far params.
    half depth = length(mul(UNITY_MATRIX_MV, v.vertex));
    o.screenuv.z = saturate((_DistanceFade.y - depth) / (_DistanceFade.y - _DistanceFade.x));
    o.screenuv.w = depth;

    return o;
}

// ----------------------------------------------------------------------------
// Pixel Shader
// ----------------------------------------------------------------------------
fixed4 frag (v2f i) : COLOR
{
    half2 distort = tex2D(_MainTex, i.texcoord.xy).xy;

    // distort*2-1 transforms range from 0..1 to -1..1.
    // negative values move to the left, positive to the right.
    half2 offset = (distort.xy * 2 - 1) * _IntensityAndScrolling.xy * i.screenuv.z * i.color.a;

#if ENABLE_TINT
    half3 tint = _Tint;
#endif

#if MASK
    // _MainTex stores in the blue channel the mask.
    // The mask intensity represents how strong the distortion should be for this pixel.
    // black=no distortion, white=full distortion
    half  mask = tex2D(_MainTex, i.texcoord.zw).b;              
    offset *= mask;

    #if ENABLE_TINT
    // Push tint towards white where distortions are not applied.
    // This makes the tint fade out using the mask.
    tint = lerp(tint, half3(0.5,0.5,0.5), 1-mask);
    #endif
#endif                          

#if ENABLE_CLIP             
    // Clip pixel if offset is really small. This makes masked particle
    // distortions blend together slightly better.
    clip(dot(offset,1) - 0.0001);                   
#endif                  

    // get screen space position of current pixel
    half2 uv = i.screenuv.xy + offset;

#if MIRROR_EDGE
    // Mirror uv's when it goes out of the screen.
    // This avoids streched seams at screen borders by introducing
    // these kind of mirroring artifacts. It looks less disturbing than the border seams though.
    uv = PingPong(uv, 1);
#endif

    half4 color = tex2D(_GrabTexture, uv);
#if ENABLE_TINT
    color.rgb *= tint * 2;
#endif
    UNITY_OPAQUE_ALPHA(color.a);

#if DEBUGUV
    color.rg = uv;
    color.b = 0;
#endif

#if DEBUGDISTANCEFADE
    color.rgb = lerp(half3(1,0,0), half3(0,1,0), i.screenuv.z);
#endif

    //color.rgb = float3(fade,fade,fade)*15;
    return color;
}

#endif // GRABPASSDISTORTION_GCINC

Shader 文件

// 热扭曲 —— GrabPass 实现方式
Shader "Custom/GrabPass Distortion (Layer)"
{
    Properties
    {
        _MainTex ("Texture (R,G=X,Y Distortion; B=Mask; A=Unused)", 2D) = "white" {}
        _Tint ("Tint (RGB)", Color) = (0.5,0.5,0.5,1)
        _IntensityAndScrolling ("Intensity (XY); Scrolling (ZW)", Vector) = (0.1,0.1,1,1)
        _DistanceFade ("Distance Fade (X=Near, Y=Far, ZW=Unused)", Float) = (20, 50, 0, 0)
        [Toggle(MASK)] _MASK ("Texture Blue channel is Mask", Float) = 0
        [Toggle(MIRROR_EDGE)] _MIRROR_EDGE ("Mirror screen borders", Float) = 0
        [Enum(UnityEngine.Rendering.CullMode)] _CullMode ("Culling", Float) = 0
        [Toggle(DEBUGUV)] _DEBUGUV ("Debug Texture Coordinates", Float) = 0
        [Toggle(DEBUGDISTANCEFADE)] _DEBUGDISTANCEFADE ("Debug Distance Fade", Float) = 0
    }

    SubShader
    {
        Tags {"Queue" = "Transparent" "IgnoreProjector" = "True"}
        Blend One Zero
        Lighting Off
        Fog { Mode Off }
        ZWrite Off
        LOD 200
        Cull [_CullMode]

        // 文档 http://docs.unity3d.com/Manual/SL-GrabPass.html
        // Note: this form of grab pass (not specifying a texture name) will do the
        // expensive screen grabbing operation for each object that uses it!
        GrabPass{ }

        Pass
        {  
            CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #pragma shader_feature MASK
                #pragma shader_feature MIRROR_EDGE
                #pragma shader_feature DEBUGUV
                #pragma shader_feature DEBUGDISTANCEFADE

                #define ENABLE_TINT 1
                #include "UnityCG.cginc"
                #include "GrabPassDistortion.cginc"
            ENDCG
        }
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值