110 lines
3.2 KiB
HLSL
110 lines
3.2 KiB
HLSL
|
|
#include "MomentOutput.hlsl"
|
||
|
|
|
||
|
|
// DONTBLOWUP is NOT part of the original paper, this is a hack i had to do to make this implementation usable
|
||
|
|
|
||
|
|
//#define ABSORPTION_EPSILON max(REAL_MIN, 1e-5)
|
||
|
|
#if _MOMENT_HALF_PRECISION
|
||
|
|
//#define DONTBLOWUP HALF_MIN
|
||
|
|
#define DONTBLOWUP HALF_EPS
|
||
|
|
#else
|
||
|
|
//#define DONTBLOWUP FLT_MIN
|
||
|
|
#define DONTBLOWUP FLT_EPS
|
||
|
|
#endif
|
||
|
|
|
||
|
|
float4 _WrappingZoneParameters;
|
||
|
|
/*! This function implements complex multiplication.*/
|
||
|
|
float2 Multiply(float2 LHS, float2 RHS) {
|
||
|
|
return float2(LHS.x * RHS.x - LHS.y * RHS.y, LHS.x * RHS.y + LHS.y * RHS.x);
|
||
|
|
}
|
||
|
|
|
||
|
|
// if ROV, set to the stored moments from the rasterizer order view and write the new moments back
|
||
|
|
// no ROVs so only single precision works - needs further changes for quantized to read/write moments
|
||
|
|
MomentOutput GenerateMoments(float vd, float t)
|
||
|
|
{
|
||
|
|
t = max(t, DONTBLOWUP); // we have a blowup issue when t (1 - alpha) is close to 0, empirically it happens above 0.99 alpha so let's lock it around there (no visual issues, at that point its pretty indiscernable from opaque)
|
||
|
|
|
||
|
|
// Return early if the surface is fully transparent
|
||
|
|
clip(0.9999999f - t);
|
||
|
|
|
||
|
|
float a = -log(t);
|
||
|
|
float d = WarpDepth(vd);
|
||
|
|
|
||
|
|
MomentOutput output;
|
||
|
|
output.b0 = a;
|
||
|
|
|
||
|
|
#ifdef _TRIGONOMETRIC
|
||
|
|
float p = mad(d, _WrappingZoneParameters.y, _WrappingZoneParameters.y);
|
||
|
|
float2 c;
|
||
|
|
sincos(p, c.y, c.x);
|
||
|
|
float2 c2 = Multiply(c, c);
|
||
|
|
output.b1 = float4(c, c2) * a;
|
||
|
|
#ifdef _MOMENT8
|
||
|
|
output.b2 = float4(Multiply(c, c2), Multiply(c2, c2)) * a;
|
||
|
|
#elif defined(_MOMENT6)
|
||
|
|
output.b2 = Multiply(c, c2) * a;
|
||
|
|
#endif
|
||
|
|
#else // not _TRIGONOMETRIC
|
||
|
|
float d2 = d * d;
|
||
|
|
float d4 = d2 * d2;
|
||
|
|
|
||
|
|
#if _MOMENT_HALF_PRECISION // QUANTIZE (ROVs ONLY)
|
||
|
|
#ifdef _MOMENT8
|
||
|
|
float4 b_even = (float4) 0;
|
||
|
|
float4 b_odd = (float4) 0;;
|
||
|
|
offsetMoments(b_even, b_odd, -1.0);
|
||
|
|
b_even *= output.b0;
|
||
|
|
b_odd *= output.b0;
|
||
|
|
|
||
|
|
float d6 = d4 * d2;
|
||
|
|
float4 b_even_new = float4(d2, d4, d6, d6 * d2);
|
||
|
|
float4 b_odd_new = float4(d, d2 * d, d4 * d, d6 * d);
|
||
|
|
float4 b_even_new_q, b_odd_new_q;
|
||
|
|
#elif defined(_MOMENT6)
|
||
|
|
float3 b_even = (float3) 0;
|
||
|
|
float3 b_odd = (float3) 0;
|
||
|
|
offsetMoments(b_even, b_odd, -1.0);
|
||
|
|
b_even *= output.b0;
|
||
|
|
b_odd *= output.b0;
|
||
|
|
|
||
|
|
float3 b_even_new = float3(d2, d4, d4 * d2);
|
||
|
|
float3 b_odd_new = float3(d, d2 * d, d4 * d);
|
||
|
|
float3 b_even_new_q, b_odd_new_q;
|
||
|
|
#else // _MOMENT4
|
||
|
|
float2 b_even = (float2) 0;
|
||
|
|
float2 b_odd = (float2) 0;
|
||
|
|
offsetMoments(b_even, b_odd, -1.0);
|
||
|
|
b_even *= output.b0;
|
||
|
|
b_odd *= output.b0;
|
||
|
|
|
||
|
|
float2 b_even_new = float2(d2, d4);
|
||
|
|
float2 b_odd_new = float2(d, d2 * d);
|
||
|
|
float2 b_even_new_q, b_odd_new_q;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
quantizeMoments(b_even_new_q, b_odd_new_q, b_even_new, b_odd_new);
|
||
|
|
// combine moments
|
||
|
|
b_even += b_even_new_q * a;
|
||
|
|
b_odd += b_odd_new_q * a;
|
||
|
|
// go back to interval [0, 1]
|
||
|
|
b_even /= a;
|
||
|
|
b_odd /= a;
|
||
|
|
offsetMoments(b_even, b_odd, 1.0);
|
||
|
|
output.b1 = float4(b_odd.x, b_even.x, b_odd.y, b_even.y);
|
||
|
|
#ifdef _MOMENT8
|
||
|
|
output.b2 = float4(b_odd.z, b_even.z, b_odd.w, b_even.w);
|
||
|
|
#elif defined(_MOMENT6)
|
||
|
|
output.b2 = float2(b_odd.z, b_even.z);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#else // _MOMENT_SINGLE_PRECISION
|
||
|
|
output.b1 = float4(d, d2, d2 * d, d4) * a;
|
||
|
|
#ifdef _MOMENT8
|
||
|
|
output.b2 = output.b1 * d4;
|
||
|
|
#elif defined(_MOMENT6)
|
||
|
|
output.b2 = output.b1.xy * d4;
|
||
|
|
#endif
|
||
|
|
#endif // precision end
|
||
|
|
#endif // TRIGONOMETRIC end
|
||
|
|
|
||
|
|
return output;
|
||
|
|
}
|