浏览代码

shaderLibrary: update moment shadow map to force explicit float

/feature-ReflectionProbeFit
sebastienlagarde 7 年前
当前提交
cafc9c36
共有 1 个文件被更改,包括 37 次插入37 次删除
  1. 74
      ScriptableRenderPipeline/Core/ShaderLibrary/Shadow/ShadowMoments.hlsl

74
ScriptableRenderPipeline/Core/ShaderLibrary/Shadow/ShadowMoments.hlsl


// Chebychev's inequality (one-tailed version)
// P( x >= t ) <= pmax(t) := sigma^2 / (sigma^2 + (t - u)^2)
// for us t is depth, u is E(x) i.d. the blurred depth
real ShadowMoments_ChebyshevsInequality( real2 moments, real depth, real minVariance, real lightLeakBias )
float ShadowMoments_ChebyshevsInequality( float2 moments, float depth, float minVariance, float lightLeakBias )
real variance = max( moments.y - (moments.x * moments.x), minVariance );
float variance = max( moments.y - (moments.x * moments.x), minVariance );
real mD = depth - moments.x;
real p = variance / (variance + mD * mD);
float mD = depth - moments.x;
float p = variance / (variance + mD * mD);
p = saturate( (p - lightLeakBias) / (1.0 - lightLeakBias) );
return max( p, depth <= moments.x );

real2 ShadowMoments_WarpDepth( real depth, real2 exponents )
float2 ShadowMoments_WarpDepth( float depth, float2 exponents )
real pos = exp( exponents.x * depth );
real neg = -exp(-exponents.y * depth );
return real2( pos, neg );
float pos = exp( exponents.x * depth );
float neg = -exp(-exponents.y * depth );
return float2( pos, neg );
// Prepare the moments so there's little quantization error when storing the moments at real
// Prepare the moments so there's little quantization error when storing the moments at float
real4 ShadowMoments_Encode16MSM( real depth )
float4 ShadowMoments_Encode16MSM( float depth )
real dsq = depth * depth;
real4 moments = { depth, dsq, depth * dsq, dsq * dsq };
real4x4 mat = { - 2.07224649 , 13.7948857237, 0.105877704 , 9.7924062118,
float dsq = depth * depth;
float4 moments = { depth, dsq, depth * dsq, dsq * dsq };
float4x4 mat = { - 2.07224649 , 13.7948857237, 0.105877704 , 9.7924062118,
real4 optimized = mul( moments, mat );
float4 optimized = mul( moments, mat );
real4 ShadowMoments_Decode16MSM( real4 moments )
float4 ShadowMoments_Decode16MSM( float4 moments )
real4x4 mat = { 0.2227744146, 0.1549679261, 0.1451988946, 0.163127443,
float4x4 mat = { 0.2227744146, 0.1549679261, 0.1451988946, 0.163127443,
0.0771972861, 0.1394629426, 0.2120202157, 0.2591432266,
0.7926986636, 0.7963415838, 0.7258694464, 0.6539092497,
0.0319417555, -0.1722823173, -0.2758014811, -0.3376131734 };

// Note: Don't call this with all moments being equal or 0.0, otherwise this code degenerates into lots of +/-inf calculations
// which don't behave quite the same on all hardware.
void ShadowMoments_SolveMSM( real4 moments, real depth, real momentBias, out real3 z, out real4 b )
void ShadowMoments_SolveMSM( float4 moments, float depth, float momentBias, out float3 z, out float4 b )
{
// Bias input data to avoid artifacts
z[0] = depth;

real L32D22 = mad( -b[0], b[1], b[2] );
real D22 = mad( -b[0], b[0], b[1] );
real sqDepthVar = mad( -b[1], b[1], b[3] );
real D33D22 = dot( real2( sqDepthVar, -L32D22 ), real2( D22, L32D22 ) );
real InvD22 = 1.0 / D22;
real L32 = L32D22 * InvD22;
float L32D22 = mad( -b[0], b[1], b[2] );
float D22 = mad( -b[0], b[0], b[1] );
float sqDepthVar = mad( -b[1], b[1], b[3] );
float D33D22 = dot( float2( sqDepthVar, -L32D22 ), float2( D22, L32D22 ) );
float InvD22 = 1.0 / D22;
float L32 = L32D22 * InvD22;
real3 c = real3( 1.0, z[0], z[0] * z[0] );
float3 c = float3( 1.0, z[0], z[0] * z[0] );
// Forward substitution to solve L * c1 = bz;
c[1] -= b.x;
c[2] -= b.y + L32 * c[1];

c[1] -= L32 * c[2];
c[0] -= dot( c.yz, b.xy );
// Solve the quadratic equation c[0] + c[1] * z + c[2] * z^2 to obtain solutions z[1] and z[2]
real p = c[1] / c[2];
real q = c[0] / c[2];
real D = ((p*p) * 0.25) - q;
real r = sqrt( D );
float p = c[1] / c[2];
float q = c[0] / c[2];
float D = ((p*p) * 0.25) - q;
float r = sqrt( D );
real ShadowMoments_SolveDelta3MSM( real3 z, real2 b, real lightLeakBias )
float ShadowMoments_SolveDelta3MSM( float3 z, float2 b, float lightLeakBias )
real4 switchVal = (z[2] < z[0]) ? real4( z[1], z[0], 1.0, 1.0 )
: ((z[1] < z[0]) ? real4( z[0], z[1], 0.0, 1.0 ) : 0.0.xxxx);
float4 switchVal = (z[2] < z[0]) ? float4( z[1], z[0], 1.0, 1.0 )
: ((z[1] < z[0]) ? float4( z[0], z[1], 0.0, 1.0 ) : 0.0.xxxx);
real quotient = (switchVal[0] * z[2] - b[0] * (switchVal[0] + z[2]) + b[1]) / ((z[2] - switchVal[1]) * (z[0] - z[1]));
real attenuation = saturate( switchVal[2] + switchVal[3] * quotient );
float quotient = (switchVal[0] * z[2] - b[0] * (switchVal[0] + z[2]) + b[1]) / ((z[2] - switchVal[1]) * (z[0] - z[1]));
float attenuation = saturate( switchVal[2] + switchVal[3] * quotient );
real ShadowMoments_SolveDelta4MSM( real3 z, real4 b, real lightLeakBias)
float ShadowMoments_SolveDelta4MSM( float3 z, float4 b, float lightLeakBias)
real zFree = ((b[2] - b[1]) * z[0] + b[2] - b[3]) / ((b[1] - b[0]) * z[0] + b[1] - b[2]);
real w1Factor = (z[0] > zFree) ? 1.0 : 0.0;
real attenuation = saturate( (b[1] - b[0] + (b[2] - b[0] - (zFree + 1.0) * (b[1] - b[0])) * (zFree - w1Factor - z[0]) / (z[0] * (z[0] - zFree))) / (zFree - w1Factor) + 1.0 - b[0] );
float zFree = ((b[2] - b[1]) * z[0] + b[2] - b[3]) / ((b[1] - b[0]) * z[0] + b[1] - b[2]);
float w1Factor = (z[0] > zFree) ? 1.0 : 0.0;
float attenuation = saturate( (b[1] - b[0] + (b[2] - b[0] - (zFree + 1.0) * (b[1] - b[0])) * (zFree - w1Factor - z[0]) / (z[0] * (z[0] - zFree))) / (zFree - w1Factor) + 1.0 - b[0] );
return saturate( ((1.0 - attenuation) - lightLeakBias) / (1.0 - lightLeakBias) );
}
正在加载...
取消
保存