Files
UnrealEngineUWP/Engine/Source/Runtime/Renderer/Private/VirtualShadowMaps/VirtualShadowMapProjection.cpp

523 lines
22 KiB
C++
Raw Normal View History

// Copyright Epic Games, Inc. All Rights Reserved.
/*=============================================================================
VirtualShadowMapProjection.cpp
=============================================================================*/
#include "VirtualShadowMapProjection.h"
#include "VirtualShadowMapVisualizationData.h"
#include "CoreMinimal.h"
#include "Stats/Stats.h"
#include "RHI.h"
#include "RenderResource.h"
#include "RendererInterface.h"
#include "Shader.h"
#include "StaticBoundShaderState.h"
#include "SceneUtils.h"
#include "RHIStaticStates.h"
#include "LightSceneInfo.h"
#include "GlobalShader.h"
#include "SceneRenderTargetParameters.h"
#include "ShadowRendering.h"
#include "DeferredShadingRenderer.h"
#include "PixelShaderUtils.h"
#include "ShadowRendering.h"
#include "SceneRendering.h"
#include "VirtualShadowMapClipmap.h"
#include "HairStrands/HairStrandsData.h"
static TAutoConsoleVariable<float> CVarScreenRayLength(
TEXT( "r.Shadow.Virtual.ScreenRayLength" ),
0.015f,
TEXT( "Length of the screen space shadow trace (smart shadow bias) before the virtual shadow map lookup." ),
ECVF_Scalability | ECVF_RenderThreadSafe
);
static TAutoConsoleVariable<float> CVarNormalBias(
TEXT( "r.Shadow.Virtual.NormalBias" ),
0.5f,
TEXT( "Receiver offset along surface normal for shadow lookup. Scaled by distance to camera." )
TEXT( "Higher values avoid artifacts on surfaces nearly parallel to the light, but also visibility offset shadows and increase the chance of hitting unmapped pages." ),
ECVF_Scalability | ECVF_RenderThreadSafe
);
TAutoConsoleVariable<int32> CVarVirtualShadowOnePassProjection(
TEXT("r.Shadow.Virtual.OnePassProjection"),
0,
TEXT("Single pass projects all local VSMs culled with the light grid. Used in conjunction with clustered deferred shading."),
ECVF_Scalability | ECVF_RenderThreadSafe
);
static TAutoConsoleVariable<int32> CVarSMRTRayCountLocal(
TEXT( "r.Shadow.Virtual.SMRT.RayCountLocal" ),
7,
TEXT( "Ray count for shadow map tracing of local lights. 0 = disabled." ),
ECVF_Scalability | ECVF_RenderThreadSafe
);
static TAutoConsoleVariable<int32> CVarSMRTSamplesPerRayLocal(
TEXT( "r.Shadow.Virtual.SMRT.SamplesPerRayLocal" ),
8,
TEXT( "Shadow map samples per ray for local lights" ),
ECVF_Scalability | ECVF_RenderThreadSafe
);
static TAutoConsoleVariable<float> CVarSMRTMaxRayAngleFromLight(
TEXT( "r.Shadow.Virtual.SMRT.MaxRayAngleFromLight" ),
0.03f,
TEXT( "Max angle (in radians) a ray is allowed to span from the light's perspective for local lights." )
TEXT( "Smaller angles limit the screen space size of shadow penumbra. " )
TEXT( "Larger angles lead to more noise. " ),
ECVF_RenderThreadSafe
);
static TAutoConsoleVariable<int32> CVarSMRTRayCountDirectional(
TEXT( "r.Shadow.Virtual.SMRT.RayCountDirectional" ),
7,
TEXT( "Ray count for shadow map tracing of directional lights. 0 = disabled." ),
ECVF_Scalability | ECVF_RenderThreadSafe
);
static TAutoConsoleVariable<int32> CVarSMRTSamplesPerRayDirectional(
TEXT( "r.Shadow.Virtual.SMRT.SamplesPerRayDirectional" ),
8,
TEXT( "Shadow map samples per ray for directional lights" ),
ECVF_Scalability | ECVF_RenderThreadSafe
);
static TAutoConsoleVariable<float> CVarSMRTRayLengthScaleDirectional(
TEXT( "r.Shadow.Virtual.SMRT.RayLengthScaleDirectional" ),
1.5f,
TEXT( "Length of ray to shoot for directional lights, scaled by distance to camera." )
TEXT( "Shorter rays limit the screen space size of shadow penumbra. " )
TEXT( "Longer rays require more samples to avoid shadows disconnecting from contact points. " ),
ECVF_RenderThreadSafe
);
static TAutoConsoleVariable<int32> CVarSMRTAdaptiveRayCount(
TEXT( "r.Shadow.Virtual.SMRT.AdaptiveRayCount" ),
1,
TEXT( "Shoot fewer rays in fully shadowed and unshadowed regions. Currently only supported with OnePassProjection. " ),
ECVF_Scalability | ECVF_RenderThreadSafe
);
static TAutoConsoleVariable<float> CVarSMRTTexelDitherScaleDirectional(
TEXT( "r.Shadow.Virtual.SMRT.TexelDitherScaleDirectional" ),
2.0f,
TEXT( "Applies a dither to the shadow map ray casts for directional lights to help hide aliasing due to insufficient shadow resolution.\n" )
TEXT( "Setting this too high can cause shadows light leaks near occluders." ),
ECVF_Scalability | ECVF_RenderThreadSafe
);
static TAutoConsoleVariable<float> CVarSMRTWorldDitherScaleDirectional(
TEXT( "r.Shadow.Virtual.SMRT.WorldDitherScaleDirectional" ),
0.0f,
TEXT( "Applies a world." ),
ECVF_Scalability | ECVF_RenderThreadSafe
);
TAutoConsoleVariable<int32> CVarSMRTExtrapolateWithSlope(
TEXT("r.Shadow.Virtual.SMRT.ExtrapolateWithSlope"),
1,
TEXT("Use slope-based extrapolation behind occluders. This can increase the quality of shadow penumbra on surfaces aligned with the light direction."),
ECVF_Scalability | ECVF_RenderThreadSafe
);
static TAutoConsoleVariable<int32> CVarForcePerLightShadowMaskClear(
TEXT( "r.Shadow.Virtual.ForcePerLightShadowMaskClear" ),
0,
TEXT( "" ),
ECVF_RenderThreadSafe
);
const TCHAR* ToString(EVirtualShadowMapProjectionInputType In)
{
switch (In)
{
case EVirtualShadowMapProjectionInputType::HairStrands: return TEXT("HairStrands");
case EVirtualShadowMapProjectionInputType::GBuffer: return Strata::IsStrataEnabled() ? TEXT("Strata") : TEXT("GBuffer");
}
return TEXT("Invalid");
}
// Composite denoised shadow projection mask onto the light's shadow mask
// Basically just a copy shader with a special blend mode
class FVirtualShadowMapProjectionCompositePS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FVirtualShadowMapProjectionCompositePS);
SHADER_USE_PARAMETER_STRUCT(FVirtualShadowMapProjectionCompositePS, FGlobalShader);
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_RDG_TEXTURE(Texture2D<float4>, InputShadowFactor)
RENDER_TARGET_BINDING_SLOTS()
END_SHADER_PARAMETER_STRUCT()
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
return DoesPlatformSupportNanite(Parameters.Platform);
}
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
// Required right now due to where the shader function lives, but not actually used
FVirtualShadowMapArray::SetShaderDefines(OutEnvironment);
}
};
IMPLEMENT_GLOBAL_SHADER(FVirtualShadowMapProjectionCompositePS, "/Engine/Private/VirtualShadowMaps/VirtualShadowMapProjection.usf", "VirtualShadowMapCompositePS", SF_Pixel);
void CompositeVirtualShadowMapMask(
FRDGBuilder& GraphBuilder,
const FIntRect ScissorRect,
const FRDGTextureRef Input,
bool bDirectionalLight,
FRDGTextureRef OutputShadowMaskTexture)
{
auto ShaderMap = GetGlobalShaderMap(GMaxRHIFeatureLevel);
FVirtualShadowMapProjectionCompositePS::FParameters* PassParameters = GraphBuilder.AllocParameters<FVirtualShadowMapProjectionCompositePS::FParameters>();
PassParameters->InputShadowFactor = Input;
PassParameters->RenderTargets[0] = FRenderTargetBinding(OutputShadowMaskTexture, ERenderTargetLoadAction::ELoad);
FRHIBlendState* BlendState = FProjectedShadowInfo::GetBlendStateForProjection(
0, // ShadowMapChannel
bDirectionalLight, // bIsWholeSceneDirectionalShadow,
false, // bUseFadePlane
false, // bProjectingForForwardShading,
false // bMobileModulatedProjections
);
auto PixelShader = ShaderMap->GetShader<FVirtualShadowMapProjectionCompositePS>();
ValidateShaderParameters(PixelShader, *PassParameters);
FPixelShaderUtils::AddFullscreenPass(GraphBuilder,
ShaderMap,
RDG_EVENT_NAME("MaskComposite"),
PixelShader,
PassParameters,
ScissorRect,
BlendState);
}
class FVirtualShadowMapProjectionCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FVirtualShadowMapProjectionCS);
SHADER_USE_PARAMETER_STRUCT(FVirtualShadowMapProjectionCS, FGlobalShader)
class FDirectionalLightDim : SHADER_PERMUTATION_BOOL("DIRECTIONAL_LIGHT");
class FSMRTExtrapolateSlopeDim : SHADER_PERMUTATION_BOOL("SMRT_EXTRAPOLATE_WITH_SLOPE");
class FOnePassProjectionDim : SHADER_PERMUTATION_BOOL("ONE_PASS_PROJECTION");
class FHairStrandsDim : SHADER_PERMUTATION_BOOL("HAS_HAIR_STRANDS");
class FVisualizeOutputDim : SHADER_PERMUTATION_BOOL("VISUALIZE_OUTPUT");
// -1 means dynamic count
class FSMRTStaticSampleCount : SHADER_PERMUTATION_RANGE_INT("SMRT_TEMPLATE_STATIC_SAMPLES_PER_RAY", -1, 2);
using FPermutationDomain = TShaderPermutationDomain<
FDirectionalLightDim,
FOnePassProjectionDim,
FHairStrandsDim,
FVisualizeOutputDim,
FSMRTExtrapolateSlopeDim,
FSMRTStaticSampleCount>;
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_STRUCT_INCLUDE(FVirtualShadowMapSamplingParameters, SamplingParameters)
SHADER_PARAMETER_RDG_UNIFORM_BUFFER(FSceneTextureUniformParameters, SceneTexturesStruct)
SHADER_PARAMETER_RDG_UNIFORM_BUFFER(FHairStrandsViewUniformParameters, HairStrands)
SHADER_PARAMETER_RDG_UNIFORM_BUFFER(FVirtualVoxelParameters, HairStrandsVoxel)
SHADER_PARAMETER_RDG_UNIFORM_BUFFER(FStrataGlobalUniformParameters, Strata)
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, View)
SHADER_PARAMETER(FIntVector4, ProjectionRect)
SHADER_PARAMETER(float, ScreenRayLength)
SHADER_PARAMETER(float, NormalBias)
SHADER_PARAMETER(uint32, SMRTRayCount)
SHADER_PARAMETER(uint32, SMRTSamplesPerRay)
SHADER_PARAMETER(float, SMRTRayLengthScale)
SHADER_PARAMETER(float, SMRTCotMaxRayAngleFromLight)
SHADER_PARAMETER(float, SMRTTexelDitherScale)
SHADER_PARAMETER(float, SMRTWorldDitherScale)
SHADER_PARAMETER(uint32, bSMRTUseAdaptiveRayCount)
SHADER_PARAMETER(uint32, InputType)
SHADER_PARAMETER(uint32, bCullBackfacingPixels)
// One pass projection parameters
SHADER_PARAMETER_RDG_UNIFORM_BUFFER(FForwardLightData, ForwardLightData)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, OutShadowMaskBits)
// Pass per light parameters
SHADER_PARAMETER_STRUCT(FLightShaderParameters, Light)
SHADER_PARAMETER(int32, LightUniformVirtualShadowMapId)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, OutShadowFactor)
// Visualization output
SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer< FPhysicalPageMetaData >, PhysicalPageMetaData)
SHADER_PARAMETER(int32, VisualizeModeId)
SHADER_PARAMETER(int32, VisualizeVirtualShadowMapId)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, OutVisualize)
END_SHADER_PARAMETER_STRUCT()
static void ModifyCompilationEnvironment( const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment )
{
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
FVirtualShadowMapArray::SetShaderDefines(OutEnvironment);
FForwardLightingParameters::ModifyCompilationEnvironment(Parameters.Platform, OutEnvironment);
FPermutationDomain PermutationVector(Parameters.PermutationId);
// TODO: We may no longer need this with SM6 requirement, but shouldn't hurt
OutEnvironment.CompilerFlags.Add(CFLAG_WaveOperations);
OutEnvironment.CompilerFlags.Add(CFLAG_Wave32);
if (FDataDrivenShaderPlatformInfo::GetSupportsRealTypes(Parameters.Platform) == ERHIFeatureSupport::RuntimeGuaranteed)
{
OutEnvironment.CompilerFlags.Add(CFLAG_AllowRealTypes);
}
}
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
FPermutationDomain PermutationVector(Parameters.PermutationId);
// Directional lights are always in separate passes as forward light data structure currently
// only contains a single directional light.
if( PermutationVector.Get< FDirectionalLightDim >() && PermutationVector.Get< FOnePassProjectionDim >() )
{
return false;
}
return DoesPlatformSupportNanite(Parameters.Platform);
}
};
IMPLEMENT_GLOBAL_SHADER(FVirtualShadowMapProjectionCS, "/Engine/Private/VirtualShadowMaps/VirtualShadowMapProjection.usf", "VirtualShadowMapProjection", SF_Compute);
static float GetNormalBiasForShader()
{
return CVarNormalBias.GetValueOnRenderThread() / 1000.0f;
}
static void RenderVirtualShadowMapProjectionCommon(
FRDGBuilder& GraphBuilder,
const FMinimalSceneTextures& SceneTextures,
const FViewInfo& View, int32 ViewIndex,
FVirtualShadowMapArray& VirtualShadowMapArray,
const FIntRect ProjectionRect,
EVirtualShadowMapProjectionInputType InputType,
FRDGTextureRef OutputTexture,
const FLightSceneProxy* LightProxy = nullptr,
int32 VirtualShadowMapId = INDEX_NONE)
{
check(GRHISupportsWaveOperations);
// Use hair strands data (i.e., hair voxel tracing) only for Gbuffer input for casting hair shadow onto opaque geometry.
const bool bHasHairStrandsData = HairStrands::HasViewHairStrandsData(View);
FVirtualShadowMapProjectionCS::FParameters* PassParameters = GraphBuilder.AllocParameters< FVirtualShadowMapProjectionCS::FParameters >();
PassParameters->SamplingParameters = VirtualShadowMapArray.GetSamplingParameters(GraphBuilder);
PassParameters->SceneTexturesStruct = SceneTextures.UniformBuffer;
PassParameters->View = View.ViewUniformBuffer;
PassParameters->ProjectionRect = FIntVector4(ProjectionRect.Min.X, ProjectionRect.Min.Y, ProjectionRect.Max.X, ProjectionRect.Max.Y);
PassParameters->ScreenRayLength = CVarScreenRayLength.GetValueOnRenderThread();
PassParameters->NormalBias = GetNormalBiasForShader();
PassParameters->InputType = uint32(InputType);
PassParameters->bCullBackfacingPixels = VirtualShadowMapArray.ShouldCullBackfacingPixels() ? 1 : 0;
PassParameters->bSMRTUseAdaptiveRayCount = CVarSMRTAdaptiveRayCount.GetValueOnRenderThread() != 0 ? 1 : 0;
PassParameters->Strata = Strata::BindStrataGlobalUniformParameters(View);
if (bHasHairStrandsData)
{
PassParameters->HairStrands = HairStrands::BindHairStrandsViewUniformParameters(View);
PassParameters->HairStrandsVoxel = HairStrands::BindHairStrandsVoxelUniformParameters(View);
}
bool bDirectionalLight = false;
bool bOnePassProjection = LightProxy == nullptr;
if (bOnePassProjection)
{
// One pass projection
PassParameters->ForwardLightData = View.ForwardLightingResources.ForwardLightUniformBuffer;
PassParameters->OutShadowMaskBits = GraphBuilder.CreateUAV( OutputTexture );
}
else
{
// Pass per light
bDirectionalLight = LightProxy->GetLightType() == LightType_Directional;
FLightRenderParameters LightParameters;
LightProxy->GetLightShaderParameters(LightParameters);
LightParameters.MakeShaderParameters(View.ViewMatrices, PassParameters->Light);
PassParameters->LightUniformVirtualShadowMapId = VirtualShadowMapId;
PassParameters->OutShadowFactor = GraphBuilder.CreateUAV( OutputTexture );
}
if (bDirectionalLight)
{
PassParameters->SMRTRayCount = CVarSMRTRayCountDirectional.GetValueOnRenderThread();
PassParameters->SMRTSamplesPerRay = CVarSMRTSamplesPerRayDirectional.GetValueOnRenderThread();
PassParameters->SMRTRayLengthScale = CVarSMRTRayLengthScaleDirectional.GetValueOnRenderThread();
PassParameters->SMRTCotMaxRayAngleFromLight = 0.0f; // unused in this path
PassParameters->SMRTTexelDitherScale = CVarSMRTTexelDitherScaleDirectional.GetValueOnRenderThread();
PassParameters->SMRTWorldDitherScale = CVarSMRTWorldDitherScaleDirectional.GetValueOnRenderThread();
}
else
{
PassParameters->SMRTRayCount = CVarSMRTRayCountLocal.GetValueOnRenderThread();
PassParameters->SMRTSamplesPerRay = CVarSMRTSamplesPerRayLocal.GetValueOnRenderThread();
PassParameters->SMRTRayLengthScale = 0.0f; // unused in this path
PassParameters->SMRTCotMaxRayAngleFromLight = 1.0f / FMath::Tan(CVarSMRTMaxRayAngleFromLight.GetValueOnRenderThread());
PassParameters->SMRTTexelDitherScale = 0.0f; // not yet implemented
PassParameters->SMRTWorldDitherScale = 0.0f; // not yet implemented
}
bool bDebugOutput = false;
#if !UE_BUILD_SHIPPING
if ( !VirtualShadowMapArray.DebugVisualizationOutput.IsEmpty() && InputType == EVirtualShadowMapProjectionInputType::GBuffer && VirtualShadowMapArray.VisualizeLight.IsValid() )
{
const FVirtualShadowMapVisualizationData& VisualizationData = GetVirtualShadowMapVisualizationData();
bDebugOutput = true;
PassParameters->VisualizeModeId = VisualizationData.GetActiveModeID();
PassParameters->VisualizeVirtualShadowMapId = VirtualShadowMapArray.VisualizeLight.GetVirtualShadowMapId();
PassParameters->PhysicalPageMetaData = GraphBuilder.CreateSRV( VirtualShadowMapArray.PhysicalPageMetaDataRDG );
PassParameters->OutVisualize = GraphBuilder.CreateUAV( VirtualShadowMapArray.DebugVisualizationOutput[ViewIndex] );
}
#endif
// If the requested samples per ray matches one of our static permutations, pick that one
// Otherwise use the dynamic samples per ray permutation (-1).
int StaticSamplesPerRay = PassParameters->SMRTSamplesPerRay == 0 ? PassParameters->SMRTSamplesPerRay : -1;
FVirtualShadowMapProjectionCS::FPermutationDomain PermutationVector;
PermutationVector.Set< FVirtualShadowMapProjectionCS::FDirectionalLightDim >( bDirectionalLight );
PermutationVector.Set< FVirtualShadowMapProjectionCS::FOnePassProjectionDim >( bOnePassProjection );
PermutationVector.Set< FVirtualShadowMapProjectionCS::FSMRTExtrapolateSlopeDim >( CVarSMRTExtrapolateWithSlope.GetValueOnRenderThread() != 0 );
PermutationVector.Set< FVirtualShadowMapProjectionCS::FHairStrandsDim >( bHasHairStrandsData );
PermutationVector.Set< FVirtualShadowMapProjectionCS::FVisualizeOutputDim >( bDebugOutput );
PermutationVector.Set< FVirtualShadowMapProjectionCS::FSMRTStaticSampleCount >( StaticSamplesPerRay );
auto ComputeShader = View.ShaderMap->GetShader< FVirtualShadowMapProjectionCS >( PermutationVector );
ClearUnusedGraphResources( ComputeShader, PassParameters );
ValidateShaderParameters( ComputeShader, *PassParameters );
const FIntPoint GroupCount = FIntPoint::DivideAndRoundUp( ProjectionRect.Size(), 8 );
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("VirtualShadowMapProjection(RayCount:%u(%s),SamplesPerRay:%u,Input:%s%s)",
PassParameters->SMRTRayCount,
PassParameters->bSMRTUseAdaptiveRayCount ? TEXT("Adaptive") : TEXT("Static"),
PassParameters->SMRTSamplesPerRay,
ToString(InputType),
bDebugOutput ? TEXT(",Debug") : TEXT("")),
ComputeShader,
PassParameters,
FIntVector( GroupCount.X, GroupCount.Y, 1 )
);
}
FRDGTextureRef RenderVirtualShadowMapProjectionOnePass(
FRDGBuilder& GraphBuilder,
const FMinimalSceneTextures& SceneTextures,
const FViewInfo& View, int32 ViewIndex,
FVirtualShadowMapArray& VirtualShadowMapArray,
EVirtualShadowMapProjectionInputType InputType)
{
FIntRect ProjectionRect = View.ViewRect;
const FRDGTextureDesc ShadowMaskDesc = FRDGTextureDesc::Create2D(
SceneTextures.Config.Extent,
VirtualShadowMapArray.GetPackedShadowMaskFormat(),
FClearValueBinding::None,
TexCreate_ShaderResource | TexCreate_UAV);
FRDGTextureRef ShadowMaskBits = GraphBuilder.CreateTexture(ShadowMaskDesc, InputType == EVirtualShadowMapProjectionInputType::HairStrands ? TEXT("ShadowMaskBits(HairStrands)") : TEXT("ShadowMaskBits(Gbuffer)"));
RenderVirtualShadowMapProjectionCommon(
GraphBuilder,
SceneTextures,
View, ViewIndex,
VirtualShadowMapArray,
ProjectionRect,
InputType,
ShadowMaskBits);
return ShadowMaskBits;
}
static FRDGTextureRef CreateShadowMaskTexture(FRDGBuilder& GraphBuilder, FIntPoint Extent)
{
const FLinearColor ClearColor(0.0f, 0.0f, 0.0f, 0.0f);
FRDGTextureDesc Desc = FRDGTextureDesc::Create2D(
Extent,
PF_G16R16,
FClearValueBinding(ClearColor),
TexCreate_ShaderResource | TexCreate_UAV);
FRDGTextureRef Texture = GraphBuilder.CreateTexture(Desc, TEXT("Shadow.Virtual.ShadowMask"));
// NOTE: Projection pass writes all relevant pixels, so should not need to clear here
if (CVarForcePerLightShadowMaskClear.GetValueOnRenderThread() != 0)
{
AddClearUAVPass(GraphBuilder, GraphBuilder.CreateUAV(Texture), ClearColor);
}
return Texture;
}
void RenderVirtualShadowMapProjection(
FRDGBuilder& GraphBuilder,
const FMinimalSceneTextures& SceneTextures,
const FViewInfo& View, int32 ViewIndex,
FVirtualShadowMapArray& VirtualShadowMapArray,
const FIntRect ScissorRect,
EVirtualShadowMapProjectionInputType InputType,
FProjectedShadowInfo* ShadowInfo,
FRDGTextureRef OutputShadowMaskTexture)
{
FRDGTextureRef VirtualShadowMaskTexture = CreateShadowMaskTexture(GraphBuilder, View.ViewRect.Max);
RenderVirtualShadowMapProjectionCommon(
GraphBuilder,
SceneTextures,
View, ViewIndex,
VirtualShadowMapArray,
ScissorRect,
InputType,
VirtualShadowMaskTexture,
ShadowInfo->GetLightSceneInfo().Proxy,
ShadowInfo->VirtualShadowMaps[0]->ID);
CompositeVirtualShadowMapMask(
GraphBuilder,
ScissorRect,
VirtualShadowMaskTexture,
false, // bDirectionalLight
OutputShadowMaskTexture);
}
void RenderVirtualShadowMapProjection(
FRDGBuilder& GraphBuilder,
const FMinimalSceneTextures& SceneTextures,
const FViewInfo& View, int32 ViewIndex,
FVirtualShadowMapArray& VirtualShadowMapArray,
const FIntRect ScissorRect,
EVirtualShadowMapProjectionInputType InputType,
const TSharedPtr<FVirtualShadowMapClipmap>& Clipmap,
FRDGTextureRef OutputShadowMaskTexture)
{
FRDGTextureRef VirtualShadowMaskTexture = CreateShadowMaskTexture(GraphBuilder, View.ViewRect.Max);
RenderVirtualShadowMapProjectionCommon(
GraphBuilder,
SceneTextures,
View, ViewIndex,
VirtualShadowMapArray,
ScissorRect,
InputType,
VirtualShadowMaskTexture,
Clipmap->GetLightSceneInfo().Proxy,
Clipmap->GetVirtualShadowMap()->ID);
CompositeVirtualShadowMapMask(
GraphBuilder,
ScissorRect,
VirtualShadowMaskTexture,
true, // bDirectionalLight
OutputShadowMaskTexture);
}