Browse Source

refactor ao/shadows, allow shadowmap dependent shader, added tone mode

ncannasse 7 years ago
parent
commit
50ea2f1546

+ 1 - 1
h3d/mat/PbrMaterial.hx

@@ -136,7 +136,7 @@ class PbrMaterial extends Material {
 		var props : PbrProps = props;
 		return new js.jquery.JQuery('
 			<dl>
-				<dt>Kind</dt>
+				<dt>Mode</dt>
 				<dd>
 					<select field="mode">
 						<option value="PBR">PBR</option>

+ 15 - 1
h3d/pass/ShadowMap.hx

@@ -10,6 +10,8 @@ class ShadowMap extends Default {
 	var shadowBiasId : Int;
 	var customDepth : Bool;
 	var depth : h3d.mat.DepthBuffer;
+	var dshader : h3d.shader.DirShadow;
+
 	@ignore public var border : Border;
 	public var size(default,set) : Int;
 	public var color : h3d.Vector;
@@ -17,6 +19,8 @@ class ShadowMap extends Default {
 	public var bias = 0.01;
 	public var blur : Blur;
 
+	public var shader(default,null) : hxsl.Shader;
+
 	public function new(size=1024) {
 		super("shadow");
 		this.size = size;
@@ -27,6 +31,7 @@ class ShadowMap extends Default {
 		shadowColorId = hxsl.Globals.allocID("shadow.color");
 		shadowPowerId = hxsl.Globals.allocID("shadow.power");
 		shadowBiasId = hxsl.Globals.allocID("shadow.bias");
+		shader = dshader = new h3d.shader.DirShadow();
 		color = new h3d.Vector();
 		blur = new Blur(2, 3);
 		border = new Border(size, size);
@@ -116,6 +121,10 @@ class ShadowMap extends Default {
 		cameraViewProj = lightCamera.m;
 	}
 
+	public function getShadowProj() {
+		return lightCamera.m;
+	}
+
 	override function draw( passes ) {
 		var texture = ctx.textures.allocTarget("shadowMap", size, size, false);
 		if( customDepth && (depth == null || depth.width != size || depth.height != size || depth.isDisposed()) ) {
@@ -147,8 +156,13 @@ class ShadowMap extends Default {
 		if( blur.quality > 0 && blur.passes > 0 )
 			blur.apply(texture, ctx.textures.allocTarget("tmpBlur", size, size, false), true);
 
+		dshader.shadowMap = texture;
+		dshader.shadowBias = bias;
+		dshader.shadowPower = power;
+		dshader.shadowProj = getShadowProj();
+
 		ctx.setGlobalID(shadowMapId, { texture : texture });
-		ctx.setGlobalID(shadowProjId, lightCamera.m);
+		ctx.setGlobalID(shadowProjId, getShadowProj());
 		ctx.setGlobalID(shadowColorId, color);
 		ctx.setGlobalID(shadowPowerId, power);
 		ctx.setGlobalID(shadowBiasId, bias);

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

@@ -5,7 +5,7 @@ class Light extends h3d.scene.Light {
 	var _color : h3d.Vector;
 	var primitive : h3d.prim.Primitive;
 	@:s public var power : Float = 1.;
-	public var isSun(get,set) : Bool;
+	public var shadows : hxsl.Shader;
 
 	function new(shader,?parent) {
 		super(shader,parent);

+ 6 - 1
h3d/scene/pbr/LightSystem.hx

@@ -5,8 +5,11 @@ class LightSystem extends h3d.scene.LightSystem {
 
 	override function computeLight( obj : h3d.scene.Object, shaders : hxsl.ShaderList ) : hxsl.ShaderList {
 		var light = Std.instance(obj, h3d.scene.pbr.Light);
-		if( light != null )
+		if( light != null ) {
+			if( light.shadows != null )
+				shaders = ctx.allocShaderList(light.shadows, shaders);
 			return ctx.allocShaderList(light.shader, shaders);
+		}
 		return shaders;
 	}
 
@@ -19,9 +22,11 @@ class LightSystem extends h3d.scene.LightSystem {
 			if( light != shadowLight ) {
 				var light = Std.instance(light, h3d.scene.pbr.Light);
 				if( light != null && light.primitive == null ) {
+					if( light.shadows != null ) lightPass.addShader(light.shadows);
 					lightPass.addShader(light.shader);
 					lightPass.render();
 					lightPass.removeShader(light.shader);
+					if( light.shadows != null ) lightPass.addShader(light.shadows);
 				}
 			}
 			light = light.next;

+ 23 - 2
h3d/scene/pbr/Renderer.hx

@@ -25,12 +25,18 @@ package h3d.scene.pbr;
 	var Irrad = "Irrad";
 }
 
+@:enum abstract TonemapMap(String) {
+	var Linear = "Linear";
+	var Reinhard = "Reinhard";
+}
+
 typedef PbrRenderProps = {
 	var mode : DisplayMode;
 	var env : String;
 	var envPower : Float;
 	var exposure : Float;
 	var sky : SkyMode;
+	var tone : TonemapMap;
 }
 
 class Renderer extends h3d.scene.Renderer {
@@ -47,6 +53,7 @@ class Renderer extends h3d.scene.Renderer {
 	var pbrProps = new h3d.shader.pbr.PropsImport();
 
 	public var skyMode : SkyMode = Hide;
+	public var toneMode : TonemapMap = Reinhard;
 	public var displayMode : DisplayMode = Pbr;
 	public var env : Environment;
 	public var exposure(get,set) : Float;
@@ -66,7 +73,6 @@ class Renderer extends h3d.scene.Renderer {
 		defaultPass = new h3d.pass.Default("default");
 		pbrOut.addShader(new h3d.shader.ScreenShader());
 		pbrOut.addShader(pbrProps);
-		pbrOut.addShader(new h3d.shader.pbr.Shadow());
 		allPasses.push(output);
 		allPasses.push(defaultPass);
 		allPasses.push(shadows);
@@ -154,12 +160,14 @@ class Renderer extends h3d.scene.Renderer {
 		if( ls.shadowLight == null ) {
 			pbrOut.removeShader(pbrDirect);
 			pbrOut.removeShader(pbrSun);
+			pbrOut.removeShader(shadows.shader);
 		} else {
+			var pdir = Std.instance(ls.shadowLight, h3d.scene.pbr.DirLight);
 			if( pbrOut.getShader(h3d.shader.pbr.Light.DirLight) == null ) {
 				pbrOut.addShader(pbrDirect);
 				pbrOut.addShader(pbrSun);
+				pbrOut.addShader(shadows.shader);
 			}
-			var pdir = Std.instance(ls.shadowLight, h3d.scene.pbr.DirLight);
 			pbrSun.lightColor.load(ls.shadowLight.color);
 			if( pdir != null ) pbrSun.lightColor.scale3(pdir.power * pdir.power);
 			pbrSun.lightDir.load(@:privateAccess ls.shadowLight.getShadowDirection());
@@ -193,6 +201,10 @@ class Renderer extends h3d.scene.Renderer {
 
 		var ldr = allocTarget("ldrOutput",0,true);
 		setTarget(ldr);
+		tonemap.shader.mode = switch( toneMode ) {
+		case Linear: 0;
+		case Reinhard: 1;
+		};
 		tonemap.shader.hdrTexture = output;
 		tonemap.render();
 
@@ -225,6 +237,7 @@ class Renderer extends h3d.scene.Renderer {
 			envPower : 1.,
 			exposure : 0.,
 			sky : Hide,
+			tone : Reinhard,
 		};
 		return props;
 	}
@@ -243,6 +256,7 @@ class Renderer extends h3d.scene.Renderer {
 		}
 		displayMode = props.mode;
 		skyMode = props.sky;
+		toneMode = props.tone;
 		exposure = props.exposure;
 		env.power = props.envPower;
 	}
@@ -252,6 +266,13 @@ class Renderer extends h3d.scene.Renderer {
 		var props : PbrRenderProps = props;
 		return new js.jquery.JQuery('
 			<dl>
+				<dt>Tone</dt>
+				<dd>
+					<select field="tone">
+						<option value="Linear">Linear</option>
+						<option value="Reinhard">Reinhard</option>
+					</select>
+				</dd>
 				<dt>Mode</dt>
 				<dd>
 					<select field="mode">

+ 25 - 0
h3d/shader/DirShadow.hx

@@ -0,0 +1,25 @@
+package h3d.shader;
+
+class DirShadow extends hxsl.Shader {
+
+	static var SRC = {
+
+		@param var shadowMap : Channel;
+		@param var shadowProj : Mat3x4;
+		@param var shadowPower : Float;
+		@param var shadowBias : Float;
+
+		var transformedPosition : Vec3;
+		var shadow : Float;
+
+		function fragment() {
+			var shadowPos = transformedPosition * shadowProj * vec3(0.5, -0.5, 1) + vec3(0.5, 0.5, 0);
+			var depth = shadowMap.get(shadowPos.xy);
+			var zMax = shadowPos.z.saturate();
+			var delta = (depth + shadowBias).min(zMax) - zMax;
+			shadow = exp( shadowPower * delta ).saturate();
+		}
+
+	}
+
+}

+ 7 - 6
h3d/shader/pbr/Lighting.hx

@@ -33,11 +33,8 @@ class Indirect extends PropsDefinition {
 				var envBRDF = irrLut.get(vec2(roughness, NdV));
 				var specular = envSpec * (F * envBRDF.x + envBRDF.y);
 
-				/*
-					diffuse *= ao;
-				*/
 				var indirect = (diffuse * (1 - metalness) * (1 - F) + specular) * irrPower;
-				pixelColor.rgb += indirect;
+				pixelColor.rgb += indirect * occlusion;
 			}
 		}
 	};
@@ -50,8 +47,13 @@ class Direct extends PropsDefinition {
 
 		var pbrLightDirection : Vec3;
 		var pbrLightColor : Vec3;
+		var shadow : Float;
 		@const var doDiscard : Bool = true;
 
+		function __init__fragment() {
+			shadow = 1.;
+		}
+
 		function fragment() {
 			var NdL = normal.dot(pbrLightDirection).max(0.);
 			if( pbrLightColor.dot(pbrLightColor) > 0.0001 && NdL > 0 ) {
@@ -96,8 +98,7 @@ class Direct extends PropsDefinition {
 
 				var specular = (D * F * G / (4 * NdL * NdV)).max(0.);
 				direct += mix(diffuse * (1 - metalness), specular, F) * pbrLightColor;
-				direct *= occlusion;
-				pixelColor.rgb += direct;
+				pixelColor.rgb += direct * shadow;
 			} else if( doDiscard )
 				discard;
 		}

+ 0 - 29
h3d/shader/pbr/Shadow.hx

@@ -1,29 +0,0 @@
-package h3d.shader.pbr;
-
-class Shadow extends hxsl.Shader {
-
-	static var SRC = {
-
-		@global var shadow : {
-			map : Channel,
-			proj : Mat3x4,
-			color : Vec3, // unused ?
-			power : Float,
-			bias : Float,
-		};
-		@param var shadowMap : Sampler2D;
-		var transformedPosition : Vec3;
-		var occlusion : Float;
-
-		function fragment() {
-			var shadowPos = transformedPosition * shadow.proj * vec3(0.5, -0.5, 1) + vec3(0.5, 0.5, 0);
-			var depth = shadow.map.get(shadowPos.xy);
-			var zMax = shadowPos.z.saturate();
-			var delta = (depth + shadow.bias).min(zMax) - zMax;
-			var shade = exp( shadow.power * delta ).saturate();
-			occlusion *= shade;
-		}
-
-	}
-
-}

+ 10 - 2
h3d/shader/pbr/ToneMapping.hx

@@ -9,12 +9,20 @@ class ToneMapping extends ScreenShader {
 		@param var exposureExp : Float;
 		@const var isSRBG : Bool;
 
+		@const var mode : Int;
+
 		function fragment() {
 			var color = hdrTexture.get(calculatedUV);
 
-			// reinhard tonemapping
 			color.rgb *= exposureExp;
-			color.rgb = color.rgb / (color.rgb + vec3(1.));
+
+			switch( mode ) {
+			case 0:
+				// linear
+			case 1:
+				// reinhard
+				color.rgb = color.rgb / (color.rgb + vec3(1.));
+			}
 
 			// gamma correct
 			if( !isSRBG ) color.rgb = color.rgb.sqrt();