// Copyright Epic Games, Inc. All Rights Reserved. #include "MegaLights.h" #include "MegaLightsInternal.h" #include "RendererPrivate.h" #include "HairStrandsInterface.h" static TAutoConsoleVariable CVarMegaLightsMinSampleClampingWeight( TEXT("r.MegaLights.MinSampleClampingWeight"), 0.01f, TEXT("Min weight for when any sample clamping can occur (r.MegaLights.DirectionalLightSampleFraction or r.MegaLights.GuideByHistory.VisibleSampleFraction)."), ECVF_Scalability | ECVF_RenderThreadSafe ); static TAutoConsoleVariable CVarMegaLightsDirectionalLightSampleFraction( TEXT("r.MegaLights.DirectionalLightSampleFraction"), 0.5f, TEXT("Max fraction of samples which should be used to sample directional lights. Higher values make directional lights higher quality, but reduce quality of local lights."), ECVF_Scalability | ECVF_RenderThreadSafe ); static TAutoConsoleVariable CVarMegaLightsGuideByHistoryLightHiddenWeight( TEXT("r.MegaLights.GuideByHistory.LightHiddenWeight"), 0.1f, TEXT("PDF weight scale for hidden lights."), ECVF_Scalability | ECVF_RenderThreadSafe ); static TAutoConsoleVariable CVarMegaLightsGuideByHistoryLightHiddenWeightForHistoryMiss( TEXT("r.MegaLights.GuideByHistory.LightHiddenWeightForHistoryMiss"), 0.4f, TEXT("PDF weight scale for hidden lights for pixels without valid temporal history."), ECVF_Scalability | ECVF_RenderThreadSafe ); static TAutoConsoleVariable CVarMegaLightsGuideByHistoryAreaLightHiddenWeight( TEXT("r.MegaLights.GuideByHistory.AreaLightHiddenWeight"), 0.25f, TEXT("PDF weight scale for hidden parts of an area light. 1 will disable area light guiding. Lower values will improve static quality, but will cause more artifacts in motion when area light guiding is wrong."), ECVF_Scalability | ECVF_RenderThreadSafe ); namespace MegaLights { float GetDirectionalLightSampleRatio() { float Fraction = CVarMegaLightsDirectionalLightSampleFraction.GetValueOnRenderThread(); if (Fraction < 1.0f) { return Fraction / (1.0f - Fraction); } else { return 0.0f; } } } class FGenerateLightSamplesCS : public FGlobalShader { DECLARE_GLOBAL_SHADER(FGenerateLightSamplesCS) SHADER_USE_PARAMETER_STRUCT(FGenerateLightSamplesCS, FGlobalShader) BEGIN_SHADER_PARAMETER_STRUCT(FParameters, ) RDG_BUFFER_ACCESS(IndirectArgs, ERHIAccess::IndirectArgs) SHADER_PARAMETER_STRUCT_INCLUDE(FMegaLightsParameters, MegaLightsParameters) SHADER_PARAMETER_STRUCT_INCLUDE(StochasticLighting::FHistoryScreenParameters, HistoryScreenParameters) SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, RWDownsampledSceneDepth) SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, RWDownsampledSceneWorldNormal) SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, RWLightSamples) SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, RWLightSampleRays) SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer, DownsampledTileAllocator) SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer, DownsampledTileData) SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer, VisibleLightHashHistory) SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer, VisibleLightMaskHashHistory) SHADER_PARAMETER(int32, bVisualizeLightLoopIterations) SHADER_PARAMETER(float, LightHiddenPDFWeight) SHADER_PARAMETER(float, LightHiddenPDFWeightForHistoryMiss) SHADER_PARAMETER(float, AreaLightHiddenPDFWeight) SHADER_PARAMETER(float, DirectionalLightSampleRatio) SHADER_PARAMETER(float, MinSampleClampingWeight) SHADER_PARAMETER_RDG_TEXTURE(Texture2D, ShadowMaskBits) SHADER_PARAMETER_RDG_TEXTURE(Texture2D, MegaLightsDepthHistory) SHADER_PARAMETER(FIntPoint, HistoryVisibleLightHashViewMinInTiles) SHADER_PARAMETER(FIntPoint, HistoryVisibleLightHashViewSizeInTiles) END_SHADER_PARAMETER_STRUCT() class FTileType : SHADER_PERMUTATION_INT("TILE_TYPE", (int32)MegaLights::ETileType::SHADING_MAX_SUBSTRATE); class FNumSamplesPerPixel1d : SHADER_PERMUTATION_SPARSE_INT("NUM_SAMPLES_PER_PIXEL_1D", 2, 4, 16); class FGuideByHistory : SHADER_PERMUTATION_BOOL("GUIDE_BY_HISTORY"); class FInputType : SHADER_PERMUTATION_INT("INPUT_TYPE", int32(EMegaLightsInput::Count)); class FDebugMode : SHADER_PERMUTATION_BOOL("DEBUG_MODE"); class FReferenceMode : SHADER_PERMUTATION_BOOL("REFERENCE_MODE"); class FHairComplexTransmittance: SHADER_PERMUTATION_BOOL("USE_HAIR_COMPLEX_TRANSMITTANCE"); using FPermutationDomain = TShaderPermutationDomain; static int32 GetGroupSize() { return 8; } static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters) { FPermutationDomain PermutationVector(Parameters.PermutationId); const EMegaLightsInput InputType = EMegaLightsInput(PermutationVector.Get()); if (MegaLights::GetShadingTileTypes(InputType).Find(PermutationVector.Get()) == INDEX_NONE) { return false; } // Hair complex transmittance is always enabled for hair input if (InputType == EMegaLightsInput::HairStrands && !PermutationVector.Get()) { return false; } // Hair complex transmittance is only enabled if: // * If Hair plugin is enabled // * For Complex tiles, as hair are only part of these type of tiles const MegaLights::ETileType TilType = (MegaLights::ETileType)PermutationVector.Get(); if (PermutationVector.Get() && (!IsHairStrandsSupported(EHairStrandsShaderType::All, Parameters.Platform) || !IsComplexTileType(TilType))) { return false; } if (PermutationVector.Get() && !MegaLights::ShouldCompileShadersForReferenceMode(Parameters.Platform)) { return false; } return MegaLights::ShouldCompileShaders(Parameters.Platform); } static EShaderPermutationPrecacheRequest ShouldPrecachePermutation(const FGlobalShaderPermutationParameters& Parameters) { FPermutationDomain PermutationVector(Parameters.PermutationId); // precache all tile types EMegaLightsInput InputType = EMegaLightsInput(PermutationVector.Get()); int NumSamplesPerPixel1d = PermutationVector.Get(); const FIntPoint NumSamplesPerPixel2d = MegaLights::GetNumSamplesPerPixel2d(InputType); if (NumSamplesPerPixel1d != (NumSamplesPerPixel2d.X * NumSamplesPerPixel2d.Y)) { return EShaderPermutationPrecacheRequest::NotUsed; } if (PermutationVector.Get()) { return EShaderPermutationPrecacheRequest::NotPrecached; } if (PermutationVector.Get()) { return EShaderPermutationPrecacheRequest::NotPrecached; } return EShaderPermutationPrecacheRequest::Precached; } static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment) { FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment); MegaLights::ModifyCompilationEnvironment(Parameters.Platform, OutEnvironment); OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE"), GetGroupSize()); FPermutationDomain PermutationVector(Parameters.PermutationId); const int32 NumSamplesPerPixel1d = PermutationVector.Get(); const FIntPoint NumSamplesPerPixel2d = MegaLights::GetNumSamplesPerPixel2d(NumSamplesPerPixel1d); OutEnvironment.SetDefine(TEXT("NUM_SAMPLES_PER_PIXEL_2D_X"), NumSamplesPerPixel2d.X); OutEnvironment.SetDefine(TEXT("NUM_SAMPLES_PER_PIXEL_2D_Y"), NumSamplesPerPixel2d.Y); if (IsMetalPlatform(Parameters.Platform)) { OutEnvironment.SetDefine(TEXT("FORCE_DISABLE_GLINTS_AA"), 1); // SUBSTRATE_TODO Temporary, while Metal compute does not have derivatives. } OutEnvironment.CompilerFlags.Add(CFLAG_WaveOperations); OutEnvironment.CompilerFlags.Add(CFLAG_Wave32); } }; IMPLEMENT_GLOBAL_SHADER(FGenerateLightSamplesCS, "/Engine/Private/MegaLights/MegaLightsSampling.usf", "GenerateLightSamplesCS", SF_Compute); class FVolumeGenerateLightSamplesCS : public FGlobalShader { DECLARE_GLOBAL_SHADER(FVolumeGenerateLightSamplesCS) SHADER_USE_PARAMETER_STRUCT(FVolumeGenerateLightSamplesCS, FGlobalShader) BEGIN_SHADER_PARAMETER_STRUCT(FParameters, ) SHADER_PARAMETER_STRUCT_INCLUDE(FMegaLightsParameters, MegaLightsParameters) SHADER_PARAMETER_STRUCT_INCLUDE(FMegaLightsVolumeParameters, MegaLightsVolumeParameters) SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer, VolumeVisibleLightHashHistory) SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture3D, RWVolumeLightSamples) SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture3D, RWVolumeLightSampleRays) SHADER_PARAMETER(FIntVector, HistoryVolumeVisibleLightHashViewSizeInTiles) SHADER_PARAMETER(FIntVector, VolumeVisibleLightHashTileSize) SHADER_PARAMETER(float, LightHiddenPDFWeight) SHADER_PARAMETER(float, LightHiddenPDFWeightForHistoryMiss) SHADER_PARAMETER(float, DirectionalLightSampleRatio) SHADER_PARAMETER(float, MinSampleClampingWeight) END_SHADER_PARAMETER_STRUCT() class FTranslucencyLightingVolume : SHADER_PERMUTATION_BOOL("TRANSLUCENCY_LIGHTING_VOLUME"); class FNumSamplesPerVoxel1d : SHADER_PERMUTATION_SPARSE_INT("NUM_SAMPLES_PER_VOXEL_1D", 2, 4); class FLightSoftFading : SHADER_PERMUTATION_BOOL("USE_LIGHT_SOFT_FADING"); class FUseLightFunctionAtlas : SHADER_PERMUTATION_BOOL("USE_LIGHT_FUNCTION_ATLAS"); class FGuideByHistory : SHADER_PERMUTATION_BOOL("GUIDE_BY_HISTORY"); class FDebugMode : SHADER_PERMUTATION_BOOL("DEBUG_MODE"); class FReferenceMode : SHADER_PERMUTATION_BOOL("REFERENCE_MODE"); using FPermutationDomain = TShaderPermutationDomain; static int32 GetGroupSize() { return 4; } static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters) { return MegaLights::ShouldCompileShaders(Parameters.Platform); } static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment) { FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment); MegaLights::ModifyCompilationEnvironment(Parameters.Platform, OutEnvironment); OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE"), GetGroupSize()); FPermutationDomain PermutationVector(Parameters.PermutationId); const int32 NumSamplesPerVoxel1d = PermutationVector.Get(); const FIntVector NumSamplesPerVoxel3d = MegaLights::GetNumSamplesPerVoxel3d(NumSamplesPerVoxel1d); OutEnvironment.SetDefine(TEXT("NUM_SAMPLES_PER_VOXEL_3D_X"), NumSamplesPerVoxel3d.X); OutEnvironment.SetDefine(TEXT("NUM_SAMPLES_PER_VOXEL_3D_Y"), NumSamplesPerVoxel3d.Y); OutEnvironment.SetDefine(TEXT("NUM_SAMPLES_PER_VOXEL_3D_Z"), NumSamplesPerVoxel3d.Z); OutEnvironment.CompilerFlags.Add(CFLAG_WaveOperations); OutEnvironment.CompilerFlags.Add(CFLAG_Wave32); OutEnvironment.CompilerFlags.Add(CFLAG_HLSL2021); } static EShaderPermutationPrecacheRequest ShouldPrecachePermutation(const FGlobalShaderPermutationParameters& Parameters) { FPermutationDomain PermutationVector(Parameters.PermutationId); if (PermutationVector.Get()) { return EShaderPermutationPrecacheRequest::NotPrecached; } if (PermutationVector.Get()) { return EShaderPermutationPrecacheRequest::NotPrecached; } return FGlobalShader::ShouldPrecachePermutation(Parameters); } }; IMPLEMENT_GLOBAL_SHADER(FVolumeGenerateLightSamplesCS, "/Engine/Private/MegaLights/MegaLightsVolumeSampling.usf", "VolumeGenerateLightSamplesCS", SF_Compute); class FClearLightSamplesCS : public FGlobalShader { DECLARE_GLOBAL_SHADER(FClearLightSamplesCS) SHADER_USE_PARAMETER_STRUCT(FClearLightSamplesCS, FGlobalShader) BEGIN_SHADER_PARAMETER_STRUCT(FParameters, ) RDG_BUFFER_ACCESS(IndirectArgs, ERHIAccess::IndirectArgs) SHADER_PARAMETER_STRUCT_INCLUDE(FMegaLightsParameters, MegaLightsParameters) SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, RWDownsampledSceneDepth) SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, RWDownsampledSceneWorldNormal) SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, RWLightSamples) SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, RWLightSampleRays) SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer, DownsampledTileAllocator) SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer, DownsampledTileData) END_SHADER_PARAMETER_STRUCT() class FDebugMode : SHADER_PERMUTATION_BOOL("DEBUG_MODE"); using FPermutationDomain = TShaderPermutationDomain; static int32 GetGroupSize() { return 8; } static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters) { return MegaLights::ShouldCompileShaders(Parameters.Platform); } static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment) { FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment); MegaLights::ModifyCompilationEnvironment(Parameters.Platform, OutEnvironment); OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE"), GetGroupSize()); } static EShaderPermutationPrecacheRequest ShouldPrecachePermutation(const FGlobalShaderPermutationParameters& Parameters) { FPermutationDomain PermutationVector(Parameters.PermutationId); if (PermutationVector.Get()) { return EShaderPermutationPrecacheRequest::NotPrecached; } return FGlobalShader::ShouldPrecachePermutation(Parameters); } }; IMPLEMENT_GLOBAL_SHADER(FClearLightSamplesCS, "/Engine/Private/MegaLights/MegaLightsSampling.usf", "ClearLightSamplesCS", SF_Compute); void FMegaLightsViewContext::GenerateSamples( FRDGTextureRef LightingChannelsTexture, uint32 ShadingPassIndex) { RDG_EVENT_SCOPE_CONDITIONAL(GraphBuilder, bReferenceMode, "Pass%d", ShadingPassIndex); const bool bDebugPass = bDebug && MegaLights::IsDebugEnabledForShadingPass(ShadingPassIndex, View.GetShaderPlatform()); MegaLightsParameters.MegaLightsStateFrameIndex = FirstPassStateFrameIndex + ShadingPassIndex; if (ShadingPassIndex > 0) { MegaLightsParameters.StochasticLightingStateFrameIndex = MegaLightsParameters.MegaLightsStateFrameIndex; } // Generate new candidate light samples { FRDGTextureUAVRef DownsampledSceneDepthUAV = GraphBuilder.CreateUAV(DownsampledSceneDepth, ERDGUnorderedAccessViewFlags::SkipBarrier); FRDGTextureUAVRef DownsampledSceneWorldNormalUAV = GraphBuilder.CreateUAV(DownsampledSceneWorldNormal, ERDGUnorderedAccessViewFlags::SkipBarrier); FRDGTextureUAVRef LightSamplesUAV = GraphBuilder.CreateUAV(LightSamples, ERDGUnorderedAccessViewFlags::SkipBarrier); FRDGTextureUAVRef LightSampleRaysUAV = GraphBuilder.CreateUAV(LightSampleRays, ERDGUnorderedAccessViewFlags::SkipBarrier); // Clear tiles which don't contain any lights or geometry { FClearLightSamplesCS::FParameters* PassParameters = GraphBuilder.AllocParameters(); PassParameters->IndirectArgs = DownsampledTileIndirectArgs; PassParameters->MegaLightsParameters = MegaLightsParameters; PassParameters->RWDownsampledSceneDepth = DownsampledSceneDepthUAV; PassParameters->RWDownsampledSceneWorldNormal = DownsampledSceneWorldNormalUAV; PassParameters->RWLightSamples = LightSamplesUAV; PassParameters->RWLightSampleRays = LightSampleRaysUAV; PassParameters->DownsampledTileAllocator = GraphBuilder.CreateSRV(DownsampledTileAllocator); PassParameters->DownsampledTileData = GraphBuilder.CreateSRV(DownsampledTileData); FClearLightSamplesCS::FPermutationDomain PermutationVector; PermutationVector.Set(bDebug); auto ComputeShader = View.ShaderMap->GetShader(PermutationVector); FComputeShaderUtils::AddPass( GraphBuilder, RDG_EVENT_NAME("ClearLightSamples"), ComputeShader, PassParameters, DownsampledTileIndirectArgs, (int32)MegaLights::ETileType::Empty * sizeof(FRHIDispatchIndirectParameters)); } const bool bVisualizeLightLoopIterations = VisualizeLightLoopIterationsMode == 2; const bool bHairComplexTransmittance = InputType == EMegaLightsInput::HairStrands || (View.HairCardsMeshElements.Num() && IsHairStrandsSupported(EHairStrandsShaderType::All, View.GetShaderPlatform())); for (const int32 ShadingTileType : ShadingTileTypes) { const MegaLights::ETileType TileType = (MegaLights::ETileType)ShadingTileType; if (!View.bLightGridHasRectLights && IsRectLightTileType(TileType)) { continue; } if (!View.bLightGridHasTexturedLights && IsTexturedLightTileType(TileType)) { continue; } const bool bIsComplexTile = MegaLights::IsComplexTileType(TileType); FGenerateLightSamplesCS::FParameters* PassParameters = GraphBuilder.AllocParameters(); PassParameters->IndirectArgs = DownsampledTileIndirectArgs; PassParameters->MegaLightsParameters = MegaLightsParameters; PassParameters->HistoryScreenParameters = HistoryScreenParameters; PassParameters->RWDownsampledSceneDepth = DownsampledSceneDepthUAV; PassParameters->RWDownsampledSceneWorldNormal = DownsampledSceneWorldNormalUAV; PassParameters->RWLightSamples = LightSamplesUAV; PassParameters->RWLightSampleRays = LightSampleRaysUAV; PassParameters->DownsampledTileAllocator = GraphBuilder.CreateSRV(DownsampledTileAllocator); PassParameters->DownsampledTileData = GraphBuilder.CreateSRV(DownsampledTileData); PassParameters->VisibleLightHashHistory = VisibleLightHashHistory != nullptr ? GraphBuilder.CreateSRV(VisibleLightHashHistory) : nullptr; PassParameters->VisibleLightMaskHashHistory = VisibleLightMaskHashHistory != nullptr ? GraphBuilder.CreateSRV(VisibleLightMaskHashHistory) : nullptr; PassParameters->bVisualizeLightLoopIterations = bVisualizeLightLoopIterations; PassParameters->LightHiddenPDFWeight = CVarMegaLightsGuideByHistoryLightHiddenWeight.GetValueOnRenderThread(); PassParameters->LightHiddenPDFWeightForHistoryMiss = CVarMegaLightsGuideByHistoryLightHiddenWeightForHistoryMiss.GetValueOnRenderThread(); PassParameters->AreaLightHiddenPDFWeight = bGuideAreaLightsByHistory ? CVarMegaLightsGuideByHistoryAreaLightHiddenWeight.GetValueOnRenderThread() : 1.0f; PassParameters->DirectionalLightSampleRatio = MegaLights::GetDirectionalLightSampleRatio(); PassParameters->MinSampleClampingWeight = CVarMegaLightsMinSampleClampingWeight.GetValueOnRenderThread(); PassParameters->MegaLightsDepthHistory = SceneDepthHistory; PassParameters->HistoryVisibleLightHashViewMinInTiles = HistoryVisibleLightHashViewMinInTiles; PassParameters->HistoryVisibleLightHashViewSizeInTiles = HistoryVisibleLightHashViewSizeInTiles; FGenerateLightSamplesCS::FPermutationDomain PermutationVector; PermutationVector.Set(ShadingTileType); PermutationVector.Set(NumSamplesPerPixel2d.X * NumSamplesPerPixel2d.Y); PermutationVector.Set(VisibleLightHashHistory != nullptr && SceneDepthHistory != nullptr); PermutationVector.Set(uint32(InputType)); PermutationVector.Set(bDebugPass || bVisualizeLightLoopIterations); PermutationVector.Set(bReferenceMode); PermutationVector.Set(bHairComplexTransmittance && bIsComplexTile); auto ComputeShader = View.ShaderMap->GetShader(PermutationVector); FComputeShaderUtils::AddPass( GraphBuilder, RDG_EVENT_NAME("GenerateSamples DownsampleFactor:%dx%d SamplesPerPixel:%dx%d TileType:%s", DownsampleFactor.X, DownsampleFactor.Y, NumSamplesPerPixel2d.X, NumSamplesPerPixel2d.Y, MegaLights::GetTileTypeString(TileType)), ComputeShader, PassParameters, DownsampledTileIndirectArgs, ShadingTileType * sizeof(FRHIDispatchIndirectParameters)); } } if (bVolumeEnabled) { VolumeLightSamples = GraphBuilder.CreateTexture( FRDGTextureDesc::Create3D(VolumeSampleBufferSize, PF_R32_UINT, FClearValueBinding::Black, TexCreate_ShaderResource | TexCreate_UAV | TexCreate_3DTiling), TEXT("MegaLights.Volume.LightSamples")); VolumeLightSampleRays = GraphBuilder.CreateTexture( FRDGTextureDesc::Create3D(VolumeSampleBufferSize, PF_R8_UINT, FClearValueBinding::Black, TexCreate_ShaderResource | TexCreate_UAV | TexCreate_3DTiling), TEXT("MegaLights.Volume.LightSampleRays")); // Generate new candidate light samples for the volume { FVolumeGenerateLightSamplesCS::FParameters* PassParameters = GraphBuilder.AllocParameters(); PassParameters->MegaLightsParameters = MegaLightsParameters; PassParameters->MegaLightsVolumeParameters = MegaLightsVolumeParameters; PassParameters->VolumeVisibleLightHashHistory = VolumeVisibleLightHashHistory != nullptr ? GraphBuilder.CreateSRV(VolumeVisibleLightHashHistory) : nullptr; PassParameters->RWVolumeLightSamples = GraphBuilder.CreateUAV(VolumeLightSamples); PassParameters->RWVolumeLightSampleRays = GraphBuilder.CreateUAV(VolumeLightSampleRays); PassParameters->HistoryVolumeVisibleLightHashViewSizeInTiles = HistoryVolumeVisibleLightHashViewSizeInTiles; PassParameters->VolumeVisibleLightHashTileSize = VolumeVisibleLightHashTileSize; PassParameters->LightHiddenPDFWeight = CVarMegaLightsGuideByHistoryLightHiddenWeight.GetValueOnRenderThread(); PassParameters->LightHiddenPDFWeightForHistoryMiss = CVarMegaLightsGuideByHistoryLightHiddenWeightForHistoryMiss.GetValueOnRenderThread(); PassParameters->DirectionalLightSampleRatio = MegaLights::GetDirectionalLightSampleRatio(); PassParameters->MinSampleClampingWeight = CVarMegaLightsMinSampleClampingWeight.GetValueOnRenderThread(); FVolumeGenerateLightSamplesCS::FPermutationDomain PermutationVector; PermutationVector.Set(false); PermutationVector.Set(NumSamplesPerVoxel3d.X * NumSamplesPerVoxel3d.Y * NumSamplesPerVoxel3d.Z); PermutationVector.Set(MegaLightsVolumeParameters.LightSoftFading > 0.0f); PermutationVector.Set(bUseLightFunctionAtlas && MegaLightsVolume::UsesLightFunction()); PermutationVector.Set(VolumeVisibleLightHashHistory != nullptr); PermutationVector.Set(bVolumeDebug); PermutationVector.Set(bReferenceMode); auto ComputeShader = View.ShaderMap->GetShader(PermutationVector); const FIntVector GroupCount = FComputeShaderUtils::GetGroupCount(VolumeDownsampledViewSize, FVolumeGenerateLightSamplesCS::GetGroupSize()); FComputeShaderUtils::AddPass( GraphBuilder, RDG_EVENT_NAME("VolumeGenerateSamples SamplesPerVoxel:%dx%dx%d", NumSamplesPerVoxel3d.X, NumSamplesPerVoxel3d.Y, NumSamplesPerVoxel3d.Z), ComputeShader, PassParameters, GroupCount); } } if (MegaLights::UseTranslucencyVolume() && bShouldRenderTranslucencyVolume && !bUnifiedVolume) { TranslucencyVolumeLightSamples.AddDefaulted(TVC_MAX); TranslucencyVolumeLightSampleRays.AddDefaulted(TVC_MAX); for (uint32 CascadeIndex = 0; CascadeIndex < TVC_MAX; ++CascadeIndex) { TranslucencyVolumeLightSamples[CascadeIndex] = GraphBuilder.CreateTexture( FRDGTextureDesc::Create3D(TranslucencyVolumeSampleBufferSize, PF_R32_UINT, FClearValueBinding::Black, TexCreate_ShaderResource | TexCreate_UAV | TexCreate_3DTiling), TEXT("MegaLights.TranslucencyVolume.LightSamples")); TranslucencyVolumeLightSampleRays[CascadeIndex] = GraphBuilder.CreateTexture( FRDGTextureDesc::Create3D(TranslucencyVolumeSampleBufferSize, PF_R8_UINT, FClearValueBinding::Black, TexCreate_ShaderResource | TexCreate_UAV | TexCreate_3DTiling), TEXT("MegaLights.TranslucencyVolume.LightSampleRays")); // Generate new candidate light samples for the Translucency Volume { FVolumeGenerateLightSamplesCS::FParameters* PassParameters = GraphBuilder.AllocParameters(); PassParameters->MegaLightsParameters = MegaLightsParameters; PassParameters->MegaLightsVolumeParameters = MegaLightsTranslucencyVolumeParameters; PassParameters->MegaLightsVolumeParameters.TranslucencyVolumeCascadeIndex = CascadeIndex; PassParameters->VolumeVisibleLightHashHistory = TranslucencyVolumeVisibleLightHashHistory[CascadeIndex] != nullptr ? GraphBuilder.CreateSRV(TranslucencyVolumeVisibleLightHashHistory[CascadeIndex]) : nullptr; PassParameters->RWVolumeLightSamples = GraphBuilder.CreateUAV(TranslucencyVolumeLightSamples[CascadeIndex]); PassParameters->RWVolumeLightSampleRays = GraphBuilder.CreateUAV(TranslucencyVolumeLightSampleRays[CascadeIndex]); PassParameters->HistoryVolumeVisibleLightHashViewSizeInTiles = HistoryTranslucencyVolumeVisibleLightHashSizeInTiles; PassParameters->VolumeVisibleLightHashTileSize = TranslucencyVolumeVisibleLightHashTileSize; PassParameters->DirectionalLightSampleRatio = MegaLights::GetDirectionalLightSampleRatio(); PassParameters->MinSampleClampingWeight = CVarMegaLightsMinSampleClampingWeight.GetValueOnRenderThread(); FVolumeGenerateLightSamplesCS::FPermutationDomain PermutationVector; PermutationVector.Set(true); PermutationVector.Set(NumSamplesPerTranslucencyVoxel3d.X * NumSamplesPerTranslucencyVoxel3d.Y * NumSamplesPerTranslucencyVoxel3d.Z); PermutationVector.Set(false); PermutationVector.Set(bUseLightFunctionAtlas && MegaLightsTranslucencyVolume::UsesLightFunction()); PermutationVector.Set(TranslucencyVolumeVisibleLightHashHistory[CascadeIndex] != nullptr); PermutationVector.Set(bTranslucencyVolumeDebug); PermutationVector.Set(bReferenceMode); auto ComputeShader = View.ShaderMap->GetShader(PermutationVector); const FIntVector GroupCount = FComputeShaderUtils::GetGroupCount(TranslucencyVolumeDownsampledBufferSize, FVolumeGenerateLightSamplesCS::GetGroupSize()); FComputeShaderUtils::AddPass( GraphBuilder, RDG_EVENT_NAME("TranslucencyVolumeGenerateSamples SamplesPerVoxel:%dx%dx%d", NumSamplesPerTranslucencyVoxel3d.X, NumSamplesPerTranslucencyVoxel3d.Y, NumSamplesPerTranslucencyVoxel3d.Z), ComputeShader, PassParameters, GroupCount); } } } bSamplesGenerated = true; }