平面阴影实现

最近项目优化低端机的渲染性能,对于阴影的处理一方面是关闭阴影,另一方面是简化原有的Shader阴影部分的实现。 就在刚才王者打吐之际,闲来无事写个简化版阴影Shader,。

思路很简单: 脚下为平面,进行平面投射。没错就是这么简单。因为简单所以高效。

由于时刻跟随脚下,所以遇见非平面会镶嵌里面或者伸出。 但这并不影响,主要目的是低端机的替代品。

如果帮助到你,实属荣幸。如果你有更好的方案(主要兼顾性能,其次表现)欢迎留言讨论。

最后附上效果图 和 全部代码,代码的渲染pass 自己实现, 阴影部分可以复制代码,或者usepass 。

时候不早了, 睡觉, 早安各位!

Shader "Shadows/LowPassShadow"
{
    Properties
    {
        _ShadowOffset("ShadowOffset", vector) = (0, 0, 0, 0)
        _ShadowColor("ShadowColor", Color) = (0.3, 0.3, 0.3, 1)
        [Enum(UnityEngine.Rendering.BlendMode)] _SrcBlend("Src Blend Mode", Float) = 1
        [Enum(UnityEngine.Rendering.BlendMode)] _DstBlend("Dst Blend Mode", Float) = 10
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        //简单阴影Pass
        Pass
        {
            Name "SampleShadow"

            Tags{"LightMode" = "ForwardBase"}
            ZWrite off

            //Blend Srcalpha OneminusSrcAlpha
            Blend [_SrcBlend] [_DstBlend]
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            #include "Lighting.cginc"


            #pragma shader_feature _Off_Shadow

            float3 _ShadowOffset;
            float4 _ShadowColor = float4(0.3, 0.3, 0.3, 0.5);

            const float4 farPosition = float4(2, 2, 2, 1);

            float4 vert(float4 vertex:POSITION):SV_POSITION
            {
                float3 light2ObjectDirection = UnityWorldSpaceLightDir(vertex);
                
                // 自己控制光线不要出现仰角
                /*
                if (light2ObjectDirection.y <= 0.4)
                {
                    return farPosition;
                }
                */

                float3 objectWorldPosition = mul(unity_ObjectToWorld, vertex);
                float3 objectButtomWorldPosition = mul(unity_ObjectToWorld, float4(0, -0.5, 0, vertex.w));

                float3 outPosition = objectWorldPosition + (objectWorldPosition - objectButtomWorldPosition).y / (-light2ObjectDirection.y) * light2ObjectDirection;
#ifdef _Off_Shadow  
                return farPosition;
#else
                return mul(UNITY_MATRIX_VP, float4(outPosition - _ShadowOffset, 1.0));
#endif
            }

            float4 frag(float4 position: SV_POSITION) :COLOR
            {
                return _ShadowColor;
            }
            ENDCG
        }
    }
}

文章作者: Yonggang Long
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Yonggang Long !
 上一篇
2022-08-10 Yonggang Long
下一篇 
2022-08-10 Yonggang Long
  目录