123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 |
- /*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
- #pragma once
- #ifndef ENABLE_SHADOWS
- #define ENABLE_SHADOWS 1
- #endif
- #if ENABLE_SHADOWS
- #ifndef ENABLE_FULLSCREEN_SHADOW
- #define ENABLE_FULLSCREEN_SHADOW 1
- #endif
- #include <scenesrg_all.srgi>
- #include <viewsrg_all.srgi>
- #include <Atom/RPI/Math.azsli>
- #include "Shadow.azsli"
- #include "ShadowmapAtlasLib.azsli"
- #include "BicubicPcfFilters.azsli"
- #include "ReceiverPlaneDepthBias.azsli"
- #include "NormalOffsetShadows.azsli"
- #include "DirectionalLightShadowCalculator.azsli"
- // This matchs ShadowFilterMethod in ShadowConstants.h
- option ShadowFilterMethod o_directional_shadow_filtering_method = ShadowFilterMethod::None;
- option bool o_directional_shadow_receiver_plane_bias_enable = true;
- option bool o_blend_between_cascades_enable = false;
- // DirectionalLightShadow calculates lit ratio for a directional light.
- class DirectionalLightShadow
- {
- static bool UseFullscreenShadows();
- //! Calculates visibility ratio of the surface from the light origin. Should be called from fragment shaders.
- //! Returns lit ratio from the light (1.0 is fully visible, 0.0 is fully shadowed).
- static real GetVisibility(uint lightIndex, float3 worldPos, real3 normalVector, float4 screenUv);
- static float2 GetVisibilityThickTransmission(uint lightIndex, real3 worldPos, real3 normalVector, float4 screenUv);
- static float2 GetVisibilityThinTransmission(uint lightIndex, real3 worldPos, real3 normalVector, float4 screenUv, real shrinkFactor);
- static DirectionalShadowCalculator MakeShadowCalculator(uint lightIndex, float3 worldPos, real3 normalVector);
- //! This alters the input color to visualize which cascade is being used
- //! and whether PCF is used as a fallback in ESM+PCF mode or not.
- static real3 AddDebugColoring(real3 color, uint lightIndex, real3 worldPos, real3 normalVector);
- };
- bool DirectionalLightShadow::UseFullscreenShadows()
- {
- #if ENABLE_FULLSCREEN_SHADOW
- #if FORCE_OPAQUE
- return true;
- #else
- bool useFullscreenShadows = o_opacity_mode == OpacityMode::Opaque || o_opacity_mode == OpacityMode::Cutout;
- return useFullscreenShadows;
- #endif
- #else
- return false;
- #endif
- }
- DirectionalShadowCalculator DirectionalLightShadow::MakeShadowCalculator(uint lightIndex, float3 worldPos, real3 normalVector)
- {
- DirectionalShadowCalculator calc;
- calc.SetBlendBetweenCascadesEnable(o_blend_between_cascades_enable);
- calc.SetShadowmaps(PassSrg::m_directionalLightShadowmap, PassSrg::m_directionalLightExponentialShadowmap);
- calc.SetReceiverShadowPlaneBiasEnable(o_directional_shadow_receiver_plane_bias_enable);
- calc.SetWorldNormal(normalVector);
- calc.SetLightIndex(lightIndex);
- calc.SetFilterMode(o_directional_shadow_filtering_method);
- calc.SetFilteringSampleCount(o_directional_shadow_filtering_sample_count);
- calc.SetWorldPos(worldPos);
- return calc;
- }
- float2 DirectionalLightShadow::GetVisibilityThickTransmission(uint lightIndex, real3 worldPos, real3 normalVector, float4 screenUv)
- {
- float visibility;
- DirectionalShadowCalculator calc = MakeShadowCalculator(lightIndex, worldPos, normalVector);
-
- if (UseFullscreenShadows())
- {
- visibility = PassSrg::m_fullscreenShadow.Load(int3(screenUv.xy, 0)).x;
- // Compute shadow coords for call to GetThickness below
- calc.ComputeShadowCoords();
- }
- else
- {
- visibility = calc.GetVisibility();
- }
- float thickness = calc.GetThickness();
- return float2(visibility, thickness);
- }
- float2 DirectionalLightShadow::GetVisibilityThinTransmission(uint lightIndex, real3 worldPos, real3 normalVector, float4 screenUv, real shrinkFactor)
- {
- float visibility;
- DirectionalShadowCalculator calc = MakeShadowCalculator(lightIndex, worldPos, normalVector);
- if (UseFullscreenShadows())
- {
- visibility = PassSrg::m_fullscreenShadow.Load(int3(screenUv.xy, 0)).x;
- }
- else
- {
- visibility = calc.GetVisibility();
- }
- // Apply transmission shrink factor for thin transmission materials and recalculate shadow coords
- // This way the shrink factor only gets applied to the thickness/transmission factor and not to the default shadows
- calc.SetWorldPos(worldPos - shrinkFactor * normalVector);
- calc.ComputeShadowCoords();
- float thickness = calc.GetThickness();
- return float2(visibility, thickness);
- }
- real DirectionalLightShadow::GetVisibility(uint lightIndex, float3 worldPos, real3 normalVector, float4 screenUv)
- {
- if (UseFullscreenShadows())
- {
- return real(PassSrg::m_fullscreenShadow.Load(int3(screenUv.xy, 0)).x);
- }
- else
- {
- DirectionalShadowCalculator calc = MakeShadowCalculator(lightIndex, worldPos, normalVector);
- return calc.GetVisibility();
- }
- }
- real3 DirectionalLightShadow::AddDebugColoring(real3 color, uint lightIndex, real3 worldPos, real3 normalVector)
- {
- if ((ViewSrg::m_directionalLightShadows[lightIndex].m_debugFlags &
- ViewSrg::DirectionalLightShadowDebugColoringBitMask) == 0)
- {
- return color;
- }
- const uint cascadeCount = ViewSrg::m_directionalLightShadows[lightIndex].m_cascadeCount;
- DirectionalShadowCalculator calc = MakeShadowCalculator(lightIndex, worldPos, normalVector);
- calc.ComputeShadowCoords();
- if (calc.m_maxCascade < cascadeCount)
- {
- // Each cascade has an assigned color. Pixels that are a blend of cascades will blend the colors.
- static const real3 debuggingColors[ViewSrg::MaxCascadeCount] =
- {
- real3(1., 0., 0.),
- real3(0., 1., 0.),
- real3(0., 0., 1.),
- real3(1., 1., 0.)
- };
- real3 debugColor = real3(0.0, 0.0, 0.0);
- for (int i = calc.m_minCascade; i <= calc.m_maxCascade; ++i)
- {
- debugColor += debuggingColors[i];
- }
- debugColor *= real(rcp(calc.m_maxCascade - calc.m_minCascade + 1.0));
- color = color * 0.75 + debugColor * 0.25;
- }
- return color;
- }
- #endif // ENABLE_SHADOWS
|