角色和武器Shader特效開發


角色Shader的動效需求

角Shader的開發不知要實現最基礎光照等功能, 可能還要在角色武器的Shader增加多種動效, 比如因武器品質區分的流光特效, 被技能擊中時的凍結效果.
這類動效的實現方式有多種, 以下以Shader的方式實現下列三種:

  • 流光
  • 溶解
    效果展示

開發思路

具體效果

  • 流光

    兩層
    Alpha控制范圍
  • matcap實現
  • 溶解

    支持溶解邊緣亮邊
    step(fixed2(noise, noise+edge), _Dissolve)

對需要實現的效果進行排序

實現這些需求的過程上來說, 肯定是一層一層在基礎效果只上疊加上去的,相互之間是有"覆蓋"關系的, 於是我們將以上需求排列整理如下:

  • 光照
  • 流光
  • 溶解

2. Shader代碼的實現

1. 封裝

#ifndef MESH_FX_CORE_INCLUDED
    #define MESH_FX_CORE_INCLUDED

    #ifdef MESH_FX_ON
        uniform float4 _EdgeColor;
        uniform sampler2D _DissolveNoiseTex;
        uniform float4 _DissolveNoiseTex_ST;
        uniform float _DissolveWidth;
        uniform float _Dissolve;

        uniform sampler2D   _MatcapTex      ;
        uniform float       _MatcapIntensity;

        uniform float4      _FlowColor;
        uniform sampler2D   _FlowTex        ;
        uniform float4      _FlowTexTiling  ;
        uniform float4      _Flow1Color;
        uniform sampler2D   _FlowTex1       ;
        uniform float4      _FlowSpeed      ;
        uniform float       _FlowIntensity  ;

        struct MeshFXData
        {
            float2 UV0;
            float3 normalWorld;
            fixed3 BaseColor;
        };

        fixed4 FX_Dissolve(MeshFXData fx)
        {
            float2 uv_DissolveNoiseTex = fx.UV0 * _DissolveNoiseTex_ST.xy + _DissolveNoiseTex_ST.zw;
            float4 dissolveTexCol = tex2D(_DissolveNoiseTex, uv_DissolveNoiseTex);
            float2 twoLayer = float2(dissolveTexCol.r, saturate(dissolveTexCol.r + _DissolveWidth));
            float2 dissolveResult = step(twoLayer, _Dissolve.xx);
            float4 finalCol = _EdgeColor * (dissolveResult.x - dissolveResult.y) * dissolveTexCol.r;
            finalCol.a = saturate(dissolveResult.x);
            return finalCol;
        }

        fixed4 FX_Frozen(MeshFXData fx)
        {
            float2 matCapUV = ((mul(UNITY_MATRIX_V, float4(fx.normalWorld, 0.0)).xyz * 0.5) + 0.5).xy;
            float4 finalCol = tex2D(_MatcapTex, matCapUV);
            finalCol.a = _MatcapIntensity;
            return finalCol;
        }

        fixed4 FX_LightFlow(MeshFXData fx)
        {
            float2 uv0 = fx.UV0 * _FlowTexTiling.xy + (_Time.y * _FlowSpeed.xy);
            fixed4 flowCol1 = tex2D(_FlowTex, uv0);
            fixed mask1 = tex2D(_FlowTex, fx.UV0.xy).a; //

            float2 uv1 = fx.UV0 * _FlowTexTiling.zw + (_Time.y * _FlowSpeed.zw);
            fixed4 flowCol2 = tex2D(_FlowTex1, uv1);
            fixed mask2 = tex2D(_FlowTex1, fx.UV0.xy).a;

            fixed4 layer1 = flowCol1 *  mask1 * _FlowColor;
            fixed4 layer2 = flowCol2 * mask2 * _Flow1Color;
            fixed4 col = (layer1 + layer2) * _FlowIntensity;
            col.a = max(flowCol1.a, flowCol2.a);
            return col;
        }

        fixed4 MeshFXInternal(MeshFXData fx)
        {
            fixed4 finalColor = fixed4(0, 0, 0, 0);

            fixed4 Dissolve = FX_Dissolve(fx);
            fixed4 Frozen = FX_Frozen(fx);
            fixed4 LightFlow = FX_LightFlow(fx);

            // lightflow -> frozen -> dissolve

            //lightflow
            finalColor.rgb = fx.BaseColor + LightFlow.rgb * fx.BaseColor * 2;

            //matcap frozen
            finalColor.rgb = lerp(finalColor.rgb, Frozen.rgb, Frozen.a);

            //dissolve
            finalColor.rgb = finalColor + Dissolve.rgb;
            finalColor.a = Dissolve.a;
            return finalColor;
        }
    #endif
#endif

2. 調用

#if defined(MESH_FX_ON)
    MeshFXData fx = (MeshFXData)0;
    fx.UV0 = i.tex.xy;
    fx.normalWorld = s.normalWorld;
    fx.BaseColor = Color.rgb;
    Color = MeshFXInternal(fx);
#endif

3. ShaderGUI的實現

體力活

<wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM