2026-02-02 21:07:49 +08:00

98 lines
4.4 KiB
HLSL

// we use this to prevent artifacts with half (16bit) moments
// this is only for power moments as trigonometric moments do not suffer as much from rounding errors (quote from the guys who actually did this technique)
// see https://momentsingraphics.de/I3D2018.html
// Definition of utility functions for quantization and dequantization of power moments stored in 16 bits per moment
// NOTE : It seems that ROVs are necessary for this to work, unfortunately this is out of scope for now
// 4 MOMENTS
void offsetMoments(inout float2 b_even, inout float2 b_odd, float sign)
{
b_odd += 0.5 * sign;
}
void quantizeMoments(out float2 b_even_q, out float2 b_odd_q, float2 b_even, float2 b_odd)
{
b_odd_q = mul(b_odd, float2x2(1.5f, sqrt(3.0f) * 0.5f, -2.0f, -sqrt(3.0f) * 2.0f / 9.0f));
b_even_q = mul(b_even, float2x2(4.0f, 0.5f, -4.0f, 0.5f));
}
void offsetAndDequantizeMoments(out float2 b_even, out float2 b_odd, float2 b_even_q, float2 b_odd_q)
{
offsetMoments(b_even_q, b_odd_q, -1.0);
b_odd = mul(b_odd_q, float2x2(-1.0f / 3.0f, -0.75f, sqrt(3.0f), 0.75f * sqrt(3.0f)));
b_even = mul(b_even_q, float2x2(0.125f, -0.125f, 1.0f, 1.0f));
}
// 6 MOMENTS
void offsetMoments(inout float3 b_even, inout float3 b_odd, float sign)
{
b_odd += 0.5 * sign;
b_even.z += 0.018888946f * sign;
}
void quantizeMoments(out float3 b_even_q, out float3 b_odd_q, float3 b_even, float3 b_odd)
{
const float3x3 QuantizationMatrixOdd = float3x3(
2.5f, -1.87499864450f, 1.26583039016f,
-10.0f, 4.20757543111f, -1.47644882902f,
8.0f, -1.83257678661f, 0.71061660238f);
const float3x3 QuantizationMatrixEven = float3x3(
4.0f, 9.0f, -0.57759806484f,
-4.0f, -24.0f, 4.61936647543f,
0.0f, 16.0f, -3.07953906655f);
b_odd_q = mul(b_odd, QuantizationMatrixOdd);
b_even_q = mul(b_even, QuantizationMatrixEven);
}
void offsetAndDequantizeMoments(out float3 b_even, out float3 b_odd, float3 b_even_q, float3 b_odd_q)
{
const float3x3 QuantizationMatrixOdd = float3x3(
-0.02877789192f, 0.09995235706f, 0.25893353755f,
0.47635550422f, 0.84532580931f, 0.90779616657f,
1.55242808973f, 1.05472570761f, 0.83327335647f);
const float3x3 QuantizationMatrixEven = float3x3(
0.00001253044f, -0.24998746956f, -0.37498825271f,
0.16668494186f, 0.16668494186f, 0.21876713299f,
0.86602540579f, 0.86602540579f, 0.81189881793f);
offsetMoments(b_even_q, b_odd_q, -1.0);
b_odd = mul(b_odd_q, QuantizationMatrixOdd);
b_even = mul(b_even_q, QuantizationMatrixEven);
}
// 8 MOMENTS
void offsetMoments(inout float4 b_even, inout float4 b_odd, float sign)
{
b_odd += 0.5 * sign;
b_even += float4(0.972481993925964, 1.0, 0.999179192513328, 0.991778293073131) * sign;
}
void quantizeMoments(out float4 b_even_q, out float4 b_odd_q, float4 b_even, float4 b_odd)
{
const float4x4 mat_odd = float4x4(3.48044635732474, -27.5760737514826, 55.1267384344761, -31.5311110403183,
1.26797185782836, -0.928755808743913, -2.07520453231032, 1.23598848322588,
-2.1671560004294, 6.17950199592966, -0.276515571579297, -4.23583042392097,
0.974332879165755, -0.443426830933027, -0.360491648368785, 0.310149466050223);
const float4x4 mat_even = float4x4(0.280504133158527, -0.757633844606942, 0.392179589334688, -0.887531871812237,
-2.01362265883247, 0.221551373038988, -1.06107954265125, 2.83887201588367,
-7.31010494985321, 13.9855979699139, -0.114305766176437, -7.4361899359832,
-15.8954215629556, 79.6186327084103, -127.457278992502, 63.7349456687829);
b_odd_q = mul(mat_odd, b_odd);
b_even_q = mul(mat_even, b_even);
}
void offsetAndDequantizeMoments(out float4 b_even, out float4 b_odd, float4 b_even_q, float4 b_odd_q)
{
const float4x4 mat_odd = float4x4(-0.00482399708502382, -0.423201508674231, 0.0348312382605129, 1.67179208266592,
-0.0233402218644408, -0.832829097046478, 0.0193406040499625, 1.21021509068975,
-0.010888537031885, -0.926393772997063, -0.11723394414779, 0.983723301818275,
-0.0308713357806732, -0.937989172670245, -0.218033377677099, 0.845991731322996);
const float4x4 mat_even = float4x4(-0.976220278891035, -0.456139260269401, -0.0504335521016742, 0.000838800390651085,
-1.04828341778299, -0.229726640510149, 0.0259608334616091, -0.00133632693205861,
-1.03115268628604, -0.077844420809897, 0.00443408851014257, -0.0103744938457406,
-0.996038443434636, 0.0175438624416783, -0.0361414253243963, -0.00317839994022725);
offsetMoments(b_even_q, b_odd_q, -1.0);
b_odd = mul(mat_odd, b_odd_q);
b_even = mul(mat_even, b_even_q);
}