514 lines
22 KiB
HLSL
514 lines
22 KiB
HLSL
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
#define USE_SUBSTRATE_FORWARD_LIGHTING_COMMON 1
|
|
#include "SubstrateLightingCommon.ush"
|
|
#include "../LightData.ush"
|
|
#include "../MobileLightingCommon.ush"
|
|
|
|
#define FORWARD_PER_PIXEL_SHADING (FORWARD_SHADING || TRANSLUCENCY_LIGHTING_SURFACE_FORWARDSHADING || MATERIAL_SHADINGMODEL_SINGLELAYERWATER)
|
|
|
|
// For debug or iteration purpose only
|
|
#ifndef SUBSTRATE_FORCE_SINGLE_BSDF
|
|
#define SUBSTRATE_FORCE_SINGLE_BSDF 1
|
|
#endif
|
|
|
|
// For debug or iteration purpose only
|
|
#ifndef SUBSTRATE_FORCE_SINGLE_LOCAL_LIGHT
|
|
#define SUBSTRATE_FORCE_SINGLE_LOCAL_LIGHT 0
|
|
#endif
|
|
|
|
// Forward declarations
|
|
void GetVolumeLightingNonDirectional(float4 AmbientLightingVector, float3 DiffuseColor, inout float3 InterpolatedLighting, out float4 VolumeLighting);
|
|
void GetVolumeLightingDirectional(float4 AmbientLightingVector, float3 DirectionalLightingVector, float3 WorldNormal, float3 DiffuseColor, float DirectionalLightingIntensity, inout float3 InterpolatedLighting, out float4 VolumeLighting);
|
|
|
|
float3 GetWorldBentNormalZero(in FMaterialPixelParameters MaterialParameters);
|
|
|
|
void GetPrecomputedIndirectLightingAndSkyLight(
|
|
VTPageTableResult LightmapVTPageTableResult,
|
|
FVertexFactoryInterpolantsVSToPS Interpolants,
|
|
bool bEvaluateBackface,
|
|
half3 DiffuseDir,
|
|
half3 SkyLightColor,
|
|
out half3 OutDiffuseIndirectLighting,
|
|
out half3 OutSubsurfaceIndirectLighting,
|
|
out half OutIndirectIrradiance,
|
|
out half3 OutWaterDiffuseIndirectLuminance);
|
|
|
|
// This code should map to GetForwardDirectLightingSplit
|
|
float3 SubstrateMobileForwardLighting(
|
|
uint EyeIndex,
|
|
float4 SvPosition,
|
|
FSubstrateIntegrationSettings Settings,
|
|
FMobileBasePassInterpolantsVSToPS BasePassInterpolants,
|
|
FVertexFactoryInterpolantsVSToPS Interpolants,
|
|
VTPageTableResult LightmapVTPageTableResult,
|
|
float3 VolumetricLightmapBrickTextureUVs,
|
|
FMaterialPixelParameters MaterialParameters,
|
|
float SceneDepth,
|
|
float2 ScreenUV,
|
|
FSubstratePixelHeader SubstratePixelHeader,
|
|
FSubstrateData SubstrateData,
|
|
inout float3 OutTransmittancePreCoverage,
|
|
inout float OutCoverage
|
|
)
|
|
{
|
|
const uint PrimitiveId = MaterialParameters.PrimitiveId;
|
|
const uint2 PixelPos = uint2(SvPosition.xy);
|
|
const float Dither = InterleavedGradientNoise(PixelPos, View.StateFrameIndexMod8);
|
|
const float3 AbsoluteWorldPosition = WSDemote(GetWorldPosition(MaterialParameters));
|
|
const float3 TranslatedWorldPosition = MaterialParameters.WorldPosition_CamRelative;
|
|
const float3 LightingPositionOffset = MaterialParameters.LightingPositionOffset;
|
|
const half4 PrecomputedShadowFactors = GetPrimaryPrecomputedShadowMask(LightmapVTPageTableResult, Interpolants, MaterialParameters);
|
|
float3 V = MaterialParameters.CameraVector;
|
|
|
|
float3 Color = 0;
|
|
OutCoverage = 0.0f;
|
|
OutTransmittancePreCoverage = 1.0f;
|
|
|
|
float SpecularScale = 1;
|
|
#if TRANSLUCENCY_ANY_VOLUMETRIC
|
|
// No specular on volumetric translucency lighting modes
|
|
SpecularScale = 0;
|
|
#endif
|
|
|
|
const uint PrimitiveLightingChannelMask = GetPrimitive_LightingChannelMask(PrimitiveId);
|
|
const float2 LocalPosition = SvPosition.xy - ResolvedView.ViewRectMin.xy;
|
|
const uint GridIndex = ComputeLightGridCellIndex(uint2(LocalPosition.x, LocalPosition.y), SvPosition.w, EyeIndex);
|
|
|
|
if (SubstratePixelHeader.SubstrateTree.BSDFCount > 0)
|
|
{
|
|
// Write Irradiance/AO data into header in order to be retrieve correctly during lighting
|
|
#if SUBSTRATE_INLINE_SHADING
|
|
HEADER_SETIRRADIANCE_AO(SubstratePixelHeader.State, SubstratePackIrradianceAndOcclusion(SubstratePixelHeader.IrradianceAO, 0));
|
|
#endif
|
|
|
|
// Update tree (coverage/transmittance/luminace weights)
|
|
SubstratePixelHeader.SubstrateUpdateTree(SubstrateData, V, Settings, OutCoverage, OutTransmittancePreCoverage);
|
|
|
|
//
|
|
// Forward lighting
|
|
//
|
|
//
|
|
#if SUBSTRATE_FORCE_SINGLE_BSDF
|
|
int BSDFIdx = 0;
|
|
#else
|
|
SUBSTRATE_UNROLL_N(SUBSTRATE_CLAMPED_CLOSURE_COUNT)
|
|
for (int BSDFIdx = 0; BSDFIdx < SubstratePixelHeader.SubstrateTree.BSDFCount; ++BSDFIdx)
|
|
#endif
|
|
{
|
|
#define CurrentBSDF SubstratePixelHeader.SubstrateTree.BSDFs[BSDFIdx]
|
|
|
|
if (SubstrateIsBSDFVisible(CurrentBSDF))
|
|
{
|
|
FSubstrateAddressing NullSubstrateAddressing = (FSubstrateAddressing)0; // Fake unused in SubstrateCreateBSDFContext when using Forward inline shading
|
|
// Starting with environment lighting, the context does not specify a light
|
|
FSubstrateBSDFContext SubstrateBSDFContext = SubstrateCreateBSDFContext(SubstratePixelHeader, CurrentBSDF, NullSubstrateAddressing, V);
|
|
|
|
////
|
|
//// Evaluate environment lighting
|
|
////
|
|
|
|
// Compute the bent normal from the BSDF normal
|
|
const float Roughness = SubstrateGetBSDFRoughness(CurrentBSDF);
|
|
const FShadingOcclusion ShadingOcclusion = ApplyBentNormal(MaterialParameters.CameraVector, SubstrateBSDFContext.N, GetWorldBentNormalZero(MaterialParameters), Roughness, SubstrateGetAO(SubstratePixelHeader));
|
|
float IndirectOcclusion = 1.0f;
|
|
half IndirectIrradiance = 0.0f;
|
|
half3 WaterDiffuseIndirectLuminance = 0.f;
|
|
|
|
// 1. Diffuse Sky evaluation using bent normal
|
|
if (UseBasePassSkylightDiffuse > 0)
|
|
{
|
|
// Update a context specific for environment lighting
|
|
FSubstrateBSDFContext EnvBSDFContext = SubstrateBSDFContext;
|
|
EnvBSDFContext.N = ShadingOcclusion.BentNormal;
|
|
EnvBSDFContext.SubstrateUpdateBSDFContext(EnvBSDFContext.L);
|
|
|
|
// And evaluate diffuse parameters
|
|
FSubstrateEnvLightResult SubstrateEnvLight = SubstrateEvaluateForEnvLight(EnvBSDFContext, false/*bEnableSpecular*/, Settings);
|
|
|
|
// Evaluate diffuse lighting
|
|
// Note: The evaluation is alway done for computing IndirectIrradiance, which is used for ImageBasedReflection evaluation
|
|
{
|
|
const float3 DiffuseNormal = SubstrateEnvLight.DiffuseNormal;
|
|
const float3 DiffuseColorForIndirect = SubstrateEnvLight.DiffuseWeight;
|
|
const float3 SubsurfaceColorForIndirect = SubstrateEnvLight.DiffuseBackFaceWeight;
|
|
|
|
const bool bEvaluateBackface = any(SubsurfaceColorForIndirect > 0.0);
|
|
|
|
const half NoL = max(0, dot(SubstrateBSDFContext.N, MobileDirectionalLight.DirectionalLightDirectionAndShadowTransition.xyz));
|
|
const bool bApplySkyLighting = !(MATERIAL_TWOSIDED && LQ_TEXTURE_LIGHTMAP) || NoL == 0;
|
|
|
|
half3 DiffuseIndirectLighting = 0.0f;
|
|
half3 SubsurfaceIndirectLighting = 0.0f;
|
|
GetPrecomputedIndirectLightingAndSkyLight(
|
|
LightmapVTPageTableResult,
|
|
Interpolants,
|
|
bEvaluateBackface,
|
|
DiffuseNormal,
|
|
ResolvedView.SkyLightColor.rgb,
|
|
DiffuseIndirectLighting,
|
|
SubsurfaceIndirectLighting,
|
|
IndirectIrradiance,
|
|
WaterDiffuseIndirectLuminance);
|
|
|
|
// SUBSTRATE_TODO: GetIndirectOcclusion require occlusion data, which are not available on mobile. The base pass has a
|
|
// AmbientOcclusionTexture which could be used, but it does not seems to be hooked for now
|
|
#if 0 && FORWARD_SHADING && (MATERIALBLENDING_SOLID || MATERIALBLENDING_MASKED)
|
|
float2 NearestResolvedDepthScreenUV = CalculateNearestResolvedDepthScreenUV(ScreenUV, MaterialParameters.ScreenPosition.w);
|
|
|
|
IndirectOcclusion = GetIndirectOcclusion(NearestResolvedDepthScreenUV, SubstratePixelHeader.HasDynamicIndirectShadowCasterRepresentation());
|
|
DiffuseIndirectLighting *= IndirectOcclusion;
|
|
SubsurfaceIndirectLighting *= IndirectOcclusion;
|
|
IndirectIrradiance *= IndirectOcclusion;
|
|
#endif
|
|
|
|
if (any((DiffuseColorForIndirect + SubsurfaceColorForIndirect) > 0.0f))
|
|
{
|
|
// For diffuse, we specify a perpendicular to the surface light direction for the transmittance to light to not be view dependent.
|
|
const float DiffuseEnvLightingNoL = 1.0f;
|
|
|
|
Color += (DiffuseIndirectLighting * DiffuseColorForIndirect + SubsurfaceIndirectLighting * SubsurfaceColorForIndirect) *
|
|
LuminanceWeight(DiffuseEnvLightingNoL, CurrentBSDF) * AOMultiBounce(SubstrateEnvLight.DiffuseColor, ShadingOcclusion.DiffOcclusion);
|
|
}
|
|
}
|
|
}
|
|
|
|
// 2. Specular evaluation (using regular normal)
|
|
#if (FORWARD_PER_PIXEL_SHADING || TRANSLUCENCY_LIGHTING_SURFACE_LIGHTINGVOLUME)
|
|
// Every components of forward shading reflection (Sky, SSR, Lumen) are enabled/disabled within GetImageBasedReflectionSpecular.
|
|
{
|
|
// Evaluate specular parameters without bent normal
|
|
FSubstrateEnvLightResult SubstrateEnvLight = SubstrateEvaluateForEnvLight(SubstrateBSDFContext, true /*bEnableSpecular*/, Settings);
|
|
|
|
// Evaluate specular lighting for the main lobe
|
|
if (any(SubstrateEnvLight.SpecularWeight > 0.0f))
|
|
{
|
|
Color += GetImageBasedReflectionSpecular(SubstrateEnvLight.SpecularDirection, SubstrateEnvLight.SpecularSafeRoughness, MaterialParameters.WorldPosition_CamRelative, SubstrateBSDFContext.N, ShadingOcclusion.SpecOcclusion, IndirectIrradiance, GridIndex) *
|
|
SubstrateEnvLight.SpecularWeight * IndirectOcclusion * LuminanceWeight(SubstrateBSDFContext, CurrentBSDF) * AOMultiBounce(SubstrateEnvLight.SpecularColor, ShadingOcclusion.SpecOcclusion);
|
|
}
|
|
// And for the second lobe if needed
|
|
if (any(SubstrateEnvLight.SpecularHazeWeight > 0.0f))
|
|
{
|
|
Color += GetImageBasedReflectionSpecular(SubstrateEnvLight.SpecularHazeDirection, SubstrateEnvLight.SpecularHazeSafeRoughness, MaterialParameters.WorldPosition_CamRelative, SubstrateBSDFContext.N, ShadingOcclusion.SpecOcclusion, IndirectIrradiance, GridIndex) *
|
|
SubstrateEnvLight.SpecularHazeWeight * IndirectOcclusion * LuminanceWeight(SubstrateBSDFContext, CurrentBSDF) * AOMultiBounce(SubstrateEnvLight.SpecularColor, ShadingOcclusion.SpecOcclusion);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
////
|
|
//// Evaluate translucent lighting volume / vertex lighting.
|
|
////
|
|
#define SUBSTRATE_TRANSLUCENCY_LIGHTING_VOLUMETRIC_DIRECTIONAL (TRANSLUCENCY_LIGHTING_VOLUMETRIC_PERVERTEX_DIRECTIONAL || TRANSLUCENCY_LIGHTING_VOLUMETRIC_DIRECTIONAL || TRANSLUCENCY_LIGHTING_SURFACE_LIGHTINGVOLUME)
|
|
#define SUBSTRATE_TRANSLUCENCY_LIGHTING_VOLUMETRIC_NONDIRECTIONAL (TRANSLUCENCY_LIGHTING_VOLUMETRIC_PERVERTEX_NONDIRECTIONAL || TRANSLUCENCY_LIGHTING_VOLUMETRIC_NONDIRECTIONAL)
|
|
|
|
#if SUBSTRATE_TRANSLUCENCY_LIGHTING_VOLUMETRIC_NONDIRECTIONAL || SUBSTRATE_TRANSLUCENCY_LIGHTING_VOLUMETRIC_DIRECTIONAL
|
|
float4 VolumeLighting = 0;
|
|
float3 InterpolatedLighting = 0;
|
|
FSubstrateEvaluateResult BSDFEvaluate = SubstrateEvaluateBSDF(SubstrateBSDFContext, Settings);
|
|
#endif
|
|
|
|
////
|
|
//// Evaluate emissive
|
|
////
|
|
Color += BSDF_GETEMISSIVE(CurrentBSDF) * CurrentBSDF.LuminanceWeightV;
|
|
|
|
////
|
|
//// Evaluate the single directional light selected for forward lighting.
|
|
////
|
|
const bool bHasDirectionalLight = any(MobileDirectionalLight.DirectionalLightColor.rgb > 0);
|
|
BRANCH
|
|
if (bHasDirectionalLight)
|
|
{
|
|
half DynamicShadowing = 1.0f;
|
|
half4 DynamicShadowFactors = 1.0f;
|
|
FDeferredLightData DirLightData = GetDirectionalLightData(MaterialParameters.ScreenPosition, SvPosition, DynamicShadowFactors, DynamicShadowing, EyeIndex);
|
|
half4 DirLightAttenuation = half4(1, 1, DynamicShadowing, DynamicShadowing);
|
|
uint DirLightingChannelMask = LIGHTING_CHANNEL_MASK;
|
|
float3 ToDirLight = DirLightData.Direction; // Already normalized
|
|
float DirLightMask = 1;
|
|
|
|
#if SUBSTRATE_TRANSLUCENT_MATERIAL
|
|
if (DirLightData.bAffectsTranslucentLighting > 0)
|
|
#endif
|
|
{
|
|
float DirectionalLightCloudShadow = 1.0f;
|
|
#if NEEDS_BASEPASS_CLOUD_SHADOW_INTERPOLATOR
|
|
DirectionalLightCloudShadow = BasePassInterpolants.VertexCloudShadow;
|
|
#endif
|
|
|
|
FTranslucencyLightingVector LightingVector = GetTranslucencyLightingVector(DirLightData, TranslatedWorldPosition);
|
|
#if SUBSTRATE_TRANSLUCENCY_LIGHTING_VOLUMETRIC_DIRECTIONAL
|
|
GetVolumeLightingDirectional(LightingVector.AmbientLightingVector, LightingVector.DirectionalLightingVector, SubstrateBSDFContext.N, BSDFEvaluate.DiffuseColor, GetMaterialTranslucencyDirectionalLightingIntensity(), InterpolatedLighting, VolumeLighting);
|
|
#elif SUBSTRATE_TRANSLUCENCY_LIGHTING_VOLUMETRIC_NONDIRECTIONAL
|
|
GetVolumeLightingNonDirectional(LightingVector.AmbientLightingVector, BSDFEvaluate.DiffuseColor, InterpolatedLighting, VolumeLighting);
|
|
#else
|
|
SubstrateBSDFContext.SubstrateUpdateBSDFContext(ToDirLight);
|
|
|
|
FSubstrateEvaluateResult BSDFEvaluate = (FSubstrateEvaluateResult)0;
|
|
Color += SubstrateForwardLightingCommon(
|
|
Dither,
|
|
Settings,
|
|
DirLightData,
|
|
ToDirLight,
|
|
DirLightMask,
|
|
DirLightAttenuation,
|
|
InitRectTexture(),
|
|
DirLightingChannelMask,
|
|
PrimitiveLightingChannelMask,
|
|
PrecomputedShadowFactors,
|
|
TranslatedWorldPosition,
|
|
SceneDepth,
|
|
LuminanceWeight(SubstrateBSDFContext, CurrentBSDF),
|
|
SubstratePixelHeader,
|
|
SubstrateBSDFContext,
|
|
BSDFEvaluate) * DirectionalLightCloudShadow;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
////
|
|
//// Evaluate local lights
|
|
////
|
|
#if MERGED_LOCAL_LIGHTS_MOBILE == 1
|
|
{
|
|
// Merged light data
|
|
FDeferredLightData LightData = (FDeferredLightData)0;
|
|
half3 LocalLightA = MobileSceneTextures.LocalLightTextureA.Load(int3(SvPosition.xy, 0)).xyz;
|
|
half4 LocalLightB = MobileSceneTextures.LocalLightTextureB.Load(int3(SvPosition.xy, 0));
|
|
|
|
LightData.SourceRadius = 0;
|
|
LightData.SourceLength = 0;
|
|
LightData.Tangent = 0;
|
|
LightData.SoftSourceRadius = 0;
|
|
LightData.SpecularScale = LocalLightB.a;
|
|
LightData.DiffuseScale = 1.f;
|
|
LightData.bSpotLight = false;
|
|
LightData.bRectLight = false;
|
|
LightData.Color = LocalLightA.rgb;
|
|
LightData.bRadialLight = false;
|
|
LightData.Direction = OctahedronToUnitVector(Pack888To1212(LocalLightB.rgb) * 2 - 1);
|
|
|
|
const half4 LightAttenuation = half4(1, 1, 1, 1);
|
|
const float SurfaceShadow = 0;
|
|
const uint LocalLightChannelMask = LIGHTING_CHANNEL_MASK;
|
|
|
|
const FRectTexture LocalRectTexture = ConvertToRectTexture(LightData);
|
|
|
|
float3 L = LightData.Direction; // Already normalized
|
|
float3 ToLight = L;
|
|
float LightMask = 1;
|
|
if (LightData.bRadialLight)
|
|
{
|
|
LightMask = GetLocalLightAttenuation(TranslatedWorldPosition, LightData, ToLight, L);
|
|
}
|
|
|
|
FTranslucencyLightingVector LightingVector = GetTranslucencyLightingVector(LightData, TranslatedWorldPosition);
|
|
#if SUBSTRATE_TRANSLUCENCY_LIGHTING_VOLUMETRIC_DIRECTIONAL
|
|
GetVolumeLightingDirectional(LightingVector.AmbientLightingVector, LightingVector.DirectionalLightingVector, SubstrateBSDFContext.N, BSDFEvaluate.DiffuseColor, GetMaterialTranslucencyDirectionalLightingIntensity(), InterpolatedLighting, VolumeLighting);
|
|
#elif SUBSTRATE_TRANSLUCENCY_LIGHTING_VOLUMETRIC_NONDIRECTIONAL
|
|
GetVolumeLightingNonDirectional(LightingVector.AmbientLightingVector, BSDFEvaluate.DiffuseColor, InterpolatedLighting, VolumeLighting);
|
|
#else
|
|
// Update the Substrate BSDF context accordgin to the new L
|
|
SubstrateBSDFContext.SubstrateUpdateBSDFContext(ToLight);
|
|
|
|
FSubstrateEvaluateResult BSDFEvaluate = (FSubstrateEvaluateResult)0;
|
|
Color += SubstrateForwardLightingCommon(
|
|
Dither,
|
|
Settings,
|
|
LightData,
|
|
ToLight,
|
|
LightMask,
|
|
LightAttenuation,
|
|
LocalRectTexture,
|
|
LocalLightChannelMask,
|
|
PrimitiveLightingChannelMask,
|
|
PrecomputedShadowFactors,
|
|
TranslatedWorldPosition,
|
|
SceneDepth,
|
|
LuminanceWeight(SubstrateBSDFContext, CurrentBSDF),
|
|
SubstratePixelHeader,
|
|
SubstrateBSDFContext,
|
|
BSDFEvaluate);
|
|
#endif
|
|
}
|
|
#elif MERGED_LOCAL_LIGHTS_MOBILE == 2
|
|
{
|
|
const FCulledLightsGridHeader CulledLightsGridHeader = GetCulledLightsGridHeader(GridIndex);
|
|
|
|
float3 MergedLightColor = uint3(0.f, 0.f , 0.f);
|
|
float3 MergedLightL = float3(0,0,0);
|
|
float MergedSpecularScale = 0.f;
|
|
float MergedTotalWeight = 0;
|
|
MergeLocalLights(CulledLightsGridHeader, MaterialParameters.WorldPosition_CamRelative, EyeIndex, false/*bSupportLightFunctions*/, MergedLightColor, MergedLightL, MergedSpecularScale, MergedTotalWeight, SubstrateBSDFContext.N);
|
|
|
|
if (MergedTotalWeight > 0.f)
|
|
{
|
|
MergedLightL = MergedLightL / MergedTotalWeight;
|
|
MergedSpecularScale = MergedSpecularScale / MergedTotalWeight;
|
|
|
|
FDeferredLightData LightData = (FDeferredLightData)0;
|
|
LightData.SourceRadius = 0;
|
|
LightData.SourceLength = 0;
|
|
LightData.Tangent = 0;
|
|
LightData.SoftSourceRadius = 0;
|
|
LightData.SpecularScale = MergedSpecularScale;
|
|
LightData.DiffuseScale = 1.f;
|
|
LightData.bSpotLight = false;
|
|
LightData.bRectLight = false;
|
|
LightData.Color = MergedLightColor;
|
|
LightData.bRadialLight = false;
|
|
LightData.Direction = MergedLightL;
|
|
|
|
const half4 LightAttenuation = half4(1, 1, 1, 1);
|
|
const float SurfaceShadow = 0;
|
|
const uint LocalLightChannelMask = LIGHTING_CHANNEL_MASK;
|
|
|
|
const FRectTexture LocalRectTexture = ConvertToRectTexture(LightData);
|
|
|
|
float3 L = LightData.Direction; // Already normalized
|
|
float3 ToLight = L;
|
|
float LightMask = 1;
|
|
if (LightData.bRadialLight)
|
|
{
|
|
LightMask = GetLocalLightAttenuation(TranslatedWorldPosition, LightData, ToLight, L);
|
|
}
|
|
|
|
FTranslucencyLightingVector LightingVector = GetTranslucencyLightingVector(LightData, TranslatedWorldPosition);
|
|
#if SUBSTRATE_TRANSLUCENCY_LIGHTING_VOLUMETRIC_DIRECTIONAL
|
|
GetVolumeLightingDirectional(LightingVector.AmbientLightingVector, LightingVector.DirectionalLightingVector, SubstrateBSDFContext.N, BSDFEvaluate.DiffuseColor, GetMaterialTranslucencyDirectionalLightingIntensity(), InterpolatedLighting, VolumeLighting);
|
|
#elif SUBSTRATE_TRANSLUCENCY_LIGHTING_VOLUMETRIC_NONDIRECTIONAL
|
|
GetVolumeLightingNonDirectional(LightingVector.AmbientLightingVector, BSDFEvaluate.DiffuseColor, InterpolatedLighting, VolumeLighting);
|
|
#else
|
|
// Update the Substrate BSDF context accordgin to the new L
|
|
SubstrateBSDFContext.SubstrateUpdateBSDFContext(ToLight);
|
|
|
|
FSubstrateEvaluateResult BSDFEvaluate = (FSubstrateEvaluateResult)0;
|
|
Color += SubstrateForwardLightingCommon(
|
|
Dither,
|
|
Settings,
|
|
LightData,
|
|
ToLight,
|
|
LightMask,
|
|
LightAttenuation,
|
|
LocalRectTexture,
|
|
LocalLightChannelMask,
|
|
PrimitiveLightingChannelMask,
|
|
PrecomputedShadowFactors,
|
|
TranslatedWorldPosition,
|
|
SceneDepth,
|
|
LuminanceWeight(SubstrateBSDFContext, CurrentBSDF),
|
|
SubstratePixelHeader,
|
|
SubstrateBSDFContext,
|
|
BSDFEvaluate);
|
|
#endif
|
|
}
|
|
}
|
|
#elif ENABLE_CLUSTERED_LIGHTS && !DISABLE_FORWARD_LOCAL_LIGHTS && (FORWARD_SHADING || TRANSLUCENCY_LIGHTING_SURFACE_FORWARDSHADING) // Forbidden for Single Layer Water
|
|
{
|
|
// Basic implementation for FORWARD_LOCAL_LIGHTS where local lights are reloaded per BSDF layer. It is fast by default when layer==1.
|
|
const FCulledLightsGridHeader CulledLightsGridHeader = GetCulledLightsGridHeader(GridIndex);
|
|
|
|
// Limit max to ForwardLightStruct.NumLocalLights.
|
|
// This prevents GPU hangs when the PS tries to read from uninitialized NumCulledLightsGrid buffer
|
|
const uint NumLightsInGridCell = min(CulledLightsGridHeader.NumLights, GetMaxLightsPerCell());
|
|
|
|
#if SUBSTRATE_FORCE_SINGLE_LOCAL_LIGHT
|
|
#define LOCAL_LIGHT_EARLY_OUT return Color;
|
|
uint GridLightListIndex = 0;
|
|
if (NumLightsInGridCell > 0)
|
|
#else
|
|
#define LOCAL_LIGHT_EARLY_OUT continue;
|
|
LOOP
|
|
for (uint GridLightListIndex = 0; GridLightListIndex < NumLightsInGridCell; GridLightListIndex++)
|
|
#endif
|
|
{
|
|
const FLocalLightData LocalLight = GetLocalLightDataFromGrid(CulledLightsGridHeader.DataStartIndex + GridLightListIndex, EyeIndex);
|
|
|
|
#if MATERIALBLENDING_ANY_TRANSLUCENT && !SUBSTRATE_FORCE_SINGLE_LOCAL_LIGHT
|
|
if(UnpackAffectsTranslucentLighting(LocalLight) == 0)
|
|
{
|
|
LOCAL_LIGHT_EARLY_OUT;
|
|
}
|
|
#endif
|
|
|
|
half4 PreviewShadowMapChannelMask = 1;
|
|
half4 DynamicShadowFactors = 1;
|
|
uint LocalLightChannelMask = LIGHTING_CHANNEL_MASK;
|
|
FDeferredLightData LightData = ConvertToDeferredLight_Mobile(LocalLight);
|
|
|
|
// Rect light optionally supported in forward.
|
|
// * This is not done explicitely in the legacy path (resulting in no lighting) but we do it for Substrate in order to avoid visual artefact.
|
|
// * This can be removed when LocalLight properly supports rect lights.
|
|
if (LightData.bRectLight && !SUPPORT_RECTLIGHT_ON_FORWARD_LIT_TRANSLUCENT)
|
|
{
|
|
LOCAL_LIGHT_EARLY_OUT;
|
|
}
|
|
|
|
// When disabled, force the compiler to remove the texture atlas sampling to avoid taking an extra texture sampler
|
|
#if !SUPPORT_RECTLIGHT_ON_FORWARD_LIT_TRANSLUCENT
|
|
LightData.bRectLight = false;
|
|
#endif
|
|
const FRectTexture LocalRectTexture = ConvertToRectTexture(LightData);
|
|
|
|
float DynamicShadowing = dot(PreviewShadowMapChannelMask, DynamicShadowFactors);
|
|
float4 LightAttenuation = float4(1, 1, DynamicShadowing.x, DynamicShadowing.x);
|
|
|
|
float3 L = LightData.Direction; // Already normalized
|
|
float3 ToLight = L;
|
|
float LightMask = 1;
|
|
if (LightData.bRadialLight)
|
|
{
|
|
LightMask = GetLocalLightAttenuation(TranslatedWorldPosition, LightData, ToLight, L);
|
|
}
|
|
|
|
if (!IsLightVisible(LocalLight, TranslatedWorldPosition))
|
|
{
|
|
LOCAL_LIGHT_EARLY_OUT;
|
|
}
|
|
|
|
FTranslucencyLightingVector LightingVector = GetTranslucencyLightingVector(LightData, TranslatedWorldPosition);
|
|
#if SUBSTRATE_TRANSLUCENCY_LIGHTING_VOLUMETRIC_DIRECTIONAL
|
|
GetVolumeLightingDirectional(LightingVector.AmbientLightingVector, LightingVector.DirectionalLightingVector, SubstrateBSDFContext.N, BSDFEvaluate.DiffuseColor, GetMaterialTranslucencyDirectionalLightingIntensity(), InterpolatedLighting, VolumeLighting);
|
|
#elif SUBSTRATE_TRANSLUCENCY_LIGHTING_VOLUMETRIC_NONDIRECTIONAL
|
|
GetVolumeLightingNonDirectional(LightingVector.AmbientLightingVector, BSDFEvaluate.DiffuseColor, InterpolatedLighting, VolumeLighting);
|
|
#else
|
|
// Update the Substrate BSDF context accordgin to the new L
|
|
SubstrateBSDFContext.SubstrateUpdateBSDFContext(ToLight);
|
|
|
|
FSubstrateEvaluateResult BSDFEvaluate = (FSubstrateEvaluateResult)0;
|
|
Color += SubstrateForwardLightingCommon(
|
|
Dither,
|
|
Settings,
|
|
LightData,
|
|
ToLight,
|
|
LightMask,
|
|
LightAttenuation,
|
|
LocalRectTexture,
|
|
LocalLightChannelMask,
|
|
PrimitiveLightingChannelMask,
|
|
PrecomputedShadowFactors,
|
|
TranslatedWorldPosition,
|
|
SceneDepth,
|
|
LuminanceWeight(SubstrateBSDFContext, CurrentBSDF),
|
|
SubstratePixelHeader,
|
|
SubstrateBSDFContext,
|
|
BSDFEvaluate);
|
|
#endif
|
|
}
|
|
#undef LOCAL_LIGHT_EARLY_OUT
|
|
}
|
|
#endif // !DISABLE_FORWARD_LOCAL_LIGHTS
|
|
|
|
}// SubstrateIsBSDFVisible
|
|
#undef CurrentBSDF
|
|
}
|
|
}
|
|
|
|
return Color;
|
|
}
|
|
|
|
|