512 lines
17 KiB
HLSL
512 lines
17 KiB
HLSL
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
#include "HeterogeneousVolumesAdaptiveVolumetricShadowMapUtils.ush"
|
|
#include "HeterogeneousVolumesAdaptiveVolumetricShadowMapSampling.ush"
|
|
|
|
#ifndef AVSM_BILINEAR_INTERPOLATION
|
|
#define AVSM_BILINEAR_INTERPOLATION 1
|
|
#endif //
|
|
|
|
#define INVALID_SAMPLE_INDEX 0xFFu
|
|
#define INVALID_SAMPLE_INDEX4 0xFFFFFFFFu
|
|
|
|
#if 0
|
|
// Reference single-channel implementation
|
|
struct FAVSM_Sampler
|
|
{
|
|
FAdaptiveVolumetricShadowMap ShadowMap;
|
|
uint PixelOffset;
|
|
uint SampleCount;
|
|
uint SampleIndex;
|
|
|
|
// Query cache
|
|
FAVSMSampleData SampleData[2];
|
|
|
|
// Convenience creation data
|
|
int Face;
|
|
int2 Pixel;
|
|
float DepthOffset;
|
|
};
|
|
|
|
bool IsValid(FAVSM_Sampler Iterator)
|
|
{
|
|
return Iterator.SampleIndex != INVALID_SAMPLE_INDEX;
|
|
}
|
|
|
|
FAVSM_Sampler AVSM_Sampler_Create(
|
|
inout FAdaptiveVolumetricShadowMap ShadowMap,
|
|
int Face,
|
|
int2 Pixel,
|
|
float DepthOffset
|
|
)
|
|
{
|
|
FAVSM_Sampler Iterator;
|
|
Iterator.ShadowMap = ShadowMap;
|
|
|
|
uint LinearIndex = AVSM_LinearIndex(Iterator.ShadowMap, Face, Pixel);
|
|
FAVSMIndirectionData IndirectionData = AVSM_UnpackIndirectionData(Iterator.ShadowMap.IndirectionBuffer[LinearIndex]);
|
|
Iterator.PixelOffset = IndirectionData.PixelOffset;
|
|
Iterator.SampleCount = IndirectionData.SampleCount;
|
|
|
|
if (Iterator.SampleCount > 0)
|
|
{
|
|
int TopLevelSampleCount = CalcTopLevelSampleCount(Iterator.SampleCount);
|
|
Iterator.SampleIndex = 0;
|
|
Iterator.SampleData[0] = AVSM_UnpackSampleData(Iterator.ShadowMap.SampleBuffer[Iterator.PixelOffset + Align4(TopLevelSampleCount) + Iterator.SampleIndex], IndirectionData);
|
|
Iterator.SampleData[1] = AVSM_UnpackSampleData(Iterator.ShadowMap.SampleBuffer[Iterator.PixelOffset + Align4(TopLevelSampleCount) + Iterator.SampleIndex + 1], IndirectionData);
|
|
}
|
|
else
|
|
{
|
|
Iterator.SampleIndex = INVALID_SAMPLE_INDEX;
|
|
Iterator.SampleData[0] = AVSM_CreateSampleData(0.0, 1.0);
|
|
Iterator.SampleData[1] = AVSM_CreateSampleData(0.0, 1.0);
|
|
}
|
|
|
|
Iterator.Face = Face;
|
|
Iterator.Pixel = Pixel;
|
|
Iterator.DepthOffset = DepthOffset;
|
|
return Iterator;
|
|
}
|
|
|
|
float AVSM_Sampler_Eval(inout FAVSM_Sampler Iterator, float X)
|
|
{
|
|
X -= Iterator.DepthOffset;
|
|
if (IsValid(Iterator))
|
|
{
|
|
int TopLevelSampleCount = CalcTopLevelSampleCount(Iterator.SampleCount);
|
|
|
|
while ((X > Iterator.SampleData[1].X) && (Iterator.SampleIndex < Iterator.SampleCount - 1))
|
|
{
|
|
Iterator.SampleIndex++;
|
|
Iterator.SampleData[0] = Iterator.SampleData[1];
|
|
Iterator.SampleData[1] = AVSM_UnpackSampleData(Iterator.ShadowMap.SampleBuffer[Iterator.PixelOffset + Align4(TopLevelSampleCount) + Iterator.SampleIndex], Iterator.IndirectionData);
|
|
}
|
|
}
|
|
|
|
float BlendWeight = saturate((X - Iterator.SampleData[0].X) * SafeRcp(Iterator.SampleData[1].X - Iterator.SampleData[0].X));
|
|
float Tau = lerp(Iterator.SampleData[0].Tau, Iterator.SampleData[1].Tau, BlendWeight);
|
|
return Tau;
|
|
}
|
|
|
|
FAVSMSampleData AVSM_Sampler_EvalInverse(inout FAVSM_Sampler Iterator, float Tau)
|
|
{
|
|
if (IsValid(Iterator))
|
|
{
|
|
int TopLevelSampleCount = CalcTopLevelSampleCount(Iterator.SampleCount);
|
|
|
|
while ((Tau < Iterator.SampleData[1].Tau) && (Iterator.SampleIndex < Iterator.SampleCount - 1))
|
|
{
|
|
Iterator.SampleIndex++;
|
|
Iterator.SampleData[0] = Iterator.SampleData[1];
|
|
Iterator.SampleData[1] = AVSM_UnpackSampleData(Iterator.ShadowMap.SampleBuffer[Iterator.PixelOffset + Align4(TopLevelSampleCount) + Iterator.SampleIndex], Iterator.IndirectionData);
|
|
}
|
|
}
|
|
|
|
float BlendWeight = saturate((Tau - Iterator.SampleData[0].Tau) * SafeRcp(Iterator.SampleData[1].Tau - Iterator.SampleData[0].Tau));
|
|
float X = lerp(Iterator.SampleData[0].X, Iterator.SampleData[1].X, BlendWeight);
|
|
X += Iterator.DepthOffset;
|
|
return AVSM_CreateSampleData(X, Tau);
|
|
}
|
|
|
|
float AVSM_Sampler_Last(inout FAVSM_Sampler Iterator)
|
|
{
|
|
float Transmittance = 1.0;
|
|
if (IsValid(Iterator))
|
|
{
|
|
int TopLevelSampleCount = CalcTopLevelSampleCount(Iterator.SampleCount);
|
|
if (TopLevelSampleCount > 0)
|
|
{
|
|
uint SampleIndex = max(Iterator.SampleCount - 2, 0);
|
|
FAVSMSampleData SampleData = AVSM_UnpackSampleData(Iterator.ShadowMap.SampleBuffer[Iterator.PixelOffset + Align4(TopLevelSampleCount) + SampleIndex], Iterator.IndirectionData);
|
|
|
|
Transmittance = SampleData.Tau;
|
|
}
|
|
}
|
|
return Transmittance;
|
|
}
|
|
#endif
|
|
|
|
// Sampler4 implementation reduces VGPR usage
|
|
struct FAVSM_Sampler4
|
|
{
|
|
FAdaptiveVolumetricShadowMap ShadowMap;
|
|
uint4 PixelOffset4;
|
|
uint SampleCount4;
|
|
float4 BeginX4;
|
|
float4 EndX4;
|
|
uint SampleIndex4;
|
|
|
|
// Query cache
|
|
uint4 SampleData0Packed4;
|
|
uint4 SampleData1Packed4;
|
|
|
|
// Convenience creation data
|
|
int Face;
|
|
float2 Pixel;
|
|
float DepthOffset;
|
|
};
|
|
|
|
uint AVSM_Sampler4_GetSampleIndex(inout FAVSM_Sampler4 Sampler4, uint Index)
|
|
{
|
|
uint SampleIndex = (Sampler4.SampleIndex4 >> (Index * 8u)) & INVALID_SAMPLE_INDEX;
|
|
return SampleIndex;
|
|
}
|
|
|
|
void AVSM_Sampler4_SetSampleIndex(inout FAVSM_Sampler4 Sampler4, int4 SampleIndex4)
|
|
{
|
|
int SampleIndexPacked = 0;
|
|
for (uint Index = 0; Index < 4; ++Index)
|
|
{
|
|
SampleIndexPacked |= ((SampleIndex4[Index] & INVALID_SAMPLE_INDEX) << (Index * 8u));
|
|
}
|
|
Sampler4.SampleIndex4 = SampleIndexPacked;
|
|
}
|
|
|
|
void AVSM_Sampler4_SetSampleIndex(inout FAVSM_Sampler4 Sampler4, uint Index, uint SampleIndex)
|
|
{
|
|
uint WriteMask = INVALID_SAMPLE_INDEX << (Index * 8u);
|
|
Sampler4.SampleIndex4 &= ~WriteMask;
|
|
Sampler4.SampleIndex4 |= (SampleIndex & INVALID_SAMPLE_INDEX) << (Index * 8u);
|
|
}
|
|
|
|
uint AVSM_Sampler4_GetSampleCount(inout FAVSM_Sampler4 Sampler4, uint Index)
|
|
{
|
|
uint SampleCount = (Sampler4.SampleCount4 >> (Index * 8u)) & INVALID_SAMPLE_INDEX;
|
|
return SampleCount;
|
|
}
|
|
|
|
float AVSM_Sampler4_GetBeginX(inout FAVSM_Sampler4 Sampler4, uint Index)
|
|
{
|
|
float BeginX = Sampler4.BeginX4[Index];
|
|
return BeginX;
|
|
}
|
|
|
|
float AVSM_Sampler4_GetEndX(inout FAVSM_Sampler4 Sampler4, uint Index)
|
|
{
|
|
float EndX = Sampler4.EndX4[Index];
|
|
return EndX;
|
|
}
|
|
|
|
bool AVSM_Sampler4_IsValid(inout FAVSM_Sampler4 Sampler4, uint Index)
|
|
{
|
|
return AVSM_Sampler4_GetSampleIndex(Sampler4, Index) != INVALID_SAMPLE_INDEX;
|
|
}
|
|
|
|
void AVSM_Sampler4_SetSampleCount(inout FAVSM_Sampler4 Sampler4, int4 SampleCount4)
|
|
{
|
|
uint SampleCountPacked = 0;
|
|
for (uint Index = 0; Index < 4; ++Index)
|
|
{
|
|
SampleCountPacked |= ((SampleCount4[Index] & INVALID_SAMPLE_INDEX) << (Index * 8u));
|
|
}
|
|
Sampler4.SampleCount4 = SampleCountPacked;
|
|
}
|
|
|
|
uint AVSM_Sampler4_GetPixelOffset(inout FAVSM_Sampler4 Sampler4, uint Index)
|
|
{
|
|
uint PixelOffset = Sampler4.PixelOffset4[Index];
|
|
return PixelOffset;
|
|
}
|
|
|
|
void AVSM_Sampler4_SetPixelOffset(inout FAVSM_Sampler4 Sampler4, uint4 PixelOffset)
|
|
{
|
|
Sampler4.PixelOffset4 = PixelOffset;
|
|
}
|
|
|
|
void AVSM_Sampler4_SetBeginX(inout FAVSM_Sampler4 Sampler4, float4 BeginX4)
|
|
{
|
|
Sampler4.BeginX4 = BeginX4;
|
|
}
|
|
|
|
void AVSM_Sampler4_SetEndX(inout FAVSM_Sampler4 Sampler4, float4 EndX4)
|
|
{
|
|
Sampler4.EndX4 = EndX4;
|
|
}
|
|
|
|
FAVSMSampleData AVSM_Sampler4_GetSampleData0(inout FAVSM_Sampler4 Sampler4, uint Index)
|
|
{
|
|
FAVSMIndirectionData IndirectionData = AVSM_CreateIndirectionData(
|
|
AVSM_Sampler4_GetPixelOffset(Sampler4, Index),
|
|
AVSM_Sampler4_GetSampleIndex(Sampler4, Index),
|
|
AVSM_Sampler4_GetBeginX(Sampler4, Index),
|
|
AVSM_Sampler4_GetEndX(Sampler4, Index)
|
|
);
|
|
|
|
FAVSMSampleData SampleData0 = AVSM_UnpackSampleData(Sampler4.SampleData0Packed4[Index], IndirectionData);
|
|
SampleData0.X += Sampler4.DepthOffset;
|
|
return SampleData0;
|
|
}
|
|
|
|
void AVSM_Sampler4_SetSampleData0(inout FAVSM_Sampler4 Sampler4, uint4 SampleDataPacked4)
|
|
{
|
|
Sampler4.SampleData0Packed4 = SampleDataPacked4;
|
|
}
|
|
|
|
void AVSM_Sampler4_SetSampleData0(inout FAVSM_Sampler4 Sampler4, uint Index, uint SampleDataPacked)
|
|
{
|
|
Sampler4.SampleData0Packed4[Index] = SampleDataPacked;
|
|
}
|
|
|
|
FAVSMSampleData AVSM_Sampler4_GetSampleData1(inout FAVSM_Sampler4 Sampler4, uint Index)
|
|
{
|
|
FAVSMIndirectionData IndirectionData = AVSM_CreateIndirectionData(
|
|
AVSM_Sampler4_GetPixelOffset(Sampler4, Index),
|
|
AVSM_Sampler4_GetSampleIndex(Sampler4, Index),
|
|
AVSM_Sampler4_GetBeginX(Sampler4, Index),
|
|
AVSM_Sampler4_GetEndX(Sampler4, Index)
|
|
);
|
|
|
|
FAVSMSampleData SampleData1 = AVSM_UnpackSampleData(Sampler4.SampleData1Packed4[Index], IndirectionData);
|
|
SampleData1.X += Sampler4.DepthOffset;
|
|
return SampleData1;
|
|
}
|
|
|
|
void AVSM_Sampler4_SetSampleData1(inout FAVSM_Sampler4 Sampler4, uint4 SampleDataPacked4)
|
|
{
|
|
Sampler4.SampleData1Packed4 = SampleDataPacked4;
|
|
}
|
|
|
|
void AVSM_Sampler4_SetSampleData1(inout FAVSM_Sampler4 Sampler4, uint Index, uint SampleDataPacked)
|
|
{
|
|
Sampler4.SampleData1Packed4[Index] = SampleDataPacked;
|
|
}
|
|
|
|
FAVSM_Sampler4 AVSM_Sampler4_Create(
|
|
inout FAdaptiveVolumetricShadowMap ShadowMap,
|
|
int Face,
|
|
float2 Pixel,
|
|
float DepthOffset
|
|
)
|
|
{
|
|
FAVSM_Sampler4 Sampler4;
|
|
Sampler4.ShadowMap = ShadowMap;
|
|
|
|
uint2 Pixel4[4] = {
|
|
clamp(Pixel, 0, ShadowMap.Resolution - 1),
|
|
clamp(Pixel + int2(1, 0), 0, ShadowMap.Resolution - 1),
|
|
clamp(Pixel + int2(0, 1), 0, ShadowMap.Resolution - 1),
|
|
clamp(Pixel + int2(1, 1), 0, ShadowMap.Resolution - 1)
|
|
};
|
|
uint4 LinearIndex4 = uint4(
|
|
AVSM_LinearIndex(Sampler4.ShadowMap, Face, Pixel4[0]),
|
|
AVSM_LinearIndex(Sampler4.ShadowMap, Face, Pixel4[1]),
|
|
AVSM_LinearIndex(Sampler4.ShadowMap, Face, Pixel4[2]),
|
|
AVSM_LinearIndex(Sampler4.ShadowMap, Face, Pixel4[3])
|
|
);
|
|
|
|
uint4 SampleCount4 = INVALID_SAMPLE_INDEX4;
|
|
uint4 SampleIndex4 = INVALID_SAMPLE_INDEX4;
|
|
uint4 SampleData0Packed4 = 0;
|
|
uint4 SampleData1Packed4 = 0;
|
|
uint4 PixelOffset4 = 0;
|
|
float4 BeginX4 = 0;
|
|
float4 EndX4 = 0;
|
|
for (int Index = 0; Index < 4; ++Index)
|
|
{
|
|
FAVSMIndirectionData IndirectionData = AVSM_UnpackIndirectionData(ShadowMap.IndirectionBuffer[LinearIndex4[Index]]);
|
|
PixelOffset4[Index] = IndirectionData.PixelOffset;
|
|
SampleCount4[Index] = IndirectionData.SampleCount;
|
|
BeginX4[Index] = IndirectionData.BeginX;
|
|
EndX4[Index] = IndirectionData.EndX;
|
|
|
|
if (SampleCount4[Index] > 0)
|
|
{
|
|
int TopLevelSampleCount = CalcTopLevelSampleCount(SampleCount4[Index]);
|
|
SampleIndex4[Index] = 0;
|
|
SampleData0Packed4[Index] = ShadowMap.SampleBuffer[PixelOffset4[Index] + Align4(TopLevelSampleCount) + SampleIndex4[Index]];
|
|
SampleData1Packed4[Index] = ShadowMap.SampleBuffer[PixelOffset4[Index] + Align4(TopLevelSampleCount) + SampleIndex4[Index] + 1];
|
|
}
|
|
else
|
|
{
|
|
SampleIndex4[Index] = INVALID_SAMPLE_INDEX;
|
|
SampleData0Packed4[Index] = AVSM_PackSampleData(0.0, 1.0, IndirectionData);
|
|
SampleData1Packed4[Index] = AVSM_PackSampleData(0.0, 1.0, IndirectionData);
|
|
}
|
|
}
|
|
AVSM_Sampler4_SetSampleCount(Sampler4, SampleCount4);
|
|
AVSM_Sampler4_SetSampleIndex(Sampler4, SampleIndex4);
|
|
AVSM_Sampler4_SetSampleData0(Sampler4, SampleData0Packed4);
|
|
AVSM_Sampler4_SetSampleData1(Sampler4, SampleData1Packed4);
|
|
AVSM_Sampler4_SetPixelOffset(Sampler4, PixelOffset4);
|
|
AVSM_Sampler4_SetBeginX(Sampler4, BeginX4);
|
|
AVSM_Sampler4_SetEndX(Sampler4, EndX4);
|
|
|
|
Sampler4.Face = Face;
|
|
Sampler4.Pixel = Pixel;
|
|
Sampler4.DepthOffset = DepthOffset;
|
|
return Sampler4;
|
|
}
|
|
|
|
float AVSM_Sampler4_Eval_Internal(inout FAVSM_Sampler4 Sampler4, int Index, float X)
|
|
{
|
|
X -= Sampler4.DepthOffset;
|
|
|
|
FAVSMSampleData SampleData[] = {
|
|
AVSM_Sampler4_GetSampleData0(Sampler4, Index),
|
|
AVSM_Sampler4_GetSampleData1(Sampler4, Index)
|
|
};
|
|
|
|
if (AVSM_Sampler4_IsValid(Sampler4, Index))
|
|
{
|
|
int SampleIndex = AVSM_Sampler4_GetSampleIndex(Sampler4, Index);
|
|
int SampleCount = AVSM_Sampler4_GetSampleCount(Sampler4, Index);
|
|
int TopLevelSampleCount = CalcTopLevelSampleCount(SampleCount);
|
|
|
|
while ((X > SampleData[1].X) && (SampleIndex < SampleCount - 1))
|
|
{
|
|
SampleIndex++;
|
|
SampleData[0] = SampleData[1];
|
|
uint PixelOffset = AVSM_Sampler4_GetPixelOffset(Sampler4, Index);
|
|
FAVSMIndirectionData IndirectionData = AVSM_CreateIndirectionData(
|
|
AVSM_Sampler4_GetPixelOffset(Sampler4, Index),
|
|
AVSM_Sampler4_GetSampleIndex(Sampler4, Index),
|
|
AVSM_Sampler4_GetBeginX(Sampler4, Index),
|
|
AVSM_Sampler4_GetEndX(Sampler4, Index)
|
|
);
|
|
SampleData[1] = AVSM_UnpackSampleData(Sampler4.ShadowMap.SampleBuffer[PixelOffset + Align4(TopLevelSampleCount) + SampleIndex], IndirectionData);
|
|
|
|
AVSM_Sampler4_SetSampleIndex(Sampler4, Index, SampleIndex);
|
|
AVSM_Sampler4_SetSampleData0(Sampler4, Index, AVSM_PackSampleData(SampleData[0], IndirectionData));
|
|
AVSM_Sampler4_SetSampleData1(Sampler4, Index, AVSM_PackSampleData(SampleData[1], IndirectionData));
|
|
}
|
|
}
|
|
|
|
float BlendWeight = saturate((X - SampleData[0].X) * SafeRcp(SampleData[1].X - SampleData[0].X));
|
|
float Tau = lerp(SampleData[0].Tau, SampleData[1].Tau, BlendWeight);
|
|
return Tau;
|
|
}
|
|
|
|
float AVSM_Bilinear_Interpolate(float Value[4], float2 Weight)
|
|
{
|
|
float ValueX[] = {
|
|
lerp(Value[0], Value[1], Weight.x),
|
|
lerp(Value[2], Value[3], Weight.x)
|
|
};
|
|
return lerp(ValueX[0], ValueX[1], Weight.y);
|
|
}
|
|
|
|
float AVSM_Sampler4_Eval(inout FAVSM_Sampler4 Sampler4, float X)
|
|
{
|
|
float Tau = AVSM_Sampler4_Eval_Internal(Sampler4, 0, X);
|
|
#if AVSM_BILINEAR_INTERPOLATION != 0
|
|
float Tau4[] = {
|
|
Tau,
|
|
AVSM_Sampler4_Eval_Internal(Sampler4, 1, X),
|
|
AVSM_Sampler4_Eval_Internal(Sampler4, 2, X),
|
|
AVSM_Sampler4_Eval_Internal(Sampler4, 3, X)
|
|
};
|
|
Tau = AVSM_Bilinear_Interpolate(Tau4, frac(Sampler4.Pixel));
|
|
#endif // AVSM_BILINEAR_INTERPOLATION != 0
|
|
return Tau;
|
|
}
|
|
|
|
float AVSM_Sampler4_Eval_NoInterpolation(inout FAVSM_Sampler4 Sampler4, float X)
|
|
{
|
|
float Tau = AVSM_Sampler4_Eval_Internal(Sampler4, 0, X);
|
|
return Tau;
|
|
}
|
|
|
|
FAVSMSampleData AVSM_Sampler4_EvalInverse_Internal(inout FAVSM_Sampler4 Sampler4, int Index, float Tau)
|
|
{
|
|
FAVSMSampleData SampleData[] = {
|
|
AVSM_Sampler4_GetSampleData0(Sampler4, Index),
|
|
AVSM_Sampler4_GetSampleData1(Sampler4, Index)
|
|
};
|
|
|
|
if (AVSM_Sampler4_IsValid(Sampler4, Index))
|
|
{
|
|
int SampleCount = AVSM_Sampler4_GetSampleCount(Sampler4, Index);
|
|
int TopLevelSampleCount = CalcTopLevelSampleCount(SampleCount);
|
|
|
|
int SampleIndex = AVSM_Sampler4_GetSampleIndex(Sampler4, Index);
|
|
uint PixelOffset = AVSM_Sampler4_GetPixelOffset(Sampler4, Index);
|
|
while ((Tau < SampleData[1].Tau) && (SampleIndex < SampleCount - 1))
|
|
{
|
|
SampleIndex++;
|
|
SampleData[0] = SampleData[1];
|
|
FAVSMIndirectionData IndirectionData = AVSM_CreateIndirectionData(
|
|
AVSM_Sampler4_GetPixelOffset(Sampler4, Index),
|
|
AVSM_Sampler4_GetSampleIndex(Sampler4, Index),
|
|
AVSM_Sampler4_GetBeginX(Sampler4, Index),
|
|
AVSM_Sampler4_GetEndX(Sampler4, Index)
|
|
);
|
|
SampleData[1] = AVSM_UnpackSampleData(Sampler4.ShadowMap.SampleBuffer[PixelOffset + Align4(TopLevelSampleCount) + SampleIndex], IndirectionData);
|
|
|
|
AVSM_Sampler4_SetSampleData0(Sampler4, Index, AVSM_PackSampleData(SampleData[0], IndirectionData));
|
|
AVSM_Sampler4_SetSampleData1(Sampler4, Index, AVSM_PackSampleData(SampleData[1], IndirectionData));
|
|
}
|
|
}
|
|
|
|
float BlendWeight = saturate((Tau - SampleData[0].Tau) * SafeRcp(SampleData[1].Tau - SampleData[0].Tau));
|
|
float X = lerp(SampleData[0].X, SampleData[1].X, BlendWeight);
|
|
X += Sampler4.DepthOffset;
|
|
return AVSM_CreateSampleData(X, Tau);
|
|
}
|
|
|
|
FAVSMSampleData AVSM_Sampler4_EvalInverse(inout FAVSM_Sampler4 Sampler4, float Tau)
|
|
{
|
|
FAVSMSampleData SampleData = AVSM_Sampler4_EvalInverse_Internal(Sampler4, 0, Tau);
|
|
#if AVSM_BILINEAR_INTERPOLATION != 0
|
|
float X4[] = {
|
|
SampleData.X,
|
|
AVSM_Sampler4_EvalInverse_Internal(Sampler4, 1, Tau).X,
|
|
AVSM_Sampler4_EvalInverse_Internal(Sampler4, 2, Tau).X,
|
|
AVSM_Sampler4_EvalInverse_Internal(Sampler4, 3, Tau).X
|
|
};
|
|
SampleData.X = AVSM_Bilinear_Interpolate(X4, frac(Sampler4.Pixel));
|
|
#endif // AVSM_BILINEAR_INTERPOLATION != 0
|
|
return SampleData;
|
|
}
|
|
|
|
FAVSMSampleData AVSM_Sampler4_Last_Internal(inout FAVSM_Sampler4 Sampler4, int Index)
|
|
{
|
|
FAVSMSampleData SampleData = AVSM_CreateSampleData(0.0, 1.0);
|
|
|
|
if (AVSM_Sampler4_IsValid(Sampler4, Index))
|
|
{
|
|
int SampleCount = AVSM_Sampler4_GetSampleCount(Sampler4, Index);
|
|
int TopLevelSampleCount = CalcTopLevelSampleCount(SampleCount);
|
|
if (TopLevelSampleCount > 0)
|
|
{
|
|
uint SampleIndex = max(SampleCount - 2, 0);
|
|
uint PixelOffset = AVSM_Sampler4_GetPixelOffset(Sampler4, Index);
|
|
FAVSMIndirectionData IndirectionData = AVSM_CreateIndirectionData(
|
|
AVSM_Sampler4_GetPixelOffset(Sampler4, Index),
|
|
AVSM_Sampler4_GetSampleIndex(Sampler4, Index),
|
|
AVSM_Sampler4_GetBeginX(Sampler4, Index),
|
|
AVSM_Sampler4_GetEndX(Sampler4, Index)
|
|
);
|
|
SampleData = AVSM_UnpackSampleData(Sampler4.ShadowMap.SampleBuffer[PixelOffset + Align4(TopLevelSampleCount) + SampleIndex], IndirectionData);
|
|
SampleData.X += Sampler4.DepthOffset;
|
|
}
|
|
}
|
|
|
|
return SampleData;
|
|
}
|
|
|
|
FAVSMSampleData AVSM_Sampler4_Last(inout FAVSM_Sampler4 Sampler4)
|
|
{
|
|
FAVSMSampleData SampleData = AVSM_Sampler4_Last_Internal(Sampler4, 0);
|
|
#if AVSM_BILINEAR_INTERPOLATION != 0
|
|
// TODO: Filter X when sentinel value is removed
|
|
//float Depth4[] = {
|
|
// SampleData.X,
|
|
// AVSM_Sampler4_Last_Internal(Sampler4, 1).X,
|
|
// AVSM_Sampler4_Last_Internal(Sampler4, 2).X,
|
|
// AVSM_Sampler4_Last_Internal(Sampler4, 3).X
|
|
//};
|
|
//SampleData.X = AVSM_Bilinear_Interpolate(Depth4, frac(Sampler4.Pixel));
|
|
|
|
float Tau4[] = {
|
|
SampleData.Tau,
|
|
AVSM_Sampler4_Last_Internal(Sampler4, 1).Tau,
|
|
AVSM_Sampler4_Last_Internal(Sampler4, 2).Tau,
|
|
AVSM_Sampler4_Last_Internal(Sampler4, 3).Tau
|
|
};
|
|
SampleData.Tau = AVSM_Bilinear_Interpolate(Tau4, frac(Sampler4.Pixel));
|
|
#endif // AVSM_BILINEAR_INTERPOLATION != 0
|
|
return SampleData;
|
|
}
|