128 lines
4.4 KiB
HLSL
128 lines
4.4 KiB
HLSL
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
#ifdef NUM_SAMPLES_PER_VOXEL_1D
|
|
#define NUM_SAMPLES_1D NUM_SAMPLES_PER_VOXEL_1D
|
|
#endif
|
|
|
|
#ifdef NUM_SAMPLES_PER_PIXEL_1D
|
|
#define NUM_SAMPLES_1D NUM_SAMPLES_PER_PIXEL_1D
|
|
#endif
|
|
|
|
struct FCandidateLightSample
|
|
{
|
|
uint LocalLightIndex;
|
|
bool bLightWasVisible;
|
|
float Weight;
|
|
};
|
|
|
|
FCandidateLightSample InitCandidateLightSample()
|
|
{
|
|
FCandidateLightSample LightSample;
|
|
LightSample.LocalLightIndex = MAX_LOCAL_LIGHT_INDEX;
|
|
LightSample.bLightWasVisible = true;
|
|
LightSample.Weight = 0.0f;
|
|
return LightSample;
|
|
}
|
|
|
|
uint PackCandidateLightSample(FCandidateLightSample LightSample)
|
|
{
|
|
uint PackedSample = LightSample.LocalLightIndex & 0xFFFF;
|
|
// Weights are always positive, so reuse the sign bit
|
|
PackedSample |= (f32tof16(LightSample.Weight) & 0x7FFF) << 16;
|
|
PackedSample |= LightSample.bLightWasVisible ? (1U << 31) : 0U;
|
|
return PackedSample;
|
|
}
|
|
|
|
FCandidateLightSample UnpackCandidateLightSample(uint PackedSample)
|
|
{
|
|
FCandidateLightSample LightSample;
|
|
LightSample.LocalLightIndex = PackedSample & 0xFFFF;
|
|
LightSample.bLightWasVisible = (PackedSample & (1U << 31)) != 0;
|
|
LightSample.Weight = f16tof32((PackedSample >> 16) & 0x7FFF);
|
|
return LightSample;
|
|
}
|
|
|
|
struct FLightSampler
|
|
{
|
|
uint PackedSamples[NUM_SAMPLES_1D];
|
|
float LightIndexRandom[NUM_SAMPLES_1D];
|
|
float WeightSum;
|
|
};
|
|
|
|
FLightSampler InitLightSampler(float RandomScalar)
|
|
{
|
|
FLightSampler LightSampler;
|
|
LightSampler.WeightSum = 0.0f;
|
|
|
|
for (uint LightSampleIndex = 0; LightSampleIndex < NUM_SAMPLES_1D; ++LightSampleIndex)
|
|
{
|
|
LightSampler.PackedSamples[LightSampleIndex] = PackCandidateLightSample(InitCandidateLightSample());
|
|
LightSampler.LightIndexRandom[LightSampleIndex] = (RandomScalar + LightSampleIndex) / NUM_SAMPLES_1D;
|
|
}
|
|
|
|
return LightSampler;
|
|
}
|
|
|
|
void AddLightSample(inout FLightSampler LightSampler, float SampleWeight, uint ForwardLightIndex, bool bWasVisibleInLastFrame)
|
|
{
|
|
float Tau = LightSampler.WeightSum / (LightSampler.WeightSum + SampleWeight);
|
|
LightSampler.WeightSum += SampleWeight;
|
|
|
|
for (uint LightSampleIndex = 0; LightSampleIndex < NUM_SAMPLES_1D; ++LightSampleIndex)
|
|
{
|
|
if (LightSampler.LightIndexRandom[LightSampleIndex] < Tau)
|
|
{
|
|
LightSampler.LightIndexRandom[LightSampleIndex] /= Tau;
|
|
}
|
|
else
|
|
{
|
|
// Select this sample
|
|
LightSampler.LightIndexRandom[LightSampleIndex] = (LightSampler.LightIndexRandom[LightSampleIndex] - Tau) / (1.0f - Tau);
|
|
|
|
FCandidateLightSample LightSample = InitCandidateLightSample();
|
|
LightSample.LocalLightIndex = ForwardLightIndex;
|
|
LightSample.bLightWasVisible = bWasVisibleInLastFrame;
|
|
LightSample.Weight = SampleWeight;
|
|
LightSampler.PackedSamples[LightSampleIndex] = PackCandidateLightSample(LightSample);
|
|
}
|
|
|
|
LightSampler.LightIndexRandom[LightSampleIndex] = clamp(LightSampler.LightIndexRandom[LightSampleIndex], 0, 0.9999f);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Mix visible and invisible samples using a desired ratio
|
|
*/
|
|
void CombineLightSamplers(inout FLightSampler LightSampler, inout FLightSampler HiddenLightSampler, bool bHasValidHistory, float HiddenRatio, inout FShaderPrintContext DebugContext)
|
|
{
|
|
const float ClampedWeightSum = max(LightSampler.WeightSum, 0.01f);
|
|
float WeightRatio = HiddenLightSampler.WeightSum / max(LightSampler.WeightSum, ClampedWeightSum);
|
|
WeightRatio = min(WeightRatio, bHasValidHistory ? HiddenRatio : 1.0f);
|
|
float ClampedHiddenWeightSum = max(LightSampler.WeightSum, ClampedWeightSum) * WeightRatio;
|
|
float HiddenSampleWeightScale = ClampedHiddenWeightSum / HiddenLightSampler.WeightSum;
|
|
|
|
float Tau = LightSampler.WeightSum / (LightSampler.WeightSum + ClampedHiddenWeightSum);
|
|
LightSampler.WeightSum += ClampedHiddenWeightSum;
|
|
|
|
for (uint LightSampleIndex = 0; LightSampleIndex < NUM_SAMPLES_1D; ++LightSampleIndex)
|
|
{
|
|
if (LightSampler.LightIndexRandom[LightSampleIndex] >= Tau)
|
|
{
|
|
LightSampler.LightIndexRandom[LightSampleIndex] = (LightSampler.LightIndexRandom[LightSampleIndex] - Tau) / (1.0f - Tau);
|
|
uint HiddenLightSampleIndex = clamp(LightSampler.LightIndexRandom[LightSampleIndex] * NUM_SAMPLES_1D, 0, NUM_SAMPLES_1D - 1);
|
|
|
|
FCandidateLightSample LightSample = UnpackCandidateLightSample(HiddenLightSampler.PackedSamples[HiddenLightSampleIndex]);
|
|
LightSample.Weight *= HiddenSampleWeightScale;
|
|
LightSampler.PackedSamples[LightSampleIndex] = PackCandidateLightSample(LightSample);
|
|
}
|
|
}
|
|
|
|
if (DebugContext.bIsActive)
|
|
{
|
|
Newline(DebugContext);
|
|
Print(DebugContext, TEXT("Clamped hidden wsum: "));
|
|
Print(DebugContext, ClampedHiddenWeightSum, FontValue);
|
|
}
|
|
} |