Parcourir la source

Improvement on CSM (debug shader and proper cascade selection).

clementlandrin il y a 2 ans
Parent
commit
7aeb335408
2 fichiers modifiés avec 60 ajouts et 42 suppressions
  1. 12 9
      h3d/pass/CascadeShadowMap.hx
  2. 48 33
      h3d/shader/CascadeShadow.hx

+ 12 - 9
h3d/pass/CascadeShadowMap.hx

@@ -19,9 +19,13 @@ class CascadeShadowMap extends DirShadowMap {
 		}
 		return cascade;
 	}
+	public var debugShader : Bool = false;
+
+	static var debugColors = [0xff0000, 0x00ff00, 0x0000ff, 0xffff00, 0x00ffff, 0xff00ff, 0x000000];
 
 	public function new( light : h3d.scene.Light ) {
 		super(light);
+		format = R32F;
 		shader = dshader = cshader = new h3d.shader.CascadeShadow();
 	}
 
@@ -64,8 +68,8 @@ class CascadeShadowMap extends DirShadowMap {
 			addCorners(near);
 			addCorners(far);
 			// Increasing z range has no effect on resolution, only on depth precision.
-			cascadeBounds.zMax = lightCamera.orthoBounds.zMax;
-			cascadeBounds.zMin = lightCamera.orthoBounds.zMin;
+			// cascadeBounds.zMax = lightCamera.orthoBounds.zMax;
+			// cascadeBounds.zMin = lightCamera.orthoBounds.zMin;
 			lightCameras[i].orthoBounds = cascadeBounds;
 
 			near = minDist + firstCascadeSize + hxd.Math.pow((i) / (cascade - 1), pow) * step;
@@ -84,19 +88,19 @@ class CascadeShadowMap extends DirShadowMap {
 	}
 
 	function syncCascadeShader(textures : Array<h3d.mat.Texture>) {
+		cshader.DEBUG = debugShader;
 		for ( i in 0...cascade ) {
-			cshader.cascadeShadowMaps[i] = textures[i];
-			cshader.cascadeProjs[i] = lightCameras[i].m;
+			cshader.cascadeShadowMaps[cascade - 1 - i] = textures[i];
+			cshader.cascadeProjs[cascade - 1 - i] = lightCameras[i].m;
+			if ( debugShader )
+				cshader.cascadeDebugs[cascade - 1 - i] = h3d.Vector.fromColor(debugColors[i]);
 		}
 		for ( i in 0...cascade-1 ) {
 			var pt = lightCameras[i].unproject(0,0,1);
 			pt.transform(ctx.camera.m);
-			cshader.cascadeLimits[i] = pt.z;
 		}
 		var pt = lightCamera.unproject(0,0,1);
 		pt.transform(ctx.camera.m);
-		cshader.cascadeLimits[cascade-1] = pt.z;
-		cshader.camViewProj = ctx.camera.m;
 		cshader.CASCADE_COUNT = cascade;
 		cshader.shadowBias = bias / lightCamera.orthoBounds.zSize;
 		cshader.shadowPower = power;
@@ -196,9 +200,8 @@ class CascadeShadowMap extends DirShadowMap {
 		if ( !debug )
 			return;
 
-		var colors = [0xff0000, 0x00ff00, 0x0000ff, 0xffff00, 0x00ffff, 0xff00ff, 0x000000];
 		for ( i in 0...cascade ) {
-			drawBounds(lightCameras[i], colors[i]);
+			drawBounds(lightCameras[i], debugColors[i]);
 		}
 	}
 }

+ 48 - 33
h3d/shader/CascadeShadow.hx

@@ -4,50 +4,65 @@ class CascadeShadow extends DirShadow {
 
 	static var SRC = {
 
+		var pixelColor : Vec4;
+
 		@const(5) var CASCADE_COUNT:Int;
+		@const var DEBUG : Bool;
 		@param var cascadeShadowMaps : Array<Sampler2D, CASCADE_COUNT>;
 		@param var cascadeProjs : Array<Mat3x4, CASCADE_COUNT>;
-		@param var cascadeLimits : Array<Float, CASCADE_COUNT>;
-		@param var camViewProj : Mat4;
+		@param var cascadeDebugs : Array<Vec4, CASCADE_COUNT>;
+
+		function inside(pos : Vec3) : Bool {
+			if ( abs(pos.x) < 1.0 && abs(pos.y) < 1.0 && abs(pos.z) < 1.0 ) {
+				return true;
+			} else {
+				return false;
+			}
+		}
 
 		function fragment() {
 			if( enable ) {
-				if( USE_PCF ) {
-					shadow = 1.0;
-					var texelSize = 1.0/shadowRes;
-					@unroll for ( c in 0...CASCADE_COUNT ) {
-						var shadowPos = transformedPosition * cascadeProjs[c];
+				shadow = 1.0;
+				var texelSize = 1.0/shadowRes;
+				@unroll for ( c in 0...CASCADE_COUNT ) {
+					var shadowPos = transformedPosition * cascadeProjs[c];
+					
+					if ( inside(shadowPos) ) {
+						shadow = 1.0;
 						var zMax = shadowPos.z.saturate();
 						var shadowUv = screenToUv(shadowPos.xy);
-
-						var rot = rand(transformedPosition.x + transformedPosition.y + transformedPosition.z) * 3.14 * 2;
-						var cosR = cos(rot);
-						var sinR = sin(rot);
-						var sampleStrength = 1.0 / PCF_SAMPLES;
-						var offScale = texelSize * pcfScale;
-						for(i in 0...PCF_SAMPLES) {
-							var offset = poissonDisk[i].xy * offScale;
-							offset = vec2(cosR * offset.x - sinR * offset.y, cosR * offset.y + sinR * offset.x);
-							var depth = cascadeShadowMaps[c].getLod(shadowUv + offset, 0).r;
-							shadow  -= (zMax - shadowBias > depth) ? sampleStrength : 0.0;
+						if( USE_PCF ) {
+							var rot = rand(transformedPosition.x + transformedPosition.y + transformedPosition.z) * 3.14 * 2;
+							var cosR = cos(rot);
+							var sinR = sin(rot);
+							var sampleStrength = 1.0 / PCF_SAMPLES;
+							var offScale = texelSize * pcfScale;
+							for(i in 0...PCF_SAMPLES) {
+								var offset = poissonDisk[i].xy * offScale;
+								offset = vec2(cosR * offset.x - sinR * offset.y, cosR * offset.y + sinR * offset.x);
+								var depth = cascadeShadowMaps[c].getLod(shadowUv + offset, 0).r;
+								shadow  -= (zMax - shadowBias > depth) ? sampleStrength : 0.0;
+							}
+						}
+						else if( USE_ESM ) {
+							var depth = cascadeShadowMaps[c].get(shadowUv).r;
+							var delta = (depth + shadowBias).min(zMax) - zMax;
+							shadow = exp(shadowPower * delta).saturate();		
+						}
+						else {
+							var depth = cascadeShadowMaps[c].get(shadowUv).r;
+							shadow -= zMax - shadowBias > depth ? 1 : 0;
 						}
 					}
 				}
-				else if( USE_ESM ) {
-					var shadowPos = transformedPosition * cascadeProjs[0];
-					var zMax = shadowPos.z.saturate();
-					var depth = cascadeShadowMaps[0].get(screenToUv(shadowPos.xy)).r;
-					var delta = (depth + shadowBias).min(zMax) - zMax;
-					shadow = exp(shadowPower * delta).saturate();
-				}
-				else {
-					shadow = 1.0;
-					@unroll for ( c in 0...CASCADE_COUNT ) {
-						var shadowPos = transformedPosition * cascadeProjs[c];
-						var shadowUv = screenToUv(shadowPos.xy);
-						var zMax = shadowPos.z.saturate();
-						var depth = cascadeShadowMaps[c].get(shadowUv).r;
-						shadow -= zMax - shadowBias > depth ? 1 : 0;
+			}
+
+			if ( DEBUG ) {
+				pixelColor = vec4(1.0, 1.0, 1.0, 1.0);
+				@unroll for ( c in 0...CASCADE_COUNT ) {
+					var shadowPos = transformedPosition * cascadeProjs[c];
+					if ( inside(shadowPos) ) {
+						pixelColor.rgb = cascadeDebugs[c].rgb;
 					}
 				}
 			}