Unity URP自学笔记三 阴影计算

通过查看Lighting.hlsl,可以看到GetMainLight方法,其中有一个方法是通过阴影坐标来获取不前的阴影值。具体操作是在顶点计算中获取当前顶点的世界坐标,然后在片断着色中通过世界坐标来获取阴影坐标,然后再获取阴影值。如下面的代码片断:

v2f vert (appdata v)
{
     v2f o;
     o.vertex = TransformObjectToHClip(v.vertex);
     o.uv = TRANSFORM_TEX(v.uv, _MainTex);
     o.W = TransformObjectToWorld(v.vertex.xyz);//获取世界坐标
     o.N = TransformObjectToWorldNormal(v.normal);
     return o;
 }

 half4 frag (v2f i) : SV_Target
 {
     float3 N = normalize(i.N);
     Light l =  GetMainLight(TransformWorldToShadowCoord(i.W)); //获取当前的光照信息,包含阴影值
     float3 L = normalize(l.direction);

     // sample the texture
     half4 col = _MainTex.Sample(sampler_MainTex, i.uv);

     half lambert = dot(N,L) * 0.5 + 0.5;
     lambert *= l.shadowAttenuation; //获取阴影值

     half col2 = smoothstep(_Step-0.0001,_Step,lambert)*_Ramp+(1.0-_Ramp);
     
     return col2 * col * _Color;
 }

还需要一个LightMode="ShadowCaster"的Pass,用于计算阴影,这个Pass的代码可以在URP的源码中看到,直接抄过来就行了,唯一需要注意的是GetShadowPositionHClips这个方法最后有一个s,其次还需要在上面的CBUFFER中的值也要写到这个ShadowCaster的pass中,这样才支持SRP Batch。
下面是完整shadow

Shader "URP/Ramp"
{
    Properties
    {
        _Color("Color",Color) = (1,1,1,1)
        _MainTex ("Texture", 2D) = "white" {}
        _Ramp("Ramp",Range(0,1)) = 0.1 //控制亮暗值的对比
        _Step("Step",Range(0,1)) = 0.5 //光照亮度在哪个值时区分显示
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" "RenderPipeline" = "UniversalRenderPipeline" "LightMode" = "UniversalForward" }
        LOD 100

        Pass
        {
            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            // Universal Pipeline keywords
            #pragma multi_compile _ _MAIN_LIGHT_SHADOWS
            #pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
            #pragma multi_compile _ _SHADOWS_SOFT

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

            CBUFFER_START(UnityPerMaterial)
            float4 _MainTex_ST;
            half _Ramp;
            real4 _Color;
            real _Step;
            CBUFFER_END


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

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float3 N : NORMAL;
                float3 W : TEXCOORD1;
                float4 vertex : SV_POSITION;
            };

            TEXTURE2D(_MainTex);
            SAMPLER(sampler_MainTex);

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = TransformObjectToHClip(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                o.W = TransformObjectToWorld(v.vertex.xyz);
                o.N = TransformObjectToWorldNormal(v.normal);
                return o;
            }

            half4 frag (v2f i) : SV_Target
            {
                float3 N = normalize(i.N);
                Light l =  GetMainLight(TransformWorldToShadowCoord(i.W)); //GetMainLight();
                float3 L = normalize(l.direction);

                // sample the texture
                half4 col = _MainTex.Sample(sampler_MainTex, i.uv);

                half lambert = dot(N,L) * 0.5 + 0.5;
                lambert *= l.shadowAttenuation;

                half col2 = smoothstep(_Step-0.0001,_Step,lambert)*_Ramp+(1.0-_Ramp);
                
                return col2 * col * _Color;
            }
            ENDHLSL
        }

        Pass
        {
            
            Tags { "LightMode" = "ShadowCaster" }
            ZWrite On
            ZTest LEqual

            HLSLPROGRAM
            #pragma vertex ShadowPassVertex
            #pragma fragment ShadowPassFragment
            // GPU Instancing
            #pragma multi_compile_instancing

            #include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl"

            float3 _LightDirection;
            
            //和上一个pass一样,用于支持SRP Batch
            CBUFFER_START(UnityPerMaterial)
            float4 _MainTex_ST;
            half _Ramp;
            real4 _Color;
            real _Step;
            CBUFFER_END

            struct Attributes
            {
                float4 positionOS   : POSITION;
                float3 normalOS     : NORMAL;
                float2 texcoord     : TEXCOORD0;
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            struct Varyings
            {
                float2 uv           : TEXCOORD0;
                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));

                #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 ShadowPassVertex(Attributes input)
            {
                Varyings output;
                UNITY_SETUP_INSTANCE_ID(input);

                output.uv = TRANSFORM_TEX(input.texcoord, _MainTex);
                output.positionCS = GetShadowPositionHClips(input);

                return output;
            }
            
            
            half4 ShadowPassFragment(Varyings input): SV_TARGET
            {
                Alpha(SampleAlbedoAlpha(input.uv, TEXTURE2D_ARGS(_BaseMap, sampler_BaseMap)).a, _BaseColor, _Cutoff);
                return 0;
            }     
            ENDHLSL

        }
    }
}

效果图
在这里插入图片描述

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Unity URP中,点光源的自定义阴影需要通过脚本来实现。具体步骤如下: 1. 创建一个新的着色器,并设置其为使用“Universal Render Pipeline/Lit”着色器。 2. 在着色器中添加一个新的块,用于计算阴影: ```hlsl #pragma shader_feature __ _SHADOWS_SOFT #pragma shader_feature __ _SHADOWS_CASCADE float3 ComputeShadowCoord(float4 pos) { float3 shadowCoord = pos.xyz / pos.w; shadowCoord = shadowCoord * 0.5f + 0.5f; #if defined(_SHADOWS_SOFT) shadowCoord.z += 0.0005f; #endif #if defined(_SHADOWS_CASCADE) shadowCoord.z += 0.0001f * pos.w; #endif return shadowCoord; } ``` 3. 在Pass中添加以下代码,用于计算阴影: ```hlsl #ifdef LIGHTMAP_ON SHADOW_COORDS_LIGHTMAP #elif defined(SHADOWS_SCREEN) SHADOW_COORDS_SCREEN #else float3 shadowCoord = ComputeShadowCoord(UnityObjectToClipPos(v.vertex)); #endif ``` 4. 在Pass中添加以下代码,用于生成阴影: ```hlsl #if defined(_SHADOWS_SOFT) float shadow = ComputeSoftPointShadow(shadowCoord, _LightPosition, _LightRadius, _ShadowmapTexture, _ShadowStrength); #elif defined(_SHADOWS_CASCADE) float shadow = ComputeCascadePointShadow(shadowCoord, _CascadeShadowmapTexture, _CascadeShadowStrength, _CascadeShadowDistance); #else float shadow = ComputePointShadow(shadowCoord, _LightPosition, _ShadowmapTexture); #endif return shadow; ``` 其中,ComputePointShadow函数用于计算光源阴影。您可以通过调整参数来自定义阴影的外观和行为。 希望这能帮助到您!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值