Selaa lähdekoodia

Add occlusionFactor for direct lights
Opti for point shadows

ShiroSmith 6 vuotta sitten
vanhempi
commit
c09f0e41a3

+ 46 - 19
h3d/pass/PointShadowMap.hx

@@ -53,6 +53,7 @@ class PointShadowMap extends Shadows {
 	override function dispose() {
 		super.dispose();
 		if( customDepth && depth != null ) depth.dispose();
+		if( tmpTex != null) tmpTex.dispose();
 	}
 
 	override function isUsingWorldDist(){
@@ -130,23 +131,35 @@ class PointShadowMap extends Shadows {
 		return true;
 	}
 
+	static var tmpTex : h3d.mat.Texture;
 	override function createDefaultShadowMap() {
-		var tex = new h3d.mat.Texture(1,1, [Target,Cube], format);
-		tex.name = "defaultCubeShadowMap";
+		if( tmpTex != null) return tmpTex;
+		tmpTex = new h3d.mat.Texture(1,1, [Target,Cube], format);
+		tmpTex.name = "defaultCubeShadowMap";
 		for(i in 0 ... 6)
-			tex.clear(0xFFFFFF, i);
-		return tex;
+			tmpTex.clear(0xFFFFFF, i);
+		return tmpTex;
 	}
 
 	override function draw( passes, ?sort ) {
 		if( !filterPasses(passes) )
 			return;
 
+		if( passes.isEmpty() ) {
+			syncShader(staticTexture == null ? createDefaultShadowMap() : staticTexture);
+			return;
+		}
+
 		var pointLight = cast(light, h3d.scene.pbr.PointLight);
 		var absPos = light.getAbsPos();
 		var sp = new h3d.col.Sphere(absPos.tx, absPos.ty, absPos.tz, pointLight.range);
 		cullPasses(passes,function(col) return col.inSphere(sp));
 
+		if( passes.isEmpty() ) {
+			syncShader(staticTexture == null ? createDefaultShadowMap() : staticTexture);
+			return;
+		}
+
 		var texture = ctx.textures.allocTarget("pointShadowMap", size, size, false, format, true);
 		if(depth == null || depth.width != size || depth.height != size || depth.isDisposed() ) {
 			if( depth != null ) depth.dispose();
@@ -154,51 +167,65 @@ class PointShadowMap extends Shadows {
 		}
 		texture.depthBuffer = depth;
 
-		var validBakedTexture = (staticTexture != null && staticTexture.width == texture.width);
-		var merge : h3d.mat.Texture = null;
-		if( mode == Mixed && !ctx.computingStatic && validBakedTexture)
-			merge = ctx.textures.allocTarget("mergedPointShadowMap", size, size, false, format, true);
-
 		lightCamera.pos.set(absPos.tx, absPos.ty, absPos.tz);
 		lightCamera.zFar = pointLight.range;
 		lightCamera.zNear = pointLight.zNear;
 
 		for( i in 0...6 ) {
-			lightCamera.setCubeMap(i);
-			lightCamera.update();
-
-			ctx.engine.pushTarget(texture, i);
-			ctx.engine.clear(0xFFFFFF, 1);
 
+			// Shadows on the current face is disabled
 			if( !faceMask.has(CubeFaceFlag.createByIndex(i)) ) {
-				ctx.engine.popTarget();
+				texture.clear(0xFFFFFF, 0, i);
 				continue;
 			}
 
+			lightCamera.setCubeMap(i);
+			lightCamera.update();
+
 			var save = passes.save();
 			cullPasses(passes, function(col) return col.inFrustum(lightCamera.frustum));
+			if( passes.isEmpty() ) {
+				passes.load(save);
+				texture.clear(0xFFFFFF, 0, i);
+				continue;
+			}
+
+			ctx.engine.pushTarget(texture, i);
+			ctx.engine.clear(0xFFFFFF, 1);
+
 			super.draw(passes,sort);
 			passes.load(save);
 			ctx.engine.popTarget();
 		}
 
+		// Blur is applied even if there's no shadows - TO DO : remove the useless blur pass
 		if( blur.radius > 0 )
 			blur.apply(ctx, texture);
 
+		if( mode == Mixed && !ctx.computingStatic )
+			syncShader(merge(texture));
+		else
+			syncShader(texture);
+	}
+
+	function merge( dynamicTex : h3d.mat.Texture ) : h3d.mat.Texture{
+		var validBakedTexture = (staticTexture != null && staticTexture.width == dynamicTex.width);
+		var merge : h3d.mat.Texture = null;
+		if( mode == Mixed && !ctx.computingStatic && validBakedTexture)
+			merge = ctx.textures.allocTarget("mergedPointShadowMap", size, size, false, format, true);
+
 		if( mode == Mixed && !ctx.computingStatic && merge != null ) {
 			for( i in 0 ... 6 ) {
 				if( !faceMask.has(CubeFaceFlag.createByIndex(i)) ) continue;
-				mergePass.shader.texA = texture;
+				mergePass.shader.texA = dynamicTex;
 				mergePass.shader.texB = staticTexture;
 				mergePass.shader.mat = cubeDir[i];
 				ctx.engine.pushTarget(merge, i);
 				mergePass.render();
 				ctx.engine.popTarget();
 			}
-			texture = merge;
 		}
-
-		syncShader(texture);
+		return merge;
 	}
 
 	function updateCamera(){

+ 1 - 0
h3d/scene/pbr/DirLight.hx

@@ -27,6 +27,7 @@ class DirLight extends Light {
 		pbr.lightDir.load(absPos.front());
 		pbr.lightDir.scale3(-1);
 		pbr.lightDir.normalize();
+		pbr.occlusionFactor = occlusionFactor;
 		super.emit(ctx);
 	}
 

+ 1 - 0
h3d/scene/pbr/Light.hx

@@ -7,6 +7,7 @@ class Light extends h3d.scene.Light {
 	@:s public var power : Float = 1.;
 	public var shadows : h3d.pass.Shadows;
 	public var isMainLight = false;
+	public var occlusionFactor : Float;
 
 	function new(shader,?parent) {
 		super(shader,parent);

+ 1 - 0
h3d/scene/pbr/PointLight.hx

@@ -50,6 +50,7 @@ class PointLight extends Light {
 		pbr.lightPos.set(absPos.tx, absPos.ty, absPos.tz);
 		pbr.invLightRange4 = 1 / (range * range * range * range);
 		pbr.pointSize = size;
+		pbr.occlusionFactor = occlusionFactor;
 	}
 
 	var s = new h3d.col.Sphere();

+ 1 - 0
h3d/scene/pbr/SpotLight.hx

@@ -116,6 +116,7 @@ class SpotLight extends Light {
 		pbr.fallOff = hxd.Math.cos(hxd.Math.degToRad(hxd.Math.min(angle/2.0, fallOff)));
 		pbr.range = hxd.Math.min(range, maxRange);
 		pbr.invLightRange4 = 1 / (maxRange * maxRange * maxRange * maxRange);
+		pbr.occlusionFactor = occlusionFactor;
 
 		if(cookie != null){
 			pbr.useCookie = true;

+ 5 - 1
h3d/shader/pbr/Light.hx

@@ -6,11 +6,12 @@ class Light extends hxsl.Shader {
 
 		var pbrLightDirection : Vec3;
 		var pbrLightColor : Vec3;
+		var pbrOcclusionFactor : Float;
 		var transformedPosition : Vec3;
 		var occlusion : Float;
 
 		@param var lightColor = vec3(0.5, 0.5, 0.5);
-
+		@param var occlusionFactor = 0.0;
 	};
 }
 
@@ -30,6 +31,7 @@ class SpotLight extends Light {
 		@param var cookieTex : Sampler2D;
 
 		function fragment() {
+			pbrOcclusionFactor = occlusionFactor;
 			pbrLightDirection = normalize(lightPos - transformedPosition);
 
 			var delta = lightPos - transformedPosition;
@@ -75,6 +77,7 @@ class PointLight extends Light {
 		@param var pointSize : Float;
 
 		function fragment() {
+			pbrOcclusionFactor = occlusionFactor;
 			var delta = lightPos - transformedPosition;
 			pbrLightDirection = delta.normalize();
 			/*
@@ -103,6 +106,7 @@ class DirLight extends Light {
 		function fragment() {
 			pbrLightDirection = lightDir;
 			pbrLightColor = lightColor;
+			pbrOcclusionFactor = occlusionFactor;
 		}
 	};
 }

+ 2 - 1
h3d/shader/pbr/Lighting.hx

@@ -66,6 +66,7 @@ class Direct extends PropsDefinition {
 
 		var pbrLightDirection : Vec3;
 		var pbrLightColor : Vec3;
+		var pbrOcclusionFactor : Float;
 		@const var doDiscard : Bool = true;
 
 		function fragment() {
@@ -113,7 +114,7 @@ class Direct extends PropsDefinition {
 				var specular = (D * F * G_Att).max(0.);
 
 				var direct = (diffuse * (1 - metalness) * (1 - F) + specular) * pbrLightColor * NdL;
-				pixelColor.rgb += direct * shadow;
+				pixelColor.rgb += direct * shadow * mix(1, occlusion, pbrOcclusionFactor);
 			} else if( doDiscard )
 				discard;
 		}