Engine/Source/Runtime/Renderer/Private/Lumen/LumenSceneLighting.cpp
void Lumen::CombineLumenSceneLighting(
FScene* Scene,
const FViewInfo& View,
FRDGBuilder& GraphBuilder,
const FLumenCardTracingInputs& TracingInputs,
const FLumenCardUpdateContext& CardUpdateContext,
const FLumenCardTileUpdateContext& CardTileUpdateContext,
ERDGPassFlags ComputePassFlags)
{
LLM_SCOPE_BYTAG(Lumen);
FLumenSceneData& LumenSceneData = *Scene->GetLumenSceneData(View);
FLumenCardCombineLightingCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FLumenCardCombineLightingCS::FParameters>();
PassParameters->IndirectArgsBuffer = CardTileUpdateContext.DispatchCardTilesIndirectArgs;
PassParameters->View = View.ViewUniformBuffer;
PassParameters->LumenCardScene = TracingInputs.LumenCardSceneUniformBuffer;
PassParameters->DiffuseColorBoost = 1.0f / FMath::Max(View.FinalPostProcessSettings.LumenDiffuseColorBoost, 1.0f);
PassParameters->AlbedoAtlas = TracingInputs.AlbedoAtlas;
PassParameters->OpacityAtlas = TracingInputs.OpacityAtlas;
PassParameters->EmissiveAtlas = TracingInputs.EmissiveAtlas;
PassParameters->DirectLightingAtlas = TracingInputs.DirectLightingAtlas;
PassParameters->IndirectLightingAtlas = TracingInputs.IndirectLightingAtlas;
PassParameters->BilinearClampedSampler = TStaticSamplerState<SF_Bilinear, AM_Clamp, AM_Clamp, AM_Clamp>::GetRHI();
PassParameters->CardTiles = GraphBuilder.CreateSRV(CardTileUpdateContext.CardTiles);
PassParameters->RWFinalLightingAtlas = GraphBuilder.CreateUAV(TracingInputs.FinalLightingAtlas);
const FIntPoint IndirectLightingAtlasSize = LumenSceneData.GetRadiosityAtlasSize();
PassParameters->IndirectLightingAtlasHalfTexelSize = FVector2f(0.5f / IndirectLightingAtlasSize.X, 0.5f / IndirectLightingAtlasSize.Y);
auto ComputeShader = View.ShaderMap->GetShader<FLumenCardCombineLightingCS>();
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("CombineLighting CS"),
ComputePassFlags,
ComputeShader,
PassParameters,
CardTileUpdateContext.DispatchCardTilesIndirectArgs,
(uint32)ELumenDispatchCardTilesIndirectArgsOffset::OneGroupPerCardTile);
}
LumenSceneLighting.usf
SamplerState BilinearClampedSampler;
StructuredBuffer<uint> CardTiles;
RWTexture2D<float3> RWFinalLightingAtlas;
[numthreads( 8 , 8 , 1)]
void CombineLumenSceneLightingCS(
uint3 GroupId : SV_GroupID,
uint3 GroupThreadId : SV_GroupThreadID)
{
uint CardTileIndex = GroupId.x;
uint2 TexelCoordInTile = GroupThreadId.xy;
FCardTileData CardTile = UnpackCardTileData(CardTiles[CardTileIndex]);
FLumenCardPageData CardPage = GetLumenCardPageData(CardTile.CardPageIndex);
FLumenCardData Card = GetLumenCardData(CardPage.CardIndex);
uint2 CoordInCardPage = 8 * CardTile.TileCoord + TexelCoordInTile;
uint2 AtlasCoord = CardPage.PhysicalAtlasCoord + CoordInCardPage;
float2 AtlasUV = CardPage.PhysicalAtlasUVRect.xy + CardPage.PhysicalAtlasUVTexelScale * (CoordInCardPage + 0.5);
float2 IndirectLightingAtlasUV = AtlasUV;
float3 Albedo = Texture2DSampleLevel(AlbedoAtlas, BilinearClampedSampler, AtlasUV, 0).xyz;
float3 Emissive = Texture2DSampleLevel(EmissiveAtlas, BilinearClampedSampler, AtlasUV, 0).xyz;
float3 DirectLighting = Texture2DSampleLevel(DirectLightingAtlas, BilinearClampedSampler, AtlasUV, 0).xyz;
float3 IndirectLighting = Texture2DSampleLevel(IndirectLightingAtlas, BilinearClampedSampler, IndirectLightingAtlasUV, 0).xyz;
float3 FinalLighting = CombineFinalLighting(Albedo, Emissive, DirectLighting, IndirectLighting);
RWFinalLightingAtlas[AtlasCoord] = FinalLighting;
}
float3 CombineFinalLighting(float3 Albedo, float3 Emissive, float3 DirectLighting, float3 IndirectLighting)
{
Albedo = DecodeSurfaceCacheAlbedo(Albedo);
float3 FinalLighting = (DirectLighting + IndirectLighting) * Diffuse_Lambert(Albedo) + Emissive;
FinalLighting = max(MakeFinite(FinalLighting), float3(0.0f, 0.0f, 0.0f));
return FinalLighting;
}
float3 DecodeSurfaceCacheAlbedo(float3 EncodedAlbedo)
{
float3 Albedo = EncodedAlbedo * EncodedAlbedo;
Albedo = min(saturate(pow(Albedo, DiffuseColorBoost)), 0.99f);
return Albedo;
}