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

103 lines
2.2 KiB
HLSL

// Copyright Epic Games, Inc. All Rights Reserved.
// Float R11G11B10 max
#define INVALID_LIGHTING half3(65024.0, 65024.0, 64512.0)
bool IsLightingValid(half3 V)
{
return !all(V == INVALID_LIGHTING);
}
half3 LumenRGBToYCoCg(half3 RGB)
{
half Y = dot(RGB, half3( 0.25, 0.5, 0.25));
half Co = dot(RGB, half3( 0.5, 0, -0.5));
half Cg = dot(RGB, half3(-0.25, 0.5, -0.25));
half3 YCoCg = half3(Y, Co, Cg);
return YCoCg;
}
half3 LumenYCoCgToRGB(half3 YCoCg)
{
half Y = YCoCg.x;
half Co = YCoCg.y;
half Cg = YCoCg.z;
half R = Y + Co - Cg;
half G = Y + Cg;
half B = Y - Co - Cg;
half3 RGB = half3(R, G, B);
return RGB;
}
float3 LumenRGBToYCoCgSafe(float3 RGB)
{
return IsLightingValid(RGB) ? LumenRGBToYCoCg(RGB) : INVALID_LIGHTING;
}
// [Moving Frostbite to Physically Based Rendering 3.0]
// Approximates factor in Lerp(N, R, factor) = dominant direction of a GGX lobe
float GetSpecularDominantDirFactor(float Roughness)
{
float S = saturate(1.0f - Roughness);
return S * (sqrt(S) + Roughness);
}
// [Moving Frostbite to Physically Based Rendering 3.0]
float GetSpecularLobeHalfAngle(float Roughness)
{
float E = 0.75f; // Percentage of preserved energy
float LobeHalfAngle = AtanFast((Pow2(Roughness) * E) / (1.0f - E));
return LobeHalfAngle;
}
float ReflectionsDenoiserOneOverTonemapRange;
float3 RGBToDenoiserSpace(float3 V)
{
if (IsLightingValid(V))
{
float Weight = 1.0f / (1.0f + Luminance(V) * ReflectionsDenoiserOneOverTonemapRange);
V = V * Weight;
}
return V;
}
float4 RGBAToDenoiserSpace(float4 V)
{
V.xyz = RGBToDenoiserSpace(V.xyz);
return V;
}
float3 DenoiserSpaceToRGB(float3 V)
{
if (IsLightingValid(V))
{
float InvWeight = 1.0f / (1.0f - Luminance(V) * ReflectionsDenoiserOneOverTonemapRange);
V = V * InvWeight;
}
return V;
}
half PackNumFramesAccumulated(half X)
{
// Assume UInt8 quantization
return X / 32.0 + 0.5 / 255.0;
}
half UnpackNumFramesAccumulated(half X)
{
return X * 32.0;
}
uint GetMaxFramesAccumulated(uint MaxFrames, float Roughness)
{
// Speedup accumulation for mirror reflections in order to reduce ghosting and other artifacts
// Mirror reflections don't need many samples to converge and can be mostly handled by TAA
MaxFrames = lerp(2, MaxFrames, saturate(Roughness / 0.05f));
return MaxFrames;
}