Unity URP支持多光源阴影

前文:Unity URPShader支持多光源处理

上文只是简单的实现了光照照亮效果,但是并没有实现多光源的阴影投射功能,接下来就是对此功能的整合。

接收阴影

//声明需要的变体和文件
//平行光的阴影
#pragma shader_feature _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE
//额外光的阴影
#pragma shader_feature _ _ADDITIONAL_LIGHT_SHADOWS
//阴影质量选择
#pragma shader_feature _ _SHADOWS_SOFT _SHADOWS_SOFT_LOW _SHADOWS_SOFT_MEDIUM _SHADOWS_SOFT_HIGH

#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
//shadowCoord 代表主光源平行光采样ShadowMap的阴影UV,shadowMask是额外光的遮罩
#if _RECEIVESHADOW_ON
        float4 shadowCoord = TransformWorldToShadowCoord(positionWS);
        o.shadowCoord = shadowCoord;
        #if defined(SHADOWS_SHADOWMASK) && defined(LIGHTMAP_ON)
            half4 shadowMask = inputData.shadowMask;
        #elif !defined(LIGHTMAP_ON)
            half4 shadowMask = unity_ProbesOcclusion;
        #else
            half4 shadowMask = half4(1, 1, 1, 1);
        #endif
#endif
//顶点处理
  #ifdef _ADDITIONAL_LIGHTS_VERTEX
      uint pixelLightCount = GetAdditionalLightsCount();
      #if _RECEIVESHADOW_ON
          for (uint lightIndex = 0u; lightIndex < pixelLightCount; ++lightIndex)
          {
              Light light = GetAdditionalLight(lightIndex, positionWS, shadowMask);
              half3 attenuatedLightColor = light.color * (light.distanceAttenuation * (light.shadowAttenuation + 0.5));
              lightColor += LightingLambert(attenuatedLightColor, light.direction, o.normalWS);
          }
      #else
          for (uint lightIndex = 0u; lightIndex < pixelLightCount; ++lightIndex)
          {
              Light light = GetAdditionalLight(lightIndex, positionWS);
              half3 attenuatedLightColor = light.color * (light.distanceAttenuation * (light.shadowAttenuation + 0.5));
              lightColor += LightingLambert(attenuatedLightColor, light.direction, o.normalWS);
          }
      #endif

额外光处理的主要函数是GetAdditionalLight(),可以在RealtimeLights hlsl文件中找到几个重载方法。

//片元处理
  //光照
  half3 lightColor = i.lightColor;
  #if _RECEIVESHADOW_ON
      Light main_light = GetMainLight(i.shadowCoord);
      half3 main_light_dir = normalize(main_light.direction);
      half diffuse_term = dot(normalize(i.normalWS), main_light_dir) * 0.5 + 0.5;
      lightColor += diffuse_term * main_light.color * (main_light.shadowAttenuation + 0.5);
      #ifdef _ADDITIONAL_LIGHTS
          uint pixelLightCount = GetAdditionalLightsCount();
          for (uint lightIndex = 0u; lightIndex < pixelLightCount; ++lightIndex)
          {
              Light light = GetAdditionalLight(lightIndex, i.positionWS.xyz, i.shadowMask);
              half3 attenuatedLightColor = light.color * (light.distanceAttenuation * (light.shadowAttenuation + 0.5));
              lightColor += LightingLambert(attenuatedLightColor, light.direction, i.normalWS);
          }
      #endif
  #else
      Light main_light = GetMainLight();
      half3 main_light_dir = normalize(main_light.direction);
      half diffuse_term = dot(normalize(i.normalWS), main_light_dir) * 0.5 + 0.5;
      lightColor += diffuse_term * main_light.color;
      #ifdef _ADDITIONAL_LIGHTS
          uint pixelLightCount = GetAdditionalLightsCount();
          for (uint lightIndex = 0u; lightIndex < pixelLightCount; ++lightIndex)
          {
              Light light = GetAdditionalLight(lightIndex, i.positionWS.xyz);
              half3 attenuatedLightColor = light.color * (light.distanceAttenuation * (light.shadowAttenuation + 0.5));
              lightColor += LightingLambert(attenuatedLightColor, light.direction, i.normalWS);
          }
      #endif
  #endif

投射阴影

  Pass
  {
      Name "ShadowCaster"
      Tags { "LightMode" = "ShadowCaster" }

      ZWrite On
      ZTest LEqual
      ColorMask 0
      Cull[_Cull]

      HLSLPROGRAM
      
      #pragma vertex vert
      #pragma fragment frag
      #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
      #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
      struct Attributes
      {
          float4 positionOS : POSITION;
          float3 normalOS : NORMAL;
      };

      struct Varyings
      {
          float4 positionHS : SV_POSITION;
      };

      half3 _LightDirection;

      Varyings vert(Attributes v)
      {
          Varyings o;
          float3 positionWS = TransformObjectToWorld(v.positionOS.xyz);
          float3 normalWS = TransformObjectToWorldNormal(v.normalOS.xyz);

          positionWS = ApplyShadowBias(positionWS, normalWS, _LightDirection);
          o.positionHS = TransformWorldToHClip(positionWS);

          #if UNITY_REVERSED_Z
              o.positionHS.z = min(o.positionHS.z, UNITY_NEAR_CLIP_VALUE);
          #else
              o.positionHS.z = max(o.positionHS.z, UNITY_NEAR_CLIP_VALUE);
          #endif

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

      ENDHLSL
  }

猜你喜欢

转载自blog.csdn.net/m0_68267247/article/details/141820640