From 19313d4635716306719193e769221c3e33bea5cd Mon Sep 17 00:00:00 2001
From: Alex Laptop <alexander.gauggel@web.de>
Date: Fri, 17 Sep 2021 15:19:14 +0200
Subject: [PATCH] [#114] Switch to newer MSM quantization scheme and reduce
 moment blur radius from 9 to 7 pixels to reduce floating point precision
 problems and make it work on iGPU

---
 .../assets/shaders/depthToMoments.comp        |  4 +-
 .../assets/shaders/shadowBlur.inc             |  2 +-
 .../assets/shaders/shadowBlurX.comp           |  2 +-
 .../assets/shaders/shadowBlurY.comp           |  6 +--
 .../assets/shaders/shadowMapping.inc          | 38 ++++++++++---------
 5 files changed, 27 insertions(+), 25 deletions(-)

diff --git a/projects/voxelization/assets/shaders/depthToMoments.comp b/projects/voxelization/assets/shaders/depthToMoments.comp
index 5a78d0cb..79e47cde 100644
--- a/projects/voxelization/assets/shaders/depthToMoments.comp
+++ b/projects/voxelization/assets/shaders/depthToMoments.comp
@@ -28,9 +28,11 @@ void main(){
         z += texelFetch(sampler2DMS(srcTexture, depthSampler), uv, i).r;
     }
     z /= msaaCount;
-    
+    z = 2 * z - 1;	// algorithm expects depth in range [-1:1]
+	
     float   z2                  = z*z;   
     vec4    moments             = vec4(z, z2, z2*z, z2*z2);
     vec4    momentsQuantized    = quantizeMoments(moments);
+	
     imageStore(outImage, uv, momentsQuantized);
 }
\ No newline at end of file
diff --git a/projects/voxelization/assets/shaders/shadowBlur.inc b/projects/voxelization/assets/shaders/shadowBlur.inc
index 06147415..ed4994ed 100644
--- a/projects/voxelization/assets/shaders/shadowBlur.inc
+++ b/projects/voxelization/assets/shaders/shadowBlur.inc
@@ -3,7 +3,7 @@
 
 vec4 blurMomentShadowMap1D(ivec2 coord, ivec2 blurDirection, texture2D srcTexture, sampler depthSampler){
     
-    int blurRadius  = 9;
+    int blurRadius  = 7;
     int minOffset   = -(blurRadius-1) / 2;
     int maxOffset   = -minOffset;
     
diff --git a/projects/voxelization/assets/shaders/shadowBlurX.comp b/projects/voxelization/assets/shaders/shadowBlurX.comp
index 45b91aad..41d127fd 100644
--- a/projects/voxelization/assets/shaders/shadowBlurX.comp
+++ b/projects/voxelization/assets/shaders/shadowBlurX.comp
@@ -18,6 +18,6 @@ void main(){
     }
     ivec2 coord = ivec2(gl_GlobalInvocationID.xy);    
     vec4 moments = blurMomentShadowMap1D(coord, ivec2(1, 0), srcTexture, depthSampler);
-    
+    // moments = texelFetch(sampler2D(srcTexture, depthSampler), coord, 0);
     imageStore(outImage, coord, moments);
 }
\ No newline at end of file
diff --git a/projects/voxelization/assets/shaders/shadowBlurY.comp b/projects/voxelization/assets/shaders/shadowBlurY.comp
index 51d4df05..c1710d7d 100644
--- a/projects/voxelization/assets/shaders/shadowBlurY.comp
+++ b/projects/voxelization/assets/shaders/shadowBlurY.comp
@@ -16,10 +16,8 @@ void main(){
     if(any(greaterThanEqual(gl_GlobalInvocationID.xy, imageSize(outImage)))){
         return;
     }
-    ivec2 coord = ivec2(gl_GlobalInvocationID.xy);
-    vec2 pixelSize = vec2(1) / textureSize(sampler2D(srcTexture, depthSampler), 0);
-    
+    ivec2 coord = ivec2(gl_GlobalInvocationID.xy);    
     vec4 moments = blurMomentShadowMap1D(coord, ivec2(0, 1), srcTexture, depthSampler);
-    
+    // moments = texelFetch(sampler2D(srcTexture, depthSampler), coord, 0);
     imageStore(outImage, coord, moments);
 }
\ No newline at end of file
diff --git a/projects/voxelization/assets/shaders/shadowMapping.inc b/projects/voxelization/assets/shaders/shadowMapping.inc
index c56ae898..9d65a2d3 100644
--- a/projects/voxelization/assets/shaders/shadowMapping.inc
+++ b/projects/voxelization/assets/shaders/shadowMapping.inc
@@ -6,7 +6,8 @@
 // nice math blob from the moment shadow mapping presentation
 float ComputeMSMShadowIntensity(vec4 _4Moments, float FragmentDepth, float DepthBias, float MomentBias)
 {
-    vec4 b=mix(_4Moments, vec4(0.5),MomentBias);
+    vec4 b=mix(_4Moments, vec4(0, 0.63, 0, 0.63),MomentBias);
+	
     vec3 z;
     z[0]=FragmentDepth-DepthBias;
     float L32D22=fma(-b[0], b[1], b[2]);
@@ -39,24 +40,23 @@ float ComputeMSMShadowIntensity(vec4 _4Moments, float FragmentDepth, float Depth
 }
 
 vec4 quantizeMoments(vec4 moments){
-    mat4 T = mat4(
-        -2.07224649,     13.7948857237,   0.105877704,   9.7924062118,
-         32.23703778,   -59.4683975703, -1.9077466311, -33.7652110555,
-        -68.571074599,   82.0359750338,  9.3496555107,  47.9456096605,
-         39.3703274134, -35.364903257,  -6.6543490743, -23.9728048165);
-    vec4 quantized = T * moments;
-    quantized[0] += 0.0359558848;
-    return quantized;
+    vec4 quantized;
+	quantized.r = 1.5 * moments.r - 2 * moments.b + 0.5;
+	quantized.g = 4   * moments.g - 4 * moments.a;
+	quantized.b = sqrt(3)/2 * moments.r - sqrt(12)/9 * moments.b + 0.5;
+	quantized.a = 0.5 * moments.g + 0.5 * moments.a;
+	
+	return quantized;
 }
 
 vec4 unquantizeMoments(vec4 moments){
-    moments[0] -= 0.0359558848;
-    mat4 T = mat4(
-        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);
-    return T * moments;
+    moments -= vec4(0.5, 0, 0.5, 0);
+	vec4 unquantized;
+	unquantized.r = -1.f / 3 * moments.r + sqrt(3) * moments.b;
+	unquantized.g = 0.125 * moments.g + moments.a;
+	unquantized.b = -0.75 * moments.r + 0.75 * sqrt(3) * moments.b;
+	unquantized.a = -0.125 * moments.g + moments.a;
+	return unquantized * 0.98;
 }
 
 float rescaleRange(float a, float b, float v)
@@ -78,17 +78,19 @@ float shadowTest(vec3 worldPos, LightInfo lightInfo, texture2D shadowMap, sample
     if(any(lessThan(lightPos.xy, vec2(0))) || any(greaterThan(lightPos.xy, vec2(1)))){
         return 1;
     }
-    
+	
     lightPos.z = clamp(lightPos.z, 0, 1);
+	lightPos.z = 2 * lightPos.z - 1;	// algorithm expects depth in range [-1:1]
 
     vec4 shadowMapSample = texture(sampler2D(shadowMap, shadowMapSampler), lightPos.xy);
     
     shadowMapSample = unquantizeMoments(shadowMapSample);
     
     float depthBias     = 0.f;
-    float momentBias    = 0.0003;
+    float momentBias    = 0.0006;
     
     float shadow = ComputeMSMShadowIntensity(shadowMapSample, lightPos.z, depthBias, momentBias);
+	return clamp(shadow, 0, 1);
     return reduceLightBleeding(shadow, 0.1f);
 }
 
-- 
GitLab