bstouls 10 rokov pred
rodič
commit
6d33506f0b
2 zmenil súbory, kde vykonal 70 pridanie a 42 odobranie
  1. 17 26
      h3d/pass/ScalableAO.hx
  2. 53 16
      samples/sao/Main.hx

+ 17 - 26
h3d/pass/ScalableAO.hx

@@ -14,40 +14,31 @@ private class SAOShader extends h3d.shader.ScreenShader {
 		@param var sampleRadius : Float;
 		@param var sampleRadius : Float;
 		@param var intensity : Float;
 		@param var intensity : Float;
 		@param var bias : Float;
 		@param var bias : Float;
-		@param var projScale : Float;
 
 
 		@param var cameraView : Mat3x4;
 		@param var cameraView : Mat3x4;
 		@param var cameraInverseViewProj : Mat4;
 		@param var cameraInverseViewProj : Mat4;
 
 
-		@param var invPixelSize : Vec2;
-
-		function getOffsetPosition( uv : Vec2, unitOffset : Vec2, radiusSS : Float ) : Vec3 {
-			uv = uv + radiusSS * unitOffset * invPixelSize;
-			return getPosition(uv);
-		}
-
-		function sampleAO(uv : Vec2, position : Vec3, normal : Vec3, sampleRadiusSS : Float, tapIndex : Int, rotationAngle : Float) : Float {
-			var epsilon = 0.01;
-			var radius2 = sampleRadius * sampleRadius;
+		@param var screenRatio : Vec2;
 
 
+		function sampleAO(uv : Vec2, position : Vec3, normal : Vec3, radiusSS : Float, tapIndex : Int, rotationAngle : Float) : Float {
 			// returns a unit vector and a screen-space radius for the tap on a unit disk
 			// returns a unit vector and a screen-space radius for the tap on a unit disk
 			// (the caller should scale by the actual disk radius)
 			// (the caller should scale by the actual disk radius)
 			// radius relative to radiusSS
 			// radius relative to radiusSS
 			var alpha = (float(tapIndex) + 0.5) * (1.0 / float(numSamples));
 			var alpha = (float(tapIndex) + 0.5) * (1.0 / float(numSamples));
 			var angle = alpha * (float(numSpiralTurns) * 6.28) + rotationAngle;
 			var angle = alpha * (float(numSpiralTurns) * 6.28) + rotationAngle;
-			var radiusSS = alpha * sampleRadiusSS;
 
 
 			var unitOffset = vec2(cos(angle), sin(angle));
 			var unitOffset = vec2(cos(angle), sin(angle));
-
-			var Q = getOffsetPosition(uv, unitOffset, radiusSS);
+			var targetUV = uv + radiusSS * alpha * unitOffset * screenRatio;
+			var Q = getPosition(targetUV);
 			var v = Q - position;
 			var v = Q - position;
 
 
 			var vv = dot(v, v);
 			var vv = dot(v, v);
-
-			var vn = dot(v, normal) - bias;
+			var vn = dot(v, normal) - (bias / sampleRadius);
 
 
 			// Smoother transition to zero (lowers contrast, smoothing out corners). [Recommended]
 			// Smoother transition to zero (lowers contrast, smoothing out corners). [Recommended]
+			var radius2 = sampleRadius * sampleRadius;
 			var f = max(radius2 - vv, 0.0) / radius2;
 			var f = max(radius2 - vv, 0.0) / radius2;
+			var epsilon = 0.01;
 			return f * f * f * max(vn / (epsilon + vv), 0.0);
 			return f * f * f * max(vn / (epsilon + vv), 0.0);
 		}
 		}
 
 
@@ -66,28 +57,29 @@ private class SAOShader extends h3d.shader.ScreenShader {
 			var origin = getPosition(vUV);
 			var origin = getPosition(vUV);
 			var normal = unpackNormal(normalTexture.get(vUV));
 			var normal = unpackNormal(normalTexture.get(vUV));
 
 
-			var sampleNoise = noiseTexture.get(vUV * noiseScale).x;
+			var sampleNoise = noiseTexture.get(vUV * noiseScale / screenRatio).x;
 			var randomPatternRotationAngle = 2.0 * PI * sampleNoise;
 			var randomPatternRotationAngle = 2.0 * PI * sampleNoise;
 
 
-			var radiusSS = sampleRadius / (origin * cameraView).z;
+			// is it correct enough to go from WS to DepthUV space ?
+			var radiusSS = sampleRadius * 0.5 / (origin * cameraView).z;
 
 
 			for( i in 0...numSamples )
 			for( i in 0...numSamples )
 				occlusion += sampleAO(vUV, origin, normal, radiusSS, i, randomPatternRotationAngle);
 				occlusion += sampleAO(vUV, origin, normal, radiusSS, i, randomPatternRotationAngle);
 
 
-			occlusion = 1.0 - occlusion / (4.0 * float(numSamples));
+			occlusion = 1.0 - occlusion / (5.0 * float(numSamples));
 			occlusion = clamp(pow(occlusion, 1.0 + intensity), 0.0, 1.0);
 			occlusion = clamp(pow(occlusion, 1.0 + intensity), 0.0, 1.0);
 
 
-			output.color = vec4(occlusion, occlusion, occlusion, .0);
+			output.color = vec4(occlusion.xxx, 1.);
 		}
 		}
 	};
 	};
 
 
 	public function new() {
 	public function new() {
 		super();
 		super();
 		numSamples = 20;
 		numSamples = 20;
-		sampleRadius = 500;
-		intensity = 20;
+		sampleRadius = 1;
+		intensity = 1;
 		numSpiralTurns = 7;
 		numSpiralTurns = 7;
-		bias = 0.5;
+		bias = 0.01;
 		noiseScale.set(10, 10);
 		noiseScale.set(10, 10);
 		noiseTexture = getNoise(128);
 		noiseTexture = getNoise(128);
 		noiseTexture.wrap = Repeat;
 		noiseTexture.wrap = Repeat;
@@ -107,7 +99,7 @@ private class SAOShader extends h3d.shader.ScreenShader {
 
 
 }
 }
 
 
-class ScalableAO extends ScreenFx<SAOShader> {
+class ScalableAO extends h3d.pass.ScreenFx<SAOShader> {
 
 
 	public function new() {
 	public function new() {
 		super(new SAOShader());
 		super(new SAOShader());
@@ -118,8 +110,7 @@ class ScalableAO extends ScreenFx<SAOShader> {
 		shader.normalTexture = normalTexture;
 		shader.normalTexture = normalTexture;
 		shader.cameraView = camera.mcam;
 		shader.cameraView = camera.mcam;
 		shader.cameraInverseViewProj = camera.getInverseViewProj();
 		shader.cameraInverseViewProj = camera.getInverseViewProj();
-		shader.invPixelSize.set(1 / engine.width, 1 / engine.height);
-		shader.projScale = 1.0 / (2.0 * Math.tan(camera.fovY * Math.PI / 180));
+		shader.screenRatio.set(engine.height / engine.width, 1);
 		render();
 		render();
 	}
 	}
 
 

+ 53 - 16
samples/sao/Main.hx

@@ -1,28 +1,32 @@
 import hxd.Math;
 import hxd.Math;
+import h3d.pass.ScalableAO;
+import hxd.Key in K;
 
 
 class CustomRenderer extends h3d.scene.Renderer {
 class CustomRenderer extends h3d.scene.Renderer {
 
 
 	var sao : h3d.pass.ScalableAO;
 	var sao : h3d.pass.ScalableAO;
-	var saoBlur : h3d.pass.Blur;
+	public var saoBlur : h3d.pass.Blur;
 	var out : h3d.mat.Texture;
 	var out : h3d.mat.Texture;
+	public var mode = 0;
 
 
 	public function new() {
 	public function new() {
 		super();
 		super();
 		sao = new h3d.pass.ScalableAO();
 		sao = new h3d.pass.ScalableAO();
 		// TODO : use a special Blur that prevents bluring across depths
 		// TODO : use a special Blur that prevents bluring across depths
-		saoBlur = new h3d.pass.Blur(3,5);
-		saoBlur.passes = 3;
+		saoBlur = new h3d.pass.Blur(2, 3, 2);
 	}
 	}
 
 
 	override function process( ctx, passes ) {
 	override function process( ctx, passes ) {
 		super.process(ctx, passes);
 		super.process(ctx, passes);
 
 
-		var saoTarget = allocTarget("sao",0,false);
-		setTarget(saoTarget);
-		sao.apply(depth.getTexture(), normal.getTexture(), ctx.camera);
-		saoBlur.apply(saoTarget, allocTarget("saoBlurTmp", 0, false));
+		if(mode != 1) {
+			var saoTarget = allocTarget("sao",0,false);
+			setTarget(saoTarget);
+			sao.apply(depth.getTexture(), normal.getTexture(), ctx.camera);
+			saoBlur.apply(saoTarget, allocTarget("saoBlurTmp", 1, false));
 
 
-		h3d.pass.Copy.run(saoTarget, null, Multiply);
+			h3d.pass.Copy.run(saoTarget, null, mode == 0 ? Multiply : null);
+		}
 	}
 	}
 
 
 }
 }
@@ -30,6 +34,9 @@ class CustomRenderer extends h3d.scene.Renderer {
 class Main extends hxd.App {
 class Main extends hxd.App {
 
 
 	var time : Float = 0.;
 	var time : Float = 0.;
+	var wscale = 1.;
+	var camdist = 6.;
+	var paused = false;
 
 
 	function initMaterial( m : h3d.mat.MeshMaterial ) {
 	function initMaterial( m : h3d.mat.MeshMaterial ) {
 		m.mainPass.enableLights = true;
 		m.mainPass.enableLights = true;
@@ -38,6 +45,7 @@ class Main extends hxd.App {
 	}
 	}
 
 
 	override function init() {
 	override function init() {
+		var r = new hxd.Rand(Std.random(0xFFFFFF));
 
 
 		var floor = new h3d.prim.Grid(40,40,0.25,0.25);
 		var floor = new h3d.prim.Grid(40,40,0.25,0.25);
 		floor.addNormals();
 		floor.addNormals();
@@ -45,30 +53,59 @@ class Main extends hxd.App {
 		var m = new h3d.scene.Mesh(floor, s3d);
 		var m = new h3d.scene.Mesh(floor, s3d);
 		initMaterial(m.material);
 		initMaterial(m.material);
 		m.material.color.makeColor(0.35, 0.5, 0.5);
 		m.material.color.makeColor(0.35, 0.5, 0.5);
+		m.setScale(wscale);
 
 
 		for( i in 0...100 ) {
 		for( i in 0...100 ) {
-			var box : h3d.prim.Polygon = new h3d.prim.Cube(Math.random(),Math.random(), 0.7 + Math.random() * 0.8);
+			var box : h3d.prim.Polygon = new h3d.prim.Cube(0.3 + r.rand() * 0.5, 0.3 + r.rand() * 0.5, 0.2 + r.rand());
 			box.unindex();
 			box.unindex();
 			box.addNormals();
 			box.addNormals();
 			var p = new h3d.scene.Mesh(box, s3d);
 			var p = new h3d.scene.Mesh(box, s3d);
-			p.x = Math.srand(3);
-			p.y = Math.srand(3);
+			p.setScale(wscale);
+			p.x = r.srand(3) * wscale;
+			p.y = r.srand(3) * wscale;
 			initMaterial(p.material);
 			initMaterial(p.material);
-			p.material.color.makeColor(Math.random() * 0.3, 0.5, 0.5);
+			p.material.color.makeColor(r.rand() * 0.3, 0.5, 0.5);
 		}
 		}
-		s3d.camera.zNear = 0.5;
-		s3d.camera.zFar = 15;
+		s3d.camera.zNear = 0.1 * wscale;
+		s3d.camera.zFar = 150 * wscale;
 
 
 		s3d.lightSystem.ambientLight.set(0.5, 0.5, 0.5);
 		s3d.lightSystem.ambientLight.set(0.5, 0.5, 0.5);
 		var dir = new h3d.scene.DirLight(new h3d.Vector( -0.3, -0.2, -1), s3d);
 		var dir = new h3d.scene.DirLight(new h3d.Vector( -0.3, -0.2, -1), s3d);
 		dir.color.set(0.5, 0.5, 0.5);
 		dir.color.set(0.5, 0.5, 0.5);
 
 
 		s3d.renderer = new CustomRenderer();
 		s3d.renderer = new CustomRenderer();
+		time = Math.PI * 0.25;
+		camdist = 6 * wscale;
+	}
+
+	function reset() {
+		s3d = new h3d.scene.Scene();
+		init();
 	}
 	}
 
 
 	override function update( dt : Float ) {
 	override function update( dt : Float ) {
-		time += dt * 0.001;
-		s3d.camera.pos.set(6 * Math.cos(time), 6 * Math.sin(time), 3);
+
+		if(K.isPressed(K.BACKSPACE))
+			reset();
+
+		if(K.isDown(K.SHIFT))
+			dt *= 10;
+		if(K.isPressed("P".code) || K.isPressed(K.SPACE))
+			paused = !paused;
+
+		var r = Std.instance(s3d.renderer, CustomRenderer);
+		if(K.isPressed(K.NUMBER_1))
+			r.mode = 0;
+		if(K.isPressed(K.NUMBER_2))
+			r.mode = 1;
+		if(K.isPressed(K.NUMBER_3))
+			r.mode = 2;
+		if(K.isPressed("B".code))
+			r.saoBlur.passes = r.saoBlur.passes == 0 ? 3 : 0;
+
+		if(!paused)
+			time += dt * 0.001;
+		s3d.camera.pos.set(camdist * Math.cos(time), camdist * Math.sin(time), camdist * 0.5);
 	}
 	}
 
 
 	public static var inst : Main;
 	public static var inst : Main;