Files
Brandyn / Techy fcc1b09210 init
2026-04-04 15:40:51 -05:00

516 lines
27 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "MegaLights.h"
#include "MegaLightsInternal.h"
#include "RendererPrivate.h"
#include "HairStrandsInterface.h"
static TAutoConsoleVariable<float> 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<float> 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<float> CVarMegaLightsGuideByHistoryLightHiddenWeight(
TEXT("r.MegaLights.GuideByHistory.LightHiddenWeight"),
0.1f,
TEXT("PDF weight scale for hidden lights."),
ECVF_Scalability | ECVF_RenderThreadSafe
);
static TAutoConsoleVariable<float> 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<float> 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<float>, RWDownsampledSceneDepth)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D<UNORM float3>, RWDownsampledSceneWorldNormal)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D<uint>, RWLightSamples)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D<uint>, RWLightSampleRays)
SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer<uint>, DownsampledTileAllocator)
SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer<uint>, DownsampledTileData)
SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer<uint>, VisibleLightHashHistory)
SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer<uint>, 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<float>, 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<FTileType, FNumSamplesPerPixel1d, FGuideByHistory, FInputType, FDebugMode, FReferenceMode, FHairComplexTransmittance>;
static int32 GetGroupSize()
{
return 8;
}
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
FPermutationDomain PermutationVector(Parameters.PermutationId);
const EMegaLightsInput InputType = EMegaLightsInput(PermutationVector.Get<FInputType>());
if (MegaLights::GetShadingTileTypes(InputType).Find(PermutationVector.Get<FTileType>()) == INDEX_NONE)
{
return false;
}
// Hair complex transmittance is always enabled for hair input
if (InputType == EMegaLightsInput::HairStrands && !PermutationVector.Get<FHairComplexTransmittance>())
{
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<FTileType>();
if (PermutationVector.Get<FHairComplexTransmittance>() &&
(!IsHairStrandsSupported(EHairStrandsShaderType::All, Parameters.Platform) || !IsComplexTileType(TilType)))
{
return false;
}
if (PermutationVector.Get<FReferenceMode>() && !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<FInputType>());
int NumSamplesPerPixel1d = PermutationVector.Get<FNumSamplesPerPixel1d>();
const FIntPoint NumSamplesPerPixel2d = MegaLights::GetNumSamplesPerPixel2d(InputType);
if (NumSamplesPerPixel1d != (NumSamplesPerPixel2d.X * NumSamplesPerPixel2d.Y))
{
return EShaderPermutationPrecacheRequest::NotUsed;
}
if (PermutationVector.Get<FDebugMode>())
{
return EShaderPermutationPrecacheRequest::NotPrecached;
}
if (PermutationVector.Get<FReferenceMode>())
{
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<FNumSamplesPerPixel1d>();
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<uint>, VolumeVisibleLightHashHistory)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture3D<uint>, RWVolumeLightSamples)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture3D<uint>, 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<FTranslucencyLightingVolume, FNumSamplesPerVoxel1d, FLightSoftFading, FUseLightFunctionAtlas, FGuideByHistory, FDebugMode, FReferenceMode>;
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<FNumSamplesPerVoxel1d>();
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<FDebugMode>())
{
return EShaderPermutationPrecacheRequest::NotPrecached;
}
if (PermutationVector.Get<FReferenceMode>())
{
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<float>, RWDownsampledSceneDepth)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D<UNORM float3>, RWDownsampledSceneWorldNormal)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D<uint>, RWLightSamples)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D<uint>, RWLightSampleRays)
SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer<uint>, DownsampledTileAllocator)
SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer<uint>, DownsampledTileData)
END_SHADER_PARAMETER_STRUCT()
class FDebugMode : SHADER_PERMUTATION_BOOL("DEBUG_MODE");
using FPermutationDomain = TShaderPermutationDomain<FDebugMode>;
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<FDebugMode>())
{
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<FClearLightSamplesCS::FParameters>();
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<FClearLightSamplesCS::FDebugMode>(bDebug);
auto ComputeShader = View.ShaderMap->GetShader<FClearLightSamplesCS>(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<FGenerateLightSamplesCS::FParameters>();
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<FGenerateLightSamplesCS::FTileType>(ShadingTileType);
PermutationVector.Set<FGenerateLightSamplesCS::FNumSamplesPerPixel1d>(NumSamplesPerPixel2d.X * NumSamplesPerPixel2d.Y);
PermutationVector.Set<FGenerateLightSamplesCS::FGuideByHistory>(VisibleLightHashHistory != nullptr && SceneDepthHistory != nullptr);
PermutationVector.Set<FGenerateLightSamplesCS::FInputType>(uint32(InputType));
PermutationVector.Set<FGenerateLightSamplesCS::FDebugMode>(bDebugPass || bVisualizeLightLoopIterations);
PermutationVector.Set<FGenerateLightSamplesCS::FReferenceMode>(bReferenceMode);
PermutationVector.Set<FGenerateLightSamplesCS::FHairComplexTransmittance>(bHairComplexTransmittance && bIsComplexTile);
auto ComputeShader = View.ShaderMap->GetShader<FGenerateLightSamplesCS>(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<FVolumeGenerateLightSamplesCS::FParameters>();
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<FVolumeGenerateLightSamplesCS::FTranslucencyLightingVolume>(false);
PermutationVector.Set<FVolumeGenerateLightSamplesCS::FNumSamplesPerVoxel1d>(NumSamplesPerVoxel3d.X * NumSamplesPerVoxel3d.Y * NumSamplesPerVoxel3d.Z);
PermutationVector.Set<FVolumeGenerateLightSamplesCS::FLightSoftFading>(MegaLightsVolumeParameters.LightSoftFading > 0.0f);
PermutationVector.Set<FVolumeGenerateLightSamplesCS::FUseLightFunctionAtlas>(bUseLightFunctionAtlas && MegaLightsVolume::UsesLightFunction());
PermutationVector.Set<FVolumeGenerateLightSamplesCS::FGuideByHistory>(VolumeVisibleLightHashHistory != nullptr);
PermutationVector.Set<FVolumeGenerateLightSamplesCS::FDebugMode>(bVolumeDebug);
PermutationVector.Set<FVolumeGenerateLightSamplesCS::FReferenceMode>(bReferenceMode);
auto ComputeShader = View.ShaderMap->GetShader<FVolumeGenerateLightSamplesCS>(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<FVolumeGenerateLightSamplesCS::FParameters>();
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<FVolumeGenerateLightSamplesCS::FTranslucencyLightingVolume>(true);
PermutationVector.Set<FVolumeGenerateLightSamplesCS::FNumSamplesPerVoxel1d>(NumSamplesPerTranslucencyVoxel3d.X * NumSamplesPerTranslucencyVoxel3d.Y * NumSamplesPerTranslucencyVoxel3d.Z);
PermutationVector.Set<FVolumeGenerateLightSamplesCS::FLightSoftFading >(false);
PermutationVector.Set<FVolumeGenerateLightSamplesCS::FUseLightFunctionAtlas>(bUseLightFunctionAtlas && MegaLightsTranslucencyVolume::UsesLightFunction());
PermutationVector.Set<FVolumeGenerateLightSamplesCS::FGuideByHistory>(TranslucencyVolumeVisibleLightHashHistory[CascadeIndex] != nullptr);
PermutationVector.Set<FVolumeGenerateLightSamplesCS::FDebugMode>(bTranslucencyVolumeDebug);
PermutationVector.Set<FVolumeGenerateLightSamplesCS::FReferenceMode>(bReferenceMode);
auto ComputeShader = View.ShaderMap->GetShader<FVolumeGenerateLightSamplesCS>(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;
}