Parcourir la source

Restore Cascade shadow mapping on pbr forward

clementlandrin il y a 1 an
Parent
commit
b03c3abdd2

+ 11 - 1
h3d/pass/CascadeShadowMap.hx

@@ -15,7 +15,6 @@ typedef CascadeCamera = {
 class CascadeShadowMap extends DirShadowMap {
 
 	var cshader : h3d.shader.CascadeShadow;
-	var cascadeViewProj = new h3d.Matrix();
 	var lightCameras : Array<CascadeCamera> = [];
 	var currentCascadeIndex = 0;
 	var tmpCorners : Array<h3d.Vector> = [for (i in 0...8) new h3d.Vector()];
@@ -23,6 +22,7 @@ class CascadeShadowMap extends DirShadowMap {
 	var tmpProj = new h3d.Matrix();
 	var tmpFrustum = new h3d.col.Frustum();
 
+	public var cascadeViewProj = new h3d.Matrix();
 	public var params : Array<CascadeParams> = [];
 	public var pow : Float = 1.0;
 	// minimum count of pixels in ratio of texture width for an object to be drawn in cascade
@@ -202,6 +202,16 @@ class CascadeShadowMap extends DirShadowMap {
 		return lightCameras[i].viewProj;
 	}
 
+	public function getCascadeOffset(i:Int) {
+		var i = hxd.Math.imin(i, lightCameras.length - 1);
+		return lightCameras[i].offset;
+	}
+
+	public function getCascadeScale(i:Int) {
+		var i = hxd.Math.imin(i, lightCameras.length - 1);
+		return lightCameras[i].scale;
+	}
+
 	function syncCascadeShader(textures : Array<h3d.mat.Texture>) {
 		cshader.DEBUG = debugShader;
 		cshader.cascadeViewProj = cascadeViewProj;

+ 10 - 1
h3d/scene/pbr/LightBuffer.hx

@@ -26,7 +26,7 @@ class LightBuffer {
 	final POINT_LIGHT_INFO_SIZE = 3;
 	final SPOT_LIGHT_INFO_SIZE = 8;
 	final DIR_LIGHT_INFO_SIZE = 5;
-	final CASCADE_SHADOW_INFO_SIZE = 15;
+	final CASCADE_SHADOW_INFO_SIZE = 13;
 
 
 	public function new() {
@@ -323,6 +323,15 @@ class LightBuffer {
 			var cascadeShadow = cast(cascadeLight.shadows, CascadeShadowMap);
 			var shadowMaps = cascadeShadow.getShadowTextures();
 			s.CASCADE_COUNT = cascadeShadow.cascade;
+			var mat = cascadeShadow.cascadeViewProj;
+			fillFloats(lightInfos, mat._11, mat._21, mat._31, mat._41, i+8);
+			fillFloats(lightInfos, mat._12, mat._22, mat._32, mat._42, i+12);
+			fillFloats(lightInfos, mat._13, mat._23, mat._33, mat._43, i+16);
+			for ( index in 0...cascadeShadow.cascade ) {
+				s.cascadeShadowMaps[index] = shadowMaps[index];
+				fillVector(lightInfos, cascadeShadow.getCascadeScale(index).toVector(), i + 20 + index * 8);
+				fillVector(lightInfos, cascadeShadow.getCascadeOffset(index).toVector(), i + 24 + index * 8);
+			}
 		}
 
 		s.dirLightCount = dirLights.length;

+ 3 - 3
h3d/shader/CascadeShadow.hx

@@ -71,10 +71,10 @@ class CascadeShadow extends DirShadow {
 				var vPos = vec4(transformedPosition, 1.0) * camera.view;
 				vPos /= vPos.w;
 
-				var cascadeFound = false;
+				var found = false;
 				@unroll for ( i in 0...CASCADE_COUNT ) {
-					if ( !cascadeFound && vPos.z <= cascadeScales[i].w ) {
-						cascadeFound = true;
+					if ( !found && vPos.z <= cascadeScales[i].w ) {
+						found = true;
 
 						var shadowPos0 = transformedPosition * cascadeViewProj;
 						var shadowPos = ( i == 0 ) ? shadowPos0 : shadowPos0 * cascadeScales[i].xyz + cascadeOffsets[i].xyz;

+ 14 - 8
h3d/shader/pbr/DefaultForward.hx

@@ -4,6 +4,12 @@ class DefaultForward extends hxsl.Shader {
 
 	static var SRC = {
 
+		@global var camera : {
+			var view : Mat4;
+			var position : Vec3;
+			var inverseViewProj : Mat4;
+		}
+
 		@const(4) var CASCADE_COUNT:Int;
 		@const(2) var DIR_SHADOW_COUNT:Int;
 		@const(16) var POINT_SHADOW_COUNT:Int;
@@ -211,19 +217,19 @@ class DefaultForward extends hxsl.Shader {
 
 		function evaluateCascadeShadow() : Float {
 			var i = dirLightStride + pointLightStride + spotLightStride;
-			var bias = lightInfos[i + 2 + 3 * 4];
-			var bias = [bias.x, bias.y, bias.z, bias.w];
 			var shadow = 1.0;
+			var shadowProj = mat3x4(lightInfos[i + 2], lightInfos[i + 3], lightInfos[i + 4]);
+
 			@unroll for ( c in 0...CASCADE_COUNT ) {
-				var offset = i + 2 + 3 * c;
-				var shadowProj = mat3x4(lightInfos[offset], lightInfos[offset+1], lightInfos[offset+2]);
-				var shadowPos = transformedPosition * shadowProj;
+				var cascadeScale = lightInfos[i + 5 + 2 * c];
+				var shadowPos0 = transformedPosition * shadowProj;
+				var shadowPos = i == 0 ? shadowPos0 : shadowPos0 * cascadeScale.xyz + lightInfos[i + 6 + 2 * c].xyz;
 				if ( inside(shadowPos) ) {
-					shadow = 1.0;
 					var zMax = saturate(shadowPos.z);
-					var shadowUv = screenToUv(shadowPos.xy);
+					var shadowUv = shadowPos.xy;
+					shadowUv.y = 1.0 - shadowUv.y;
 					var depth = cascadeShadowMaps[c].get(shadowUv.xy).r;
-					shadow -= (zMax - bias[c] > depth) ? 1.0 : 0.0;
+					shadow -= zMax > depth ? 1.0 : 0.0;
 				}
 			}
 			return saturate(shadow);