137 lines
3.8 KiB
HLSL
137 lines
3.8 KiB
HLSL
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
// cubic interpolation between values.
|
|
// note f0 = function at t=0
|
|
// f1 = function at t=1
|
|
float Monotonic1DCubic_{ParameterName}(float fm1, float f0, float f1, float f2, float t)
|
|
{
|
|
float d0 = .5 * (f1 - fm1);
|
|
float d1 = .5 * (f2 - f0);
|
|
float delta0 = f1 - f0;
|
|
|
|
if (sign(d0) != sign(d1) ||
|
|
sign(delta0) != sign(d0) ||
|
|
abs(delta0) < 1.1754943508e-38)
|
|
{
|
|
d0 = 0;
|
|
d1 = 0;
|
|
}
|
|
|
|
float a0 = f0;
|
|
float a1 = d0;
|
|
float a2 = 3.0f*delta0 - 2.0f * d0 - d1;
|
|
float a3 = d0 + d1 - 2 * delta0;
|
|
|
|
return a3 * t*t*t + a2 * t*t + a1 * t + a0;
|
|
}
|
|
|
|
float Basic1DCubic_{ParameterName}(float fm1, float f0, float f1, float f2, float t)
|
|
{
|
|
if (abs(f1 - f0) < 1.1754943508e-38)
|
|
{
|
|
return f0;
|
|
}
|
|
|
|
float a0 = f0;
|
|
float a1 = -1./3 * fm1 - 1./2* f0 + f1 - 1./6 * f2;
|
|
float a2 = 1./2 * fm1 - f0 + 1./2 * f1;
|
|
float a3 = -1./6 * fm1 + 1./2 * f0 - 1./2 * f1 + 1./6 * f2;
|
|
return a3 * t*t*t + a2 * t*t + a1 * t + a0;
|
|
}
|
|
|
|
float Basic2DCubic_{ParameterName}(SamplerState Sampler, float3 UVW, int MipLevel)
|
|
{
|
|
const int AttributeIndex = round(UVW[2]);
|
|
|
|
const float2 GridPos = UVW.xy * {NumCellsName}.xy - .5;
|
|
|
|
// identify the lower-left-hand corner of the cell
|
|
const int2 GridCell = floor(GridPos);
|
|
|
|
const int2 MaxCell = {NumCellsName} - int2(3,3);
|
|
|
|
if (any((GridCell < int2(2,2)) || (GridCell >= MaxCell)))
|
|
{
|
|
// revert to bilinear hardware sampling at the boundary cells.
|
|
return {GridName}.SampleLevel(Sampler, UVW, MipLevel);
|
|
}
|
|
else
|
|
{
|
|
const float2 t = frac(GridPos);
|
|
float4 GridVals;
|
|
|
|
float minv = 3.402823466e+38;
|
|
float maxv = -3.402823466e+38;
|
|
|
|
float4 InterpInX;
|
|
for (int j = 0; j < 4; ++j)
|
|
{
|
|
for (int i = 0; i < 4; ++i)
|
|
{
|
|
const float CurrValue = {GridName}.Load(int4(GridCell.x + i - 1, GridCell.y + j - 1, AttributeIndex, MipLevel));
|
|
GridVals[i] = CurrValue;
|
|
minv = min(CurrValue, minv);
|
|
maxv = max(CurrValue, maxv);
|
|
}
|
|
InterpInX[j] = Basic1DCubic_{ParameterName}(GridVals[0], GridVals[1], GridVals[2], GridVals[3], t[0]);
|
|
}
|
|
const float BiCubicValue = Basic1DCubic_{ParameterName}(InterpInX[0], InterpInX[1], InterpInX[2], InterpInX[3], t[1]);
|
|
|
|
if (BiCubicValue < minv || BiCubicValue > maxv)
|
|
{
|
|
return {GridName}.SampleLevel(Sampler, UVW, MipLevel);
|
|
}
|
|
return BiCubicValue;
|
|
}
|
|
}
|
|
|
|
float Monotonic2DCubic_{ParameterName}(SamplerState Sampler, float3 UVW, int MipLevel)
|
|
{
|
|
const int AttributeIndex = round(UVW[2]);
|
|
|
|
const float2 GridPos = UVW.xy * {NumCellsName}.xy - .5;
|
|
|
|
// identify the lower-left-hand corner of the cell
|
|
const int2 GridCell = floor(GridPos);
|
|
|
|
const int2 MaxCell = {NumCellsName} - int2(2,2);
|
|
|
|
if (any((GridCell < int2(1,1)) || (GridCell >= MaxCell)))
|
|
{
|
|
// revert to bilinear hardware sampling at the boundary cells.
|
|
return {GridName}.SampleLevel(Sampler, UVW, MipLevel);
|
|
}
|
|
else
|
|
{
|
|
const float2 t = GridPos - GridCell;
|
|
float4 GridVals;
|
|
|
|
float minv = 3.402823466e+38;
|
|
float maxv = -3.402823466e+38;
|
|
|
|
float4 InterpInX;
|
|
for (int j = 0; j < 4; ++j)
|
|
{
|
|
for (int i = 0; i < 4; ++i)
|
|
{
|
|
const float CurrValue = {GridName}.Load(int4(GridCell.x + i - 1, GridCell.y + j - 1, AttributeIndex, MipLevel));
|
|
GridVals[i] = CurrValue;
|
|
minv = min(CurrValue, minv);
|
|
maxv = max(CurrValue, maxv);
|
|
}
|
|
InterpInX[j] = Monotonic1DCubic_{ParameterName}(GridVals[0], GridVals[1], GridVals[2], GridVals[3], t[0]);
|
|
}
|
|
const float BiCubicValue = Monotonic1DCubic_{ParameterName}(InterpInX[0], InterpInX[1], InterpInX[2], InterpInX[3], t[1]);
|
|
|
|
if (BiCubicValue < minv || BiCubicValue > maxv)
|
|
{
|
|
return {GridName}.SampleLevel(Sampler, UVW, MipLevel);
|
|
}
|
|
return BiCubicValue;
|
|
}
|
|
}
|
|
|
|
float SampleBiCubic_{ParameterName}(SamplerState Sampler, float3 UVW, int MipLevel)
|
|
{
|
|
return Basic2DCubic_{ParameterName}(Sampler, UVW, MipLevel);
|
|
} |