Files
UnrealEngine/Engine/Shaders/Private/MegaLights/MegaLightsShading.ush
Brandyn / Techy fcc1b09210 init
2026-04-04 15:40:51 -05:00

159 lines
5.6 KiB
HLSL

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
// Experimental - Stochastic lighting for Substrate
// Select and light stochastically a single Slab for material containing several layers
#define SUBSTRATE_STOCHASTIC_LIGHTING 0
#include "MegaLights.ush"
#include "MegaLightsMaterial.ush"
FDeferredLightingSplit GetMegaLightsSplitLighting(
float3 TranslatedWorldPosition,
float3 CameraVector,
FMegaLightsMaterial Material,
float AmbientOcclusion,
FDeferredLightData LightData,
float4 LightAttenuation,
float Dither,
uint2 ScreenCoord,
inout float SurfaceShadow)
#if SUBSTRATE_ENABLED && !INPUT_TYPE == INPUT_TYPE_HAIRSTRANDS
{
const uint2 PixelCoord = ScreenCoord;
FDeferredLightingSplit Out = (FDeferredLightingSplit)0;
#if SUBSTRATE_GBUFFER_FORMAT==1 && SUBSTRATE_LOAD_FROM_MATERIALCONTAINER
FSubstrateAddressing SubstrateAddressing = GetSubstratePixelDataByteOffset(PixelCoord, uint2(View.BufferSizeAndInvSize.xy), Substrate.MaxBytesPerPixel);
FSubstratePixelHeader SubstratePixelHeader = UnpackSubstrateHeaderIn(Substrate.MaterialTextureArray, SubstrateAddressing, Substrate.TopLayerTexture);
const bool bIsValid = SubstratePixelHeader.ClosureCount > 0;
#else
const bool bIsValid = Material.IsValid();
#endif
BRANCH
if (bIsValid)
{
float3 V = -CameraVector;
float3 L = LightData.Direction; // Already normalized
float3 ToLight = L;
float LightMask = 1;
if (LightData.bRadialLight)
{
LightMask = GetLocalLightAttenuation(TranslatedWorldPosition, LightData, ToLight, L);
#if ADAPTIVE_VOLUMETRIC_SHADOW_MAP
//LightAttenuation *= ComputeTransmittance(TranslatedWorldPosition, LightData.TranslatedWorldPosition, 256);
LightAttenuation *= AVSM_SampleTransmittance(TranslatedWorldPosition, LightData.TranslatedWorldPosition);
#endif // ADAPTIVE_VOLUMETRIC_SHADOW_MAP
}
if (LightMask > 0)
{
FSubstrateShadowTermInputParameters SubstrateShadowTermInputParameters = GetInitialisedSubstrateShadowTermInputParameters();
SubstrateShadowTermInputParameters.bEvaluateShadowTerm = true;
SubstrateShadowTermInputParameters.SceneDepth = Material.Depth;
SubstrateShadowTermInputParameters.PrecomputedShadowFactors = 1.f; //SubstrateReadPrecomputedShadowFactors(SubstratePixelHeader, PixelCoord, SceneTexturesStruct.GBufferETexture);
SubstrateShadowTermInputParameters.TranslatedWorldPosition = TranslatedWorldPosition;
SubstrateShadowTermInputParameters.LightAttenuation = LightAttenuation;
SubstrateShadowTermInputParameters.Dither = Dither;
// When using stochastic material selection,
// * Seek the selected closure
// * Force single closure evaluation
const bool bStochasticLighting = Substrate.bStochasticLighting > 0;
#if SUBSTRATE_STOCHASTIC_LIGHTING && SUBSTRATE_LOAD_FROM_MATERIALCONTAINER
if (bStochasticLighting)
{
#if SUBSTRATE_MATERIAL_CLOSURE_COUNT > 1
if (SubstratePixelHeader.ClosureCount > 1)
{
const uint AddressOffset = UnpackClosureOffsetAtIndex(Substrate.ClosureOffsetTexture[SubstrateAddressing.PixelCoords], Material.ClosureIndex, SubstratePixelHeader.ClosureCount);
SubstrateSeekClosure(SubstrateAddressing, AddressOffset);
}
#endif
SubstratePixelHeader.ClosureCount = 1;
}
#endif
FSubstrateDeferredLighting SubstrateLighting = SubstrateDeferredLighting(
LightData,
V,
L,
ToLight,
LightMask,
SubstrateShadowTermInputParameters,
#if SUBSTRATE_GBUFFER_FORMAT==1 && SUBSTRATE_LOAD_FROM_MATERIALCONTAINER
Substrate.MaterialTextureArray,
SubstrateAddressing,
SubstratePixelHeader
#else
Material.BSDF,
Material.BSDFTangentBasis,
Material.BSDFAO
#endif
);
// SUBSTRATE_TODO - Add support for SUBSTRATE_OPAQUE_ROUGH_REFRACTION_ENABLED
Out.DiffuseLighting = float4(SubstrateLighting.TotalDiffuseLighting, 0);
Out.SpecularLighting = float4(SubstrateLighting.TotalSpecularLighting, 0);
// SUBSTRATE_TODO - Accumulate Luminance separately
Out.LightingLuminance = Luminance(SubstrateLighting.TotalDiffuseLighting + SubstrateLighting.TotalSpecularLighting);
#if SUBSTRATE_STOCHASTIC_LIGHTING
// Account for the probability of having chosen this slab
if (bStochasticLighting)
{
const float InvPdf = 1.f / Material.PDF;
Out.DiffuseLighting *= InvPdf;
Out.SpecularLighting *= InvPdf;
Out.LightingLuminance *= InvPdf;
}
#endif
}
}
return Out;
}
#else // INPUT_TYPE == INPUT_TYPE_GBUFFER || INPUT_TYPE == INPUT_TYPE_HAIRSTRANDS
{
return GetDynamicLightingSplit(
TranslatedWorldPosition, CameraVector, Material.GBuffer, AmbientOcclusion,
LightData, LightAttenuation, Dither, ScreenCoord,
SurfaceShadow);
}
#endif // SUBSTRATE_ENABLED
#if INPUT_TYPE == INPUT_TYPE_HAIRSTRANDS
#include "../HairStrands/HairStrandsVisibilityCommon.ush"
#include "../HairStrands/HairStrandsVisibilityUtils.ush"
#include "../HairStrands/HairStrandsCommon.ush"
#include "../HairStrands/HairStrandsDeepTransmittanceCommon.ush"
#include "../HairStrands/HairStrandsDeepTransmittanceDualScattering.ush"
// Compute transmittance data from a transmittance mask
FHairTransmittanceData GetTransmittanceDataFromTransmitttanceMask(
FDeferredLightData LightData,
FMegaLightsMaterial Material,
FHairTransmittanceMask TransmittanceMask,
float3 TranslatedWorldPosition,
float3 CameraVector)
{
float3 L = LightData.Direction;
if (LightData.bRadialLight)
{
L = normalize(LightData.TranslatedWorldPosition - TranslatedWorldPosition);
}
const float3 V = normalize(-CameraVector);
return GetHairTransmittance(
V,
L,
Material.GBuffer,
TransmittanceMask,
View.HairScatteringLUTTexture,
HairScatteringLUTSampler,
View.HairComponents);
}
#endif