Files
UnrealEngine/Engine/Shaders/Private/LightData.ush
2025-05-18 13:04:45 +08:00

810 lines
27 KiB
HLSL

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "Common.ush"
#include "HairShadingCommon.ush" // Used for FHairTransmittanceData
#include "/Engine/Shared/LightViewData.h"
#include "/Engine/Shared/LightDefinitions.h"
///////////////////////////////////////////////////////////////////////////////////////////////////
// Defines
#define LIGHTING_CHANNEL_MASK 0x7
#define MAX_RECT_ATLAS_MIP 32
///////////////////////////////////////////////////////////////////////////////////////////////////
// Rect light texture data
struct FRectTexture
{
half2 AtlasUVOffset;
half2 AtlasUVScale;
half AtlasMaxLevel;
};
FRectTexture InitRectTexture()
{
FRectTexture Out;
Out.AtlasUVOffset = 0;
Out.AtlasUVScale = 0;
Out.AtlasMaxLevel = MAX_RECT_ATLAS_MIP;
return Out;
}
struct FRectLightData
{
float BarnCosAngle;
float BarnLength;
FRectTexture AtlasData;
};
FRectLightData UnpackRectLightData(uint In0, uint In1, uint In2)
{
FRectLightData Out;
Out.AtlasData.AtlasUVOffset = half2(f16tof32(In0 & 0xFFFF), f16tof32(In0 >> 16));
Out.AtlasData.AtlasUVScale = half2(f16tof32(In1 & 0xFFFF), f16tof32(In1 >> 16));
Out.BarnLength = f16tof32(In2 & 0xFFFF); // 16 bits
Out.BarnCosAngle = UnpackUnorm10(In2 >> 16); // 10 bits
Out.AtlasData.AtlasMaxLevel = half(In2 >> 26); // 6 bits
return Out;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Directional light data
struct FDirectionalLightData
{
uint HasDirectionalLight;
uint DirectionalLightSceneInfoExtraDataPacked;
float2 DirectionalLightDistanceFadeMAD;
float3 DirectionalLightColor;
float3 DirectionalLightDirection;
float DirectionalLightSourceRadius;
float DirectionalLightSoftSourceRadius;
float DirectionalLightSpecularScale;
float DirectionalLightDiffuseScale;
uint LightFunctionAtlasLightIndex;
uint bAffectsTranslucentLighting;
};
///////////////////////////////////////////////////////////////////////////////////////////////////
// Forward light data
struct FForwardLightData
{
// Raw value form light buffers
float4 LightPositionAndInvRadius;
float4 LightColorAndIdAndFalloffExponent;
float4 SpotAnglesAndSourceRadiusPacked;
float4 LightDirectionAndSceneInfoExtraDataPacked;
float4 LightTangentAndIESDataAndSpecularScale;
float3 RectData;
// Derived terms after unpacking
/** Virtual shadow map ID or INDEX_NONE if not present.*/
int VirtualShadowMapId;
/** Previous frame LocalLightIndex or INDEX_NONE if not present.*/
int PrevLocalLightIndex;
/** Index into GPUScene lights */
int LightSceneId;
};
///////////////////////////////////////////////////////////////////////////////////////////////////
// Helper struct to provide type safety when loading lights from the Light Grid
// Local lights can optimize bRadialLight=true
struct FLocalLightData
{
FForwardLightData Internal;
#if !COMPILER_SUPPORTS_HLSL2021
uint Unused; // necessary to avoid ambiguity with struct FForwardLightData
#endif
};
///////////////////////////////////////////////////////////////////////////////////////////////////
// Simple light data
/** Data about a single light to be shaded with the simple shading model, designed for speed and limited feature set. */
struct FSimpleDeferredLightData
{
float3 TranslatedWorldPosition;
float InvRadius;
float3 Color;
float FalloffExponent;
/** Whether to use inverse squared falloff. */
bool bInverseSquared;
};
///////////////////////////////////////////////////////////////////////////////////////////////////
// Light-weight light data - Used for raytracing/VSM/Lumen/...
// Mirrors FLightShaderParameters on C++ side.
struct FLightShaderParameters
{
float3 TranslatedWorldPosition;
float InvRadius;
float3 Color;
float FalloffExponent;
float3 Direction;
float3 Tangent;
float2 SpotAngles;
float SpecularScale;
float DiffuseScale;
float SourceRadius;
float SoftSourceRadius;
float SourceLength;
float RectLightBarnCosAngle;
float RectLightBarnLength;
float2 RectLightAtlasUVOffset;
float2 RectLightAtlasUVScale;
float RectLightAtlasMaxLevel;
float IESAtlasIndex;
uint LightFunctionAtlasLightIndex;
uint bAffectsTranslucentLighting;
};
///////////////////////////////////////////////////////////////////////////////////////////////////
// Heavy light data - used for deferred lighting functions
/**
* Data about a single light.
* Putting the light data in this struct allows the same lighting code to be used between standard deferred,
* Where many light properties are known at compile time, and tiled deferred, where all light properties have to be fetched from a buffer.
*/
// TODO: inherit or compose FLightShaderParameters
struct FDeferredLightData
{
float3 TranslatedWorldPosition;
half InvRadius;
/** Premultiplied with light brightness, can be huge. Do not use half precision here */
float3 Color;
half FalloffExponent;
float3 Direction;
float3 Tangent;
float SoftSourceRadius;
half2 SpotAngles;
float SourceRadius;
float SourceLength;
half SpecularScale;
half DiffuseScale;
float ContactShadowLength;
/** Intensity of shadow-casting contact shadows */
float ContactShadowCastingIntensity;
/** Intensity of non-shadow-casting contact shadows */
float ContactShadowNonCastingIntensity;
float2 DistanceFadeMAD;
half4 ShadowMapChannelMask;
/** Whether ContactShadowLength is in World Space or in Screen Space. */
bool ContactShadowLengthInWS;
/** Whether to use inverse squared falloff. */
bool bInverseSquared;
/** Whether this is a light with radial attenuation, aka point or spot light. */
bool bRadialLight;
/** Whether this light needs spotlight attenuation. */
bool bSpotLight;
bool bRectLight;
/** Whether the light should apply shadowing. */
uint ShadowedBits;
/** Rect light data. */
FRectLightData RectLightData;
/** IES data. */
float IESAtlasIndex;
// Light function atlas index
uint LightFunctionAtlasLightIndex;
/** Hair transmittance data. */
FHairTransmittanceData HairTransmittance;
// Wether the light affect translucent materials or not
uint bAffectsTranslucentLighting;
};
///////////////////////////////////////////////////////////////////////////////////////////////////
// Pack/unpack function related to light structures
float3 UnpackLightTranslatedWorldPosition(FForwardLightData In)
{
return In.LightPositionAndInvRadius.xyz;
}
float3 UnpackLightTranslatedWorldPosition(FLocalLightData In)
{
return UnpackLightTranslatedWorldPosition(In.Internal);
}
float UnpackLightInvRadius(FForwardLightData In)
{
return In.LightPositionAndInvRadius.w;
}
float UnpackLightInvRadius(FLocalLightData In)
{
return UnpackLightInvRadius(In.Internal);
}
float3 UnpackLightDirection(FForwardLightData In)
{
return In.LightDirectionAndSceneInfoExtraDataPacked.xyz;
}
float3 UnpackLightDirection(FLocalLightData In)
{
return UnpackLightDirection(In.Internal);
}
uint UnpackLightSceneInfoExtraDataPacked(FForwardLightData In)
{
return asuint(In.LightDirectionAndSceneInfoExtraDataPacked.w);
}
uint UnpackLightSceneInfoExtraDataPacked(FLocalLightData In)
{
return UnpackLightSceneInfoExtraDataPacked(In.Internal);
}
float3 UnpackLightColor(float2 In)
{
float3 Dir = float3(
((asuint(In.y) >> 0) & 0x3FF),
((asuint(In.y) >> 10) & 0x3FF),
((asuint(In.y) >> 20) & 0x3FF));
return In.x * Dir;
}
float3 UnpackLightColor(FForwardLightData In)
{
return UnpackLightColor(In.LightColorAndIdAndFalloffExponent.xy);
}
float3 UnpackLightColor(FLocalLightData In)
{
return UnpackLightColor(In.Internal);
}
float UnpackLightFalloffExponent(FForwardLightData In)
{
return In.LightColorAndIdAndFalloffExponent.w;
}
float UnpackLightFalloffExponent(FLocalLightData In)
{
return UnpackLightFalloffExponent(In.Internal);
}
float4 UnpackShadowMapChannelMask(uint In)
{
// 8 ALU
return float4((In & 0x1), (In & 0x2) >> 1, (In & 0x4) >> 2, (In & 0x8) >> 3);
}
uint UnpackLightingChannelMask(uint In)
{
return (In >> 8) & LIGHTING_CHANNEL_MASK;
}
uint UnpackLightingChannelMask(FForwardLightData In)
{
const uint LightSceneInfoExtraDataPacked = asuint(In.LightDirectionAndSceneInfoExtraDataPacked.w);
return UnpackLightingChannelMask(LightSceneInfoExtraDataPacked);
}
uint UnpackLightingChannelMask(FLocalLightData In)
{
return UnpackLightingChannelMask(In.Internal);
}
uint UnpackLightType(uint InLightSceneInfoExtraDataPacked)
{
return (InLightSceneInfoExtraDataPacked >> 16) & 0x3;
}
bool UnpackCastShadow(uint InLightSceneInfoExtraDataPacked)
{
return ((InLightSceneInfoExtraDataPacked >> 18) & 0x1) != 0;
}
bool UnpackCastVolumetricShadow(uint InLightSceneInfoExtraDataPacked)
{
return ((InLightSceneInfoExtraDataPacked >> 31) & 0x1) != 0;
}
bool UnpackCastShadow(FForwardLightData In)
{
const uint LightSceneInfoExtraDataPacked = asuint(In.LightDirectionAndSceneInfoExtraDataPacked.w);
return UnpackCastShadow(LightSceneInfoExtraDataPacked);
}
bool UnpackCastVolumetricShadow(FForwardLightData In)
{
const uint LightSceneInfoExtraDataPacked = asuint(In.LightDirectionAndSceneInfoExtraDataPacked.w);
return UnpackCastVolumetricShadow(LightSceneInfoExtraDataPacked);
}
bool UnpackCastShadow(FLocalLightData In)
{
return UnpackCastShadow(In.Internal);
}
bool UnpackHasLightFunction(uint InLightSceneInfoExtraDataPacked)
{
return ((InLightSceneInfoExtraDataPacked >> 19) & 0x1) != 0;
}
bool UnpackHasLightFunction(FForwardLightData In)
{
const uint LightSceneInfoExtraDataPacked = asuint(In.LightDirectionAndSceneInfoExtraDataPacked.w);
return UnpackHasLightFunction(LightSceneInfoExtraDataPacked);
}
bool UnpackHasLightFunction(FLocalLightData In)
{
return UnpackHasLightFunction(In.Internal);
}
uint UnpackLightFunctionAtlasIndex(uint InLightSceneInfoExtraDataPacked)
{
return ((InLightSceneInfoExtraDataPacked >> 20) & 0xFF);
}
uint UnpackLightFunctionAtlasIndex(FForwardLightData In)
{
const uint LightSceneInfoExtraDataPacked = asuint(In.LightDirectionAndSceneInfoExtraDataPacked.w);
return UnpackLightFunctionAtlasIndex(LightSceneInfoExtraDataPacked);
}
uint UnpackLightFunctionAtlasIndex(FLocalLightData In)
{
return UnpackLightFunctionAtlasIndex(In.Internal);
}
uint UnpackAffectsTranslucentLighting(uint InLightSceneInfoExtraDataPacked)
{
return ((InLightSceneInfoExtraDataPacked >> 28) & 0x1);
}
uint UnpackAffectsTranslucentLighting(FForwardLightData In)
{
const uint LightSceneInfoExtraDataPacked = asuint(In.LightDirectionAndSceneInfoExtraDataPacked.w);
return UnpackAffectsTranslucentLighting(LightSceneInfoExtraDataPacked);
}
uint UnpackAffectsTranslucentLighting(FLocalLightData In)
{
return UnpackAffectsTranslucentLighting(In.Internal);
}
uint UnpackIsHandledByMegaLights(uint InLightSceneInfoExtraDataPacked)
{
return ((InLightSceneInfoExtraDataPacked >> 29) & 0x1);
}
uint UnpackIsHandledByMegaLights(FForwardLightData In)
{
const uint LightSceneInfoExtraDataPacked = asuint(In.LightDirectionAndSceneInfoExtraDataPacked.w);
return UnpackIsHandledByMegaLights(LightSceneInfoExtraDataPacked);
}
uint UnpackIsHandledByMegaLights(FLocalLightData In)
{
return UnpackIsHandledByMegaLights(In.Internal);
}
uint UnpackIsClusteredDeferredSupported(uint InLightSceneInfoExtraDataPacked)
{
return ((InLightSceneInfoExtraDataPacked >> 30) & 0x1);
}
uint UnpackIsClusteredDeferredSupported(FForwardLightData In)
{
const uint LightSceneInfoExtraDataPacked = asuint(In.LightDirectionAndSceneInfoExtraDataPacked.w);
return UnpackIsClusteredDeferredSupported(LightSceneInfoExtraDataPacked);
}
uint UnpackIsClusteredDeferredSupported(FLocalLightData In)
{
return UnpackIsClusteredDeferredSupported(In.Internal);
}
float UnpackVolumetricScatteringIntensity(FForwardLightData In)
{
return f16tof32(asuint(In.SpotAnglesAndSourceRadiusPacked.w) >> 16);
}
float UnpackVolumetricScatteringIntensity(FLocalLightData In)
{
return UnpackVolumetricScatteringIntensity(In.Internal);
}
float UnpackLightSourceRadius(FForwardLightData In)
{
return f16tof32(asuint(In.SpotAnglesAndSourceRadiusPacked.z) & 0xFFFF);
}
float UnpackLightSourceRadius(FLocalLightData In)
{
return UnpackLightSourceRadius(In.Internal);
}
float UnpackLightSoftSourceRadius(FForwardLightData In)
{
return f16tof32(asuint(In.SpotAnglesAndSourceRadiusPacked.z) >> 16);
}
float UnpackLightSoftSourceRadius(FLocalLightData In)
{
return UnpackLightSoftSourceRadius(In.Internal);
}
float UnpackLightSourceLength(FForwardLightData In)
{
return f16tof32(asuint(In.SpotAnglesAndSourceRadiusPacked.w));
}
float UnpackLightSourceLength(FLocalLightData In)
{
return UnpackLightSourceLength(In.Internal);
}
float GetLightSourceRadius(FForwardLightData In)
{
return UnpackLightSourceRadius(In);
}
float GetLightSourceRadius(FLocalLightData In)
{
return GetLightSourceRadius(In.Internal);
}
float2 GetLightSpotAngles(FForwardLightData In)
{
return In.SpotAnglesAndSourceRadiusPacked.xy;
}
float2 GetLightSpotAngles(FLocalLightData In)
{
return GetLightSpotAngles(In.Internal);
}
float UnpackLightSpecularScale(FForwardLightData In)
{
return UnpackUnorm10(asuint(In.LightTangentAndIESDataAndSpecularScale.w));
}
float UnpackLightSpecularScale(FLocalLightData In)
{
return UnpackLightSpecularScale(In.Internal);
}
float UnpackLightDiffuseScale(FForwardLightData In)
{
return UnpackUnorm10(asuint(In.LightTangentAndIESDataAndSpecularScale.w)>>10);
}
float UnpackLightDiffuseScale(FLocalLightData In)
{
return UnpackLightDiffuseScale(In.Internal);
}
float UnpackLigthIESAtlasIndex(FForwardLightData In)
{
// Offset IESAtlasIndex here in order to preserve INDEX_NONE = -1 after encoding
return int(asuint(In.LightTangentAndIESDataAndSpecularScale.w) >> 20) - 1;
}
float UnpackLigthIESAtlasIndex(FLocalLightData In)
{
return UnpackLigthIESAtlasIndex(In.Internal);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Conversion functions
FRectTexture ConvertToRectTexture(FDeferredLightData In)
{
FRectTexture Output;
Output.AtlasUVOffset = In.RectLightData.AtlasData.AtlasUVOffset;
Output.AtlasUVScale = In.RectLightData.AtlasData.AtlasUVScale;
Output.AtlasMaxLevel = In.RectLightData.AtlasData.AtlasMaxLevel;
return Output;
}
// Helper function for converting FForwardLightData into FDeferredLightData
FDeferredLightData ConvertToDeferredLight(
const FForwardLightData In,
float InSpecularScale,
inout half4 OutPreviewShadowMapChannelMask,
inout uint OutLightingChannelMask)
{
FDeferredLightData Out = (FDeferredLightData)0;
const uint LightSceneInfoExtraDataPacked = asuint(In.LightDirectionAndSceneInfoExtraDataPacked.w);
const uint LightType = UnpackLightType(LightSceneInfoExtraDataPacked);
Out.TranslatedWorldPosition = In.LightPositionAndInvRadius.xyz;
Out.InvRadius = In.LightPositionAndInvRadius.w;
Out.Color = UnpackLightColor(In.LightColorAndIdAndFalloffExponent.xy);
Out.FalloffExponent = In.LightColorAndIdAndFalloffExponent.w;
Out.Direction = In.LightDirectionAndSceneInfoExtraDataPacked.xyz;
Out.SpotAngles = GetLightSpotAngles(In);
Out.SourceRadius = UnpackLightSourceRadius(In);
Out.SourceLength = UnpackLightSourceLength(In);
Out.Tangent = In.LightTangentAndIESDataAndSpecularScale.xyz;
Out.SoftSourceRadius = UnpackLightSoftSourceRadius(In);
Out.bInverseSquared = Out.FalloffExponent == 0 && (LightType != LIGHT_TYPE_DIRECTIONAL); // Directional lights don't use 'inverse squared attenuation'
Out.SpecularScale = UnpackLightSpecularScale(In) * InSpecularScale;
Out.DiffuseScale = UnpackLightDiffuseScale(In);
Out.bRadialLight = LightType != LIGHT_TYPE_DIRECTIONAL;
Out.bSpotLight = LightType == LIGHT_TYPE_SPOT;
Out.bRectLight = LightType == LIGHT_TYPE_RECT;
Out.HairTransmittance = InitHairTransmittanceData();
Out.RectLightData = UnpackRectLightData(
asuint(In.RectData.x),
asuint(In.RectData.y),
asuint(In.RectData.z));
Out.IESAtlasIndex = UnpackLigthIESAtlasIndex(In);
Out.LightFunctionAtlasLightIndex = UnpackLightFunctionAtlasIndex(In);
Out.bAffectsTranslucentLighting = UnpackAffectsTranslucentLighting(In);
// Shadow
// * Static shadowing uses ShadowMapChannel,
// * Dynamic shadows are packed into light attenuation using PreviewShadowMapChannel
// Data Layout on [10:0] with:
// * ShadowMapChannelMask = [3:0]
// * PreviewShadowMapChannel= [7:4]
// * LightincChannelMask = [8:10]
Out.ShadowedBits = (LightSceneInfoExtraDataPacked & 0xFF) != 0 ? 1 : 0;
Out.ShadowMapChannelMask = UnpackShadowMapChannelMask(LightSceneInfoExtraDataPacked);
OutPreviewShadowMapChannelMask = UnpackShadowMapChannelMask(LightSceneInfoExtraDataPacked >> 4);
OutLightingChannelMask = UnpackLightingChannelMask(LightSceneInfoExtraDataPacked);
return Out;
}
FDeferredLightData ConvertToDeferredLight(
const FLocalLightData In,
float InSpecularScale,
inout half4 OutPreviewShadowMapChannelMask,
inout uint OutLightingChannelMask)
{
FDeferredLightData DeferredLightData = ConvertToDeferredLight(In.Internal, InSpecularScale, OutPreviewShadowMapChannelMask, OutLightingChannelMask);
DeferredLightData.bRadialLight = true;
DeferredLightData.bInverseSquared = DeferredLightData.FalloffExponent == 0;
return DeferredLightData;
}
FDeferredLightData ConvertToDeferredLight(const FForwardLightData In)
{
half4 OutPreviewShadowMapChannelMask = 0;
uint OutLightingChannelMask = LIGHTING_CHANNEL_MASK;
return ConvertToDeferredLight(In, 1.0f, OutPreviewShadowMapChannelMask, OutLightingChannelMask);
}
FDeferredLightData ConvertToDeferredLight(const FLocalLightData In)
{
half4 OutPreviewShadowMapChannelMask = 0;
uint OutLightingChannelMask = LIGHTING_CHANNEL_MASK;
return ConvertToDeferredLight(In, 1.0f, OutPreviewShadowMapChannelMask, OutLightingChannelMask);
}
FDeferredLightData ConvertToDeferredLight_Mobile(const FLocalLightData In)
{
half4 OutPreviewShadowMapChannelMask = 0;
uint OutLightingChannelMask = LIGHTING_CHANNEL_MASK;
FDeferredLightData Out = ConvertToDeferredLight(In, 1.0f, OutPreviewShadowMapChannelMask, OutLightingChannelMask);
// Override value for performance on mobile
Out.SoftSourceRadius= 0;
Out.SpecularScale = 1.0f; // If enabled -> UnpackLightSpecularScale(In);
Out.DiffuseScale = 1.0f; // If enabled -> UnpackLightDiffuseScale(In);
#if RECT_LIGHT_AS_SPOTLIGHT
// Render RectLight approximately as SpotLight
Out.bSpotLight = Out.bSpotLight || Out.bRectLight;
Out.bRectLight = false;
#endif
BRANCH
if (!Out.bRectLight)
{
Out.SourceRadius = 0;
Out.SourceLength = 0;
Out.Tangent = 0;
}
return Out;
}
FLightShaderParameters ConvertToLightShaderParameters(FDeferredLightData In)
{
FLightShaderParameters Out;
Out.TranslatedWorldPosition = In.TranslatedWorldPosition;
Out.InvRadius = In.InvRadius;
Out.Color = In.Color;
Out.FalloffExponent = In.FalloffExponent;
Out.Direction = In.Direction;
Out.Tangent = In.Tangent;
Out.SpotAngles = In.SpotAngles;
Out.SpecularScale = 1;
Out.DiffuseScale = 1;
Out.SourceRadius = In.SourceRadius;
Out.SoftSourceRadius = In.SoftSourceRadius;
Out.SourceLength = In.SourceLength;
Out.RectLightBarnCosAngle = In.RectLightData.BarnCosAngle;
Out.RectLightBarnLength = In.RectLightData.BarnLength;
Out.RectLightAtlasUVOffset = In.RectLightData.AtlasData.AtlasUVOffset;
Out.RectLightAtlasUVScale = In.RectLightData.AtlasData.AtlasUVScale;
Out.RectLightAtlasMaxLevel = In.RectLightData.AtlasData.AtlasMaxLevel;
return Out;
}
FLightShaderParameters ConvertFromForward(const FForwardLightData In)
{
FLightShaderParameters Out = (FLightShaderParameters)0;
Out.TranslatedWorldPosition = In.LightPositionAndInvRadius.xyz;
Out.InvRadius = In.LightPositionAndInvRadius.w;
Out.Color = UnpackLightColor(In.LightColorAndIdAndFalloffExponent.xy);
Out.FalloffExponent = In.LightColorAndIdAndFalloffExponent.w;
Out.Direction = In.LightDirectionAndSceneInfoExtraDataPacked.xyz;
Out.Tangent = In.LightTangentAndIESDataAndSpecularScale.xyz;
Out.SpotAngles = GetLightSpotAngles(In);
Out.SpecularScale = UnpackLightSpecularScale(In);
Out.DiffuseScale = UnpackLightDiffuseScale(In);
Out.IESAtlasIndex = UnpackLigthIESAtlasIndex(In);
Out.SourceRadius = UnpackLightSourceRadius(In);
Out.SoftSourceRadius = UnpackLightSoftSourceRadius(In);
Out.SourceLength = UnpackLightSourceLength(In);
Out.LightFunctionAtlasLightIndex = UnpackLightFunctionAtlasIndex(In);
Out.bAffectsTranslucentLighting = UnpackAffectsTranslucentLighting(In);
const FRectLightData RectLightData = UnpackRectLightData(
asuint(In.RectData.x),
asuint(In.RectData.y),
asuint(In.RectData.z));
Out.RectLightBarnCosAngle = RectLightData.BarnCosAngle;
Out.RectLightBarnLength = RectLightData.BarnLength;
Out.RectLightAtlasUVOffset = RectLightData.AtlasData.AtlasUVOffset;
Out.RectLightAtlasUVScale = RectLightData.AtlasData.AtlasUVScale;
Out.RectLightAtlasMaxLevel = RectLightData.AtlasData.AtlasMaxLevel;
return Out;
}
FLightShaderParameters ConvertFromLocal(const FLocalLightData In)
{
return ConvertFromForward(In.Internal);
}
// Helper function for converting FDirectionalLightData into FDeferredLightData
FDeferredLightData ConvertToDeferredLight(
FDirectionalLightData In,
float InSpecularScale,
inout half4 OutPreviewShadowMapChannelMask,
inout uint OutLightingChannelMask)
{
FDeferredLightData Out = (FDeferredLightData)0;
Out.Color = In.DirectionalLightColor;
Out.FalloffExponent = 0;
Out.Direction = In.DirectionalLightDirection;
Out.DistanceFadeMAD = In.DirectionalLightDistanceFadeMAD;
Out.bRadialLight = false;
Out.SpecularScale = In.DirectionalLightSpecularScale * InSpecularScale;
Out.DiffuseScale = In.DirectionalLightDiffuseScale;
Out.ShadowedBits = (In.DirectionalLightSceneInfoExtraDataPacked & 0xFF) != 0 ? 1 : 0;
Out.HairTransmittance = InitHairTransmittanceData();
Out.SourceRadius = In.DirectionalLightSourceRadius;
Out.SoftSourceRadius = In.DirectionalLightSoftSourceRadius;
Out.IESAtlasIndex = -1;
Out.LightFunctionAtlasLightIndex = In.LightFunctionAtlasLightIndex;
Out.bAffectsTranslucentLighting = In.bAffectsTranslucentLighting;
// Shadow
// * Static shadowing uses ShadowMapChannel,
// * Dynamic shadows are packed into light attenuation using PreviewShadowMapChannel
// Data Layout on [10:0] with:
// * ShadowMapChannelMask = [3:0]
// * PreviewShadowMapChannel= [7:4]
// * LightincChannelMask = [8:10]
Out.ShadowMapChannelMask = UnpackShadowMapChannelMask(In.DirectionalLightSceneInfoExtraDataPacked);
OutPreviewShadowMapChannelMask = UnpackShadowMapChannelMask(In.DirectionalLightSceneInfoExtraDataPacked >> 4);
OutLightingChannelMask = UnpackLightingChannelMask(In.DirectionalLightSceneInfoExtraDataPacked);
return Out;
}
// Helper function for converting FLightSceneData into FDeferredLightData
FDeferredLightData ConvertToDeferredLight(FLightSceneData In, FLightViewData InViewData)
{
FDeferredLightData Out = (FDeferredLightData)0;
const uint LightType = UnpackLightType(InViewData.LightSceneInfoExtraDataPacked);
Out.TranslatedWorldPosition = InViewData.TranslatedWorldPosition;
Out.InvRadius = In.InvRadius;
Out.Color = InViewData.Color;
Out.FalloffExponent = In.FalloffExponent;
Out.Direction = In.Direction;
Out.SpotAngles = In.SpotAngles;
Out.SourceRadius = In.SourceRadius;
Out.SourceLength = In.SourceLength;
Out.Tangent = In.Tangent;
Out.SoftSourceRadius = In.SoftSourceRadius;
Out.bInverseSquared = In.FalloffExponent == 0 && (LightType != LIGHT_TYPE_DIRECTIONAL); // Directional lights don't use 'inverse squared attenuation'
Out.SpecularScale = In.SpecularScale;
Out.DiffuseScale = In.DiffuseScale;
Out.bRadialLight = LightType != LIGHT_TYPE_DIRECTIONAL;
Out.bSpotLight = LightType == LIGHT_TYPE_SPOT;
Out.bRectLight = LightType == LIGHT_TYPE_RECT;
Out.HairTransmittance = InitHairTransmittanceData();
Out.RectLightData.BarnCosAngle = In.RectLightBarnCosAngle;
Out.RectLightData.BarnLength = In.RectLightBarnLength;
Out.RectLightData.AtlasData.AtlasMaxLevel = InViewData.RectLightAtlasMaxLevel;
Out.RectLightData.AtlasData.AtlasUVOffset = InViewData.RectLightAtlasUVOffset;
Out.RectLightData.AtlasData.AtlasUVScale = InViewData.RectLightAtlasUVScale;
Out.IESAtlasIndex = InViewData.IESAtlasIndex;
Out.LightFunctionAtlasLightIndex = UnpackLightFunctionAtlasIndex(InViewData.LightSceneInfoExtraDataPacked);
Out.bAffectsTranslucentLighting = UnpackAffectsTranslucentLighting(InViewData.LightSceneInfoExtraDataPacked);
// Shadow
// * Static shadowing uses ShadowMapChannel,
// * Dynamic shadows are packed into light attenuation using PreviewShadowMapChannel
// Data Layout on [10:0] with:
// * ShadowMapChannelMask = [3:0]
// * PreviewShadowMapChannel= [7:4]
// * LightingChannelMask = [8:10]
Out.ShadowedBits = (InViewData.LightSceneInfoExtraDataPacked & 0xFF) != 0 ? 1 : 0;
Out.ShadowMapChannelMask = UnpackShadowMapChannelMask(InViewData.LightSceneInfoExtraDataPacked);
return Out;
}
// Helper function for converting FLightSceneData into FLightShaderParameters
FLightShaderParameters ConvertToLightShaderParameters(FLightSceneData In, FLightViewData InViewData)
{
FLightShaderParameters Out;
Out.TranslatedWorldPosition = DFFastAddDemote(In.WorldPosition, PrimaryView.PreViewTranslation);
Out.InvRadius = In.InvRadius;
Out.Color = InViewData.Color;
Out.FalloffExponent = In.FalloffExponent;
Out.Direction = In.Direction;
Out.Tangent = In.Tangent;
Out.SpotAngles = In.SpotAngles;
Out.SpecularScale = 1.0f; // In.SpecularScale;
Out.DiffuseScale = In.DiffuseScale;
Out.SourceRadius = In.SourceRadius;
Out.SoftSourceRadius = In.SoftSourceRadius;
Out.SourceLength = In.SourceLength;
Out.RectLightBarnCosAngle = In.RectLightBarnCosAngle;
Out.RectLightBarnLength = In.RectLightBarnLength;
Out.RectLightAtlasUVOffset = InViewData.RectLightAtlasUVOffset;
Out.RectLightAtlasUVScale = InViewData.RectLightAtlasUVScale;
Out.RectLightAtlasMaxLevel = InViewData.RectLightAtlasMaxLevel;
return Out;
}
// Helper function for converting FLocalLightData into FSimpleDeferredLightData
FSimpleDeferredLightData ConvertToSimpleLight(FLocalLightData In)
{
FSimpleDeferredLightData Out = (FSimpleDeferredLightData)0;
Out.TranslatedWorldPosition = In.Internal.LightPositionAndInvRadius.xyz;
Out.InvRadius = In.Internal.LightPositionAndInvRadius.w;
Out.Color = UnpackLightColor(In.Internal.LightColorAndIdAndFalloffExponent.xy);
Out.FalloffExponent = In.Internal.LightColorAndIdAndFalloffExponent.w;
Out.bInverseSquared = Out.FalloffExponent == 0;
return Out;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Helper functions
// Return true if the point is influenced by the light
bool IsLightVisible(FForwardLightData InLight, float3 TranslatedWorldPosition)
{
float InvLightRadiusSq = InLight.LightPositionAndInvRadius.w * InLight.LightPositionAndInvRadius.w;
return length2(TranslatedWorldPosition - InLight.LightPositionAndInvRadius.xyz) * InvLightRadiusSq <= 1.0f;
}
bool IsLightVisible(FLocalLightData InLight, float3 TranslatedWorldPosition)
{
return IsLightVisible(InLight.Internal, TranslatedWorldPosition);
}