115 lines
3.7 KiB
HLSL
115 lines
3.7 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 InitLightSamplerStratified(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 InitLightSamplerFromSequence(inout FLightSampler LightSampler, uint2 ScreenCoord, uint StateFrameIndex)
|
|
{
|
|
LightSampler.WeightSum = 0.0f;
|
|
|
|
for (uint LightSampleIndex = 0; LightSampleIndex < NUM_SAMPLES_1D; ++LightSampleIndex)
|
|
{
|
|
FRandomSequence RandSequence = RandomSequenceCreate(uint3(ScreenCoord, StateFrameIndex), LightSampleIndex, NUM_SAMPLES_1D);
|
|
|
|
LightSampler.PackedSamples[LightSampleIndex] = PackCandidateLightSample(InitCandidateLightSample());
|
|
LightSampler.LightIndexRandom[LightSampleIndex] = RandSequence.Get1D();
|
|
}
|
|
}
|
|
|
|
float DirectionalLightSampleRatio;
|
|
float MinSampleClampingWeight;
|
|
|
|
void AddLightSample(inout FLightSampler LightSampler, float SampleWeight, uint ForwardLightIndex, bool bWasVisibleInLastFrame, bool bRadialLight)
|
|
{
|
|
// Make sure that directional lights don't completely take over the entire sample budget
|
|
if (!bRadialLight && DirectionalLightSampleRatio > 0.0f)
|
|
{
|
|
SampleWeight = min(SampleWeight, max(LightSampler.WeightSum, MinSampleClampingWeight) * DirectionalLightSampleRatio);
|
|
}
|
|
|
|
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);
|
|
}
|
|
} |