非光源阴影投影-URP

URP默认材质下光源阴影:

1.UniversalRenderPipelineAsset 设置阴影质量以及阴影开关

file

2.光源设置阴影

file

3.材质设置为接收阴影
file

顶点投射阴影:

角色名
P_Hero_Swordman_Swordman_001
https://zhuanlan.zhihu.com/p/31504088

思路1:
Shadow Map 投射到Plane上,map以外的地方透明 Planer

思路2:
让被投影的材质可以接收阴影
参考:

https://www.jianshu.com/p/a8e4dd93d7d6

Planer

https://zhuanlan.zhihu.com/p/31504088
https://blog.csdn.net/yinfourever/article/details/108646426
https://blog.csdn.net/linjf520/article/details/112979847
理论:
https://zhuanlan.zhihu.com/p/94491734

完整参考:

 Properties
    {
        _LightDir2("_LightDir", Vector) = (0, 1, 1, 0.1)
        _ShadowColor2("_ShadowColor", Color) = (0, 0, 0, 1)
        _ShadowFalloff2("_ShadowFalloff", Float) = 0
    }
//阴影pass
        Pass
        {
            Name "Shadow"

            Tags
            {
                "Queue" = "Transparent"
                "RenderType" = "Transparent"
                "RenderPipeline" = "UniversalPipeline"
                "LightMode" = "UniversalForwardOnly"
            }
            //用使用模板测试以保证alpha显示正确
            Stencil
            {
                Ref 0
                Comp equal
                Pass incrWrap
                Fail keep
                ZFail keep
            }

            //透明混合模式
            Blend SrcAlpha OneMinusSrcAlpha
            ZTest Less
            //ZWrite Always
            //关闭深度写入
            ZWrite on

            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
                float4 color : COLOR;
            };

            float4 _LightDir2;
            float4 _ShadowColor2;
            float _ShadowFalloff2;

            float3 ShadowProjectPos(float4 vertPos)
            {
                float3 shadowPos;

                //得到顶点的世界空间坐标
                float3 worldPos = mul(unity_ObjectToWorld, vertPos).xyz;

                //灯光方向
                float3 lightDir = normalize(_LightDir2.xyz);

                //阴影的世界空间坐标(低于地面的部分不做改变)
                shadowPos.y = min(worldPos.y, _LightDir2.w);
                shadowPos.xz = worldPos.xz - lightDir.xz * max(0, worldPos.y - _LightDir2.w) / lightDir.y;

                return shadowPos;
            }

            v2f vert(appdata v)
            {
                v2f o;

                //得到阴影的世界空间坐标
                float3 shadowPos = ShadowProjectPos(v.vertex);

                //转换到裁切空间
                o.vertex = UnityWorldToClipPos(shadowPos);

                //得到中心点世界坐标
                float3 center = float3(unity_ObjectToWorld[0].w, _LightDir2.w, unity_ObjectToWorld[2].w);
                //计算阴影衰减
                float falloff = 1 - saturate(distance(shadowPos, center) * _ShadowFalloff2);

                //阴影颜色
                o.color = _ShadowColor2;
                o.color.a *= falloff;

                return o;
            }

            fixed4 frag(v2f i) : SV_Target
            {
                return i.color;
            }
            ENDHLSL
        }

URP下多Pass 渲染

每一个Pass 需要不同LightMode,否则Pass无效

https://blog.csdn.net/TGB666/article/details/122266277

URP下多光源阴影

https://zhuanlan.zhihu.com/p/158172358

https://www.jianshu.com/p/a8e4dd93d7d6

https://blog.csdn.net/zakerhero/article/details/106274331

阴影接收

最简单的阴影接收 叠加Diffuse

Shader "URP/MultiLightShadow"
{
    Properties
    {
        _Diffuse("Diffuse", Color) = (1, 1, 1, 1)
    }
    SubShader
    {

        Pass
        {
            Tags
            {
                "RenderType" = "Opaque"
                "RenderPipeline" = "UniversalPipeline"
                "LightMode" = "UniversalForward"
            }

            HLSLPROGRAM
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"

            float4 _Diffuse;

            // 接收阴影所需关键字
            #pragma multi_compile _ _MAIN_LIGHT_SHADOWS
            #pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
            #pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS
            #pragma multi_compile _ _SHADOWS_SOFT

            #pragma vertex vert
            #pragma fragment frag

            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"

            struct Attributes
            {
                float4 positionOS: POSITION;
            };

            struct Varyings
            {
                float4 positionCS: POSITION;//或者 SV_POSITION
                float3 positionWS: TEXCOORD0;
            };

            Varyings vert(Attributes v)
            {
                Varyings o;
                // 获取不同空间下坐标信息
                VertexPositionInputs positionInputs = GetVertexPositionInputs(v.positionOS.xyz);
                o.positionCS = positionInputs.positionCS;
                o.positionWS = positionInputs.positionWS;

                return o;
            }

            half4 frag(Varyings input) : SV_Target
            {
                // 获取阴影坐标
                float4 shadowCoord = TransformWorldToShadowCoord(input.positionWS.xyz);
                //使用HLSL的函数获取主光源数据
                Light mainLight = GetMainLight(shadowCoord);
                half3 diffuse = mainLight.color * mainLight.distanceAttenuation * mainLight.shadowAttenuation * _Diffuse
                    .rgb;
                return half4(diffuse, 1.0);
            }
            ENDHLSL
        }
    }
    FallBack "Packages/com.unity.render-pipelines.universal/FallbackError"
}

阴影投射

AES 新建一个PBR Shader,拷过去即可

最简单的阴影投射

//下面计算阴影的Pass可以直接通过使用URP内置的Pass计算
        //UsePass "Universal Render Pipeline/Lit/ShadowCaster"
        // or
        // 计算阴影的Pass
        Pass
        {
            Name "ShadowCaster"
            Tags { "LightMode" = "ShadowCaster" }
            Cull Off
            ZWrite On
            ZTest LEqual

            HLSLPROGRAM

            // 设置关键字
            #pragma shader_feature _ALPHATEST_ON

            #pragma vertex vert
            #pragma fragment frag

            #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl"

            float3 _LightDirection;

            struct Attributes
            {
                float4 positionOS: POSITION;
                float3 normalOS: NORMAL;
            };

            struct Varyings
            {
                float4 positionCS: SV_POSITION;
            };            

            // 获取裁剪空间下的阴影坐标
            float4 GetShadowPositionHClips(Attributes input)
            {
                float3 positionWS = TransformObjectToWorld(input.positionOS.xyz);
                float3 normalWS = TransformObjectToWorldNormal(input.normalOS);
                // 获取阴影专用裁剪空间下的坐标
                float4 positionCS = TransformWorldToHClip(ApplyShadowBias(positionWS, normalWS, _LightDirection));

                // 判断是否是在DirectX平台翻转过坐标
                #if UNITY_REVERSED_Z
                    positionCS.z = min(positionCS.z, positionCS.w * UNITY_NEAR_CLIP_VALUE);
                #else
                    positionCS.z = max(positionCS.z, positionCS.w * UNITY_NEAR_CLIP_VALUE);
                #endif

                return positionCS;
            }

            Varyings vert(Attributes input)
            {
                Varyings output;
                output.positionCS = GetShadowPositionHClips(input);
                return output;
            }

            half4 frag(Varyings input): SV_TARGET
            {
                return 0;
            }

            ENDHLSL

        }

CG 语言API 参考

https://developer.download.nvidia.cn/cg/index_stdlib.html

留下评论