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

101 lines
2.9 KiB
HLSL

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "../LumenDiffuseColorBoost.ush"
struct FSurfaceCacheDepthData
{
bool bValid;
float Depth;
};
float EncodeSurfaceCacheDepth(float Depth, bool bValid)
{
// Reserve 1.0f for invalid pixels
float MaxValidDepth = float(0xFFFF - 1 - 0.5f) / float(0xFFFF);
Depth = min(Depth, MaxValidDepth);
return bValid ? Depth : 1.0f;
}
bool IsSurfaceCacheDepthValid(float Depth)
{
return Depth < 1.0f;
}
float3 DecodeSurfaceCacheCardSpaceNormal(float2 EncodedNormal)
{
float3 CardSpaceNormal;
CardSpaceNormal.xy = EncodedNormal.xy * 2.0f - 1.0f;
CardSpaceNormal.z = sqrt(max(1.0f - length2(CardSpaceNormal.xy), 0.0001f));
return CardSpaceNormal;
}
#ifdef LUMEN_CARD_DATA_STRIDE
float3 DecodeSurfaceCacheNormal(FLumenCardData Card, float2 EncodedNormal)
{
float3 CardSpaceNormal = DecodeSurfaceCacheCardSpaceNormal(EncodedNormal);
return normalize(mul(Card.WorldToLocalRotation, CardSpaceNormal));
}
#endif
float DiffuseColorBoost;
float3 DecodeSurfaceCacheAlbedo(float3 EncodedAlbedo)
{
float3 Albedo = ApplyDiffuseColorBoost(EncodedAlbedo * EncodedAlbedo, DiffuseColorBoost);
return Albedo;
}
float3 CombineFinalLighting(float3 Albedo, float3 Emissive, float3 DirectLighting, float3 IndirectLighting)
{
Albedo = DecodeSurfaceCacheAlbedo(Albedo);
float3 DiffuseLambert = Albedo * (1 / PI);
float3 FinalLighting = (DirectLighting + IndirectLighting) * DiffuseLambert + Emissive;
// Secure against strange values, as we are writing it to a persistent atlas with a feedback loop
FinalLighting = max(MakeFinite(FinalLighting), float3(0.0f, 0.0f, 0.0f));
return FinalLighting;
}
struct FLumenSurfaceCacheData
{
bool bValid;
float Depth;
float3 Albedo;
float3 Emissive;
// Derived
float3 WorldPosition;
float3 WorldNormal;
};
#ifdef LUMEN_CARD_DATA_STRIDE
FLumenSurfaceCacheData GetSurfaceCacheData(FLumenCardData Card, float2 CardUV, float2 AtlasUV)
{
float Depth = Texture2DSampleLevel(LumenCardScene.DepthAtlas, GlobalPointClampedSampler, AtlasUV, 0).x;
FLumenSurfaceCacheData SurfaceCacheData;
SurfaceCacheData.Depth = Depth;
SurfaceCacheData.bValid = IsSurfaceCacheDepthValid(Depth);
SurfaceCacheData.Albedo = float3(0.0f, 0.0f, 0.0f);
SurfaceCacheData.Emissive = float3(0.0f, 0.0f, 0.0f);
float2 NormalXY = float2(0.5f, 0.5f);
if (SurfaceCacheData.bValid)
{
SurfaceCacheData.Albedo = DecodeSurfaceCacheAlbedo(Texture2DSampleLevel(LumenCardScene.AlbedoAtlas, GlobalPointClampedSampler, AtlasUV, 0).xyz);
SurfaceCacheData.Emissive = Texture2DSampleLevel(LumenCardScene.EmissiveAtlas, GlobalPointClampedSampler, AtlasUV, 0).x;
NormalXY = Texture2DSampleLevel(LumenCardScene.NormalAtlas, GlobalPointClampedSampler, AtlasUV, 0).xy;
}
SurfaceCacheData.WorldNormal = DecodeSurfaceCacheNormal(Card, NormalXY);
SurfaceCacheData.WorldPosition = GetCardWorldPosition(Card, CardUV, SurfaceCacheData.Depth);
return SurfaceCacheData;
}
#endif