Files
UnrealEngine/Engine/Shaders/Private/Lumen/LumenSceneDirectLighting.usf
2025-05-18 13:04:45 +08:00

134 lines
4.8 KiB
HLSL

// Copyright Epic Games, Inc. All Rights Reserved.
#include "../Common.ush"
#include "LumenCardCommon.ush"
#include "LumenCardTile.ush"
#include "LumenCardTileShadowDownsampleFactor.ush"
#include "SurfaceCache/LumenSurfaceCache.ush"
#define SUPPORT_CONTACT_SHADOWS 0
#define USE_IES_PROFILE 1
#include "../DeferredLightingCommon.ush"
#include "../VolumeLightingCommon.ush"
#define FILTER_DIRECTIONAL_LIGHT_SHADOWING 1
#include "../ForwardShadowingCommon.ush"
#include "LumenSceneDirectLighting.ush"
#include "LumenFloatQuantization.ush"
FDeferredLightData GetLumenDirectLightingLightData(uint LightIndex, float3 PreViewTranslation, float Exposure)
{
FDeferredLightData Out;
#if USE_LIGHT_UNIFORM_BUFFER
Out = InitDeferredLightFromUniforms(LIGHT_TYPE);
#else
FLumenLight LumenLight = LoadLumenLight(LightIndex, PreViewTranslation, Exposure);
Out = LumenLight.DeferredLightData;
Out.bRectLight = HAS_RECT_LIGHTS && Out.bRectLight;
#endif
return Out;
}
float3 GetIrradianceForLight(
uint LightIndex,
FLumenSurfaceCacheData SurfaceCacheData,
float3 PreViewTranslation, // LUMEN_LWC_TODO
float Exposure,
float3 ShadowFactor)
{
FDeferredLightData LightData = GetLumenDirectLightingLightData(LightIndex, PreViewTranslation, Exposure);
float3 TranslatedWorldPosition = SurfaceCacheData.WorldPosition + PreViewTranslation;
return GetIrradianceForLight(LightData, SurfaceCacheData.WorldNormal, TranslatedWorldPosition, true /*bSupportRectLight*/) * ShadowFactor;
}
#ifndef HAS_MULTIPLE_VIEWS
#define HAS_MULTIPLE_VIEWS 0
#endif
RWTexture2D<float3> RWDirectLightingAtlas;
StructuredBuffer<uint> CardTiles;
StructuredBuffer<uint> LightTileOffsetNumPerCardTile;
StructuredBuffer<uint2> LightTilesPerCardTile;
float CachedLightingPreExposure;
#if WAVE_OP_WAVE_SIZE > 0 && COMPILER_SUPPORTS_WAVE_SIZE
WAVESIZE(WAVE_OP_WAVE_SIZE)
#endif
[numthreads(CARD_TILE_SIZE, CARD_TILE_SIZE, 1)]
void LumenCardBatchDirectLightingCS(
uint3 GroupId : SV_GroupID,
uint3 GroupThreadId : SV_GroupThreadID)
{
uint CardTileIndex = GroupId.x;
uint2 TexelCoordInTile = GroupThreadId.xy;
uint PackedOffsetNum = LightTileOffsetNumPerCardTile[CardTileIndex];
uint LightTilesOffset = BitFieldExtractU32(PackedOffsetNum, 24, 0);
uint NumLightTiles = BitFieldExtractU32(PackedOffsetNum, 8, 24);
FCardTileData CardTile = UnpackCardTileData(CardTiles[CardTileIndex]);
FLumenCardPageData CardPage = GetLumenCardPageData(CardTile.CardPageIndex);
uint2 CoordInCardPage = CARD_TILE_SIZE * CardTile.TileCoord + TexelCoordInTile;
uint2 AtlasCoord = CardPage.PhysicalAtlasCoord + CoordInCardPage;
float2 AtlasUV = CardPage.PhysicalAtlasUVRect.xy + CardPage.PhysicalAtlasUVTexelScale * (CoordInCardPage + 0.5);
float2 CardUV = CardPage.CardUVRect.xy + CardPage.CardUVTexelScale * (CoordInCardPage + 0.5);
FLumenCardData Card = GetLumenCardData(CardPage.CardIndex);
FLumenSurfaceCacheData SurfaceCacheData = GetSurfaceCacheData(Card, CardUV, AtlasUV);
if (NumLightTiles == 0 || !SurfaceCacheData.bValid)
{
RWDirectLightingAtlas[AtlasCoord] = 0;
return;
}
float3 Irradiance = 0.0f;
uint4 TileShadowDownsampleFactorLow = 0;
uint4 TileShadowDownsampleFactorHigh = 0;
for (uint CulledLightIndex = 0; CulledLightIndex < NumLightTiles; ++CulledLightIndex)
{
FLightTileForLightPass LightTile = UnpackLightTileForLightPass(LightTilesPerCardTile[LightTilesOffset + CulledLightIndex]);
FShadowMaskRay ShadowMaskRay;
ShadowMaskRay.bShadowFactorComplete = true;
ShadowMaskRay.ShadowFactor = 1.0f;
if (LightTile.ShadowMaskIndex != 0xffffffff)
{
ReadShadowMaskRay(LightTile.ShadowMaskIndex, TexelCoordInTile, ShadowMaskRay);
}
if (any(ShadowMaskRay.ShadowFactor > 0.0f))
{
uint ViewIndex = HAS_MULTIPLE_VIEWS ? LightTile.ViewIndex : 0;
const FDFVector3 PreViewTranslation = GetPreViewTranslation(ViewIndex);
Irradiance += GetIrradianceForLight(LightTile.LightIndex, SurfaceCacheData, DFHackToFloat(PreViewTranslation), ViewExposure[ViewIndex], ShadowMaskRay.ShadowFactor);
//Irradiance += bShadowFactorValid ? float3(0, 1, 0) : float3(0.2f, 0.0f, 0.0f);
}
#if WAVE_OP_WAVE_SIZE == 64
if (WaveActiveAllTrue(!IsVisibleToLight(ShadowMaskRay.ShadowFactor)) || WaveActiveAllTrue(IsVisibleToLight(ShadowMaskRay.ShadowFactor)))
{
SetLumenCardTileShadowDownsampleFactorForLight(TileShadowDownsampleFactorLow, TileShadowDownsampleFactorHigh, LightTile.LightIndex);
}
#elif WAVE_OP_WAVE_SIZE == 32
// TODO: add wave32 support
#endif
}
#if WAVE_OP_WAVE_SIZE == 64
if (WaveIsFirstLane())
#elif WAVE_OP_WAVE_SIZE == 32
// TODO: add wave32 support
#endif
{
WriteLumenCardTileShadowDownsampleFactor(TileShadowDownsampleFactorLow, TileShadowDownsampleFactorHigh, AtlasCoord / CARD_TILE_SIZE, LumenCardScene.PhysicalAtlasSize.x / CARD_TILE_SIZE);
}
RWDirectLightingAtlas[AtlasCoord] = QuantizeForFloatRenderTarget(Irradiance * CachedLightingPreExposure, int3(AtlasCoord, View.StateFrameIndexMod8 + 1));
}