Browse Source

added MRT support for flash

Nicolas Cannasse 9 years ago
parent
commit
31c67d5b98
6 changed files with 110 additions and 16 deletions
  1. 9 0
      h3d/Engine.hx
  2. 3 0
      h3d/impl/Driver.hx
  3. 5 0
      h3d/impl/LogDriver.hx
  4. 29 6
      h3d/impl/Stage3dDriver.hx
  5. 44 0
      h3d/pass/MRT.hx
  6. 20 10
      samples/sao/Main.hx

+ 9 - 0
h3d/Engine.hx

@@ -41,6 +41,7 @@ class Engine {
 	var targetStack : TargetTmp;
 	var targetStack : TargetTmp;
 	var currentTarget : h3d.mat.Texture;
 	var currentTarget : h3d.mat.Texture;
 	var needFlushTarget : Bool;
 	var needFlushTarget : Bool;
+	var nullTexture : h3d.mat.Texture;
 
 
 	@:access(hxd.Stage)
 	@:access(hxd.Stage)
 	public function new( hardware = true, aa = 0 ) {
 	public function new( hardware = true, aa = 0 ) {
@@ -288,6 +289,14 @@ class Engine {
 		needFlushTarget = currentTarget != tex;
 		needFlushTarget = currentTarget != tex;
 	}
 	}
 
 
+	public function pushTargets( textures : Array<h3d.mat.Texture> ) {
+		if( nullTexture == null ) nullTexture = new h3d.mat.Texture(0, 0, [NoAlloc]);
+		pushTarget(nullTexture);
+		driver.setRenderTargets(textures);
+		currentTarget = nullTexture;
+		needFlushTarget = false;
+	}
+
 	public function popTarget() {
 	public function popTarget() {
 		var c = targetStack;
 		var c = targetStack;
 		if( c == null )
 		if( c == null )

+ 3 - 0
h3d/impl/Driver.hx

@@ -134,6 +134,9 @@ class Driver {
 	public function setRenderTarget( tex : Null<h3d.mat.Texture> ) {
 	public function setRenderTarget( tex : Null<h3d.mat.Texture> ) {
 	}
 	}
 
 
+	public function setRenderTargets( textures : Array<h3d.mat.Texture> ) {
+	}
+
 	public function present() {
 	public function present() {
 	}
 	}
 
 

+ 5 - 0
h3d/impl/LogDriver.hx

@@ -261,6 +261,11 @@ class LogDriver extends Driver {
 		d.setRenderTarget(tex);
 		d.setRenderTarget(tex);
 	}
 	}
 
 
+	override function setRenderTargets( textures : Array<h3d.mat.Texture> ) {
+		log('SetRenderTargets $textures');
+		d.setRenderTargets(textures);
+	}
+
 	override function present() {
 	override function present() {
 		log('Present');
 		log('Present');
 		d.present();
 		d.present();

+ 29 - 6
h3d/impl/Stage3dDriver.hx

@@ -64,7 +64,7 @@ class Stage3dDriver extends Driver {
 	var curAttributes : Int;
 	var curAttributes : Int;
 	var curTextures : Array<h3d.mat.Texture>;
 	var curTextures : Array<h3d.mat.Texture>;
 	var curSamplerBits : Array<Int>;
 	var curSamplerBits : Array<Int>;
-	var inTarget : h3d.mat.Texture;
+	var renderTargets : Int;
 	var antiAlias : Int;
 	var antiAlias : Int;
 	var width : Int;
 	var width : Int;
 	var height : Int;
 	var height : Int;
@@ -186,7 +186,7 @@ class Stage3dDriver extends Driver {
 	}
 	}
 
 
 	override function captureRenderBuffer( pixels : hxd.Pixels ) {
 	override function captureRenderBuffer( pixels : hxd.Pixels ) {
-		if( inTarget != null )
+		if( renderTargets != 0 )
 			throw "Can't capture render target in flash";
 			throw "Can't capture render target in flash";
 		var bmp = new flash.display.BitmapData(pixels.width, pixels.height, true, 0);
 		var bmp = new flash.display.BitmapData(pixels.width, pixels.height, true, 0);
 		ctx.drawToBitmapData(bmp);
 		ctx.drawToBitmapData(bmp);
@@ -709,8 +709,8 @@ class Stage3dDriver extends Driver {
 				height += y;
 				height += y;
 				y = 0;
 				y = 0;
 			}
 			}
-			var tw = inTarget == null ? this.width : 9999;
-			var th = inTarget == null ? this.height : 9999;
+			var tw = renderTargets == 0 ? this.width : 9999;
+			var th = renderTargets == 0 ? this.height : 9999;
 			if( x + width > tw ) width = tw - x;
 			if( x + width > tw ) width = tw - x;
 			if( y + height > th ) height = th - y;
 			if( y + height > th ) height = th - y;
 			enableDraw = width > 0 && height > 0;
 			enableDraw = width > 0 && height > 0;
@@ -720,14 +720,19 @@ class Stage3dDriver extends Driver {
 	}
 	}
 
 
 	override function setRenderTarget( t : Null<h3d.mat.Texture>) {
 	override function setRenderTarget( t : Null<h3d.mat.Texture>) {
+		if( renderTargets > 1 ) {
+			for( i in 1...renderTargets )
+				ctx.setRenderToTexture(null, false, 0, 0, i);
+			renderTargets = 0;
+		}
 		if( t == null ) {
 		if( t == null ) {
 			ctx.setRenderToBackBuffer();
 			ctx.setRenderToBackBuffer();
-			inTarget = null;
+			renderTargets = 0;
 		} else {
 		} else {
 			if( t.t == null )
 			if( t.t == null )
 				t.alloc();
 				t.alloc();
 			ctx.setRenderToTexture(t.t, t.flags.has(TargetUseDefaultDepth));
 			ctx.setRenderToTexture(t.t, t.flags.has(TargetUseDefaultDepth));
-			inTarget = t;
+			renderTargets = 1;
 			t.lastFrame = frame;
 			t.lastFrame = frame;
 			// make sure we at least clear the color the first time
 			// make sure we at least clear the color the first time
 			if( flashVersion >= 15 && !t.flags.has(WasCleared) ) {
 			if( flashVersion >= 15 && !t.flags.has(WasCleared) ) {
@@ -738,6 +743,24 @@ class Stage3dDriver extends Driver {
 		reset();
 		reset();
 	}
 	}
 
 
+	override function setRenderTargets( textures : Array<h3d.mat.Texture>) {
+		if( textures.length == 0 ) {
+			setRenderTarget(null);
+			return;
+		}
+		for( i in 0...textures.length ) {
+			var t = textures[i];
+			if( t.t == null )
+				t.alloc();
+			ctx.setRenderToTexture(t.t, t.flags.has(TargetUseDefaultDepth), 0, 0, i);
+			t.lastFrame = frame;
+		}
+		for( i in textures.length...renderTargets )
+			ctx.setRenderToTexture(null, false, 0, 0, i);
+		renderTargets = textures.length;
+		reset();
+	}
+
 	static var BLEND = [
 	static var BLEND = [
 		flash.display3D.Context3DBlendFactor.ONE,
 		flash.display3D.Context3DBlendFactor.ONE,
 		flash.display3D.Context3DBlendFactor.ZERO,
 		flash.display3D.Context3DBlendFactor.ZERO,

+ 44 - 0
h3d/pass/MRT.hx

@@ -0,0 +1,44 @@
+package h3d.pass;
+
+class MRT extends Default {
+
+	var fragmentOutputs : Array<String>;
+	public var clearColors : Array<Null<Int>>;
+	public var clearSameColor : Null<Int>;
+	public var clearDepth : Null<Float>;
+
+	public function new( fragmentOutputs, ?clearSameColor, ?clearDepth, ?clearColors ) {
+		this.fragmentOutputs = fragmentOutputs;
+		this.clearSameColor = clearSameColor;
+		if( clearDepth ) this.clearDepth = 1.;
+		this.clearColors = clearColors;
+		super();
+	}
+
+	override function getOutputs() {
+		var out = ["output.position"];
+		for( o in fragmentOutputs )
+			out.push("output." + o);
+		return out;
+	}
+
+	override function draw(passes:Object) {
+		var tex = [for( i in 0...fragmentOutputs.length ) tcache.allocTarget(fragmentOutputs[i], ctx, ctx.engine.width, ctx.engine.height, true)];
+		if( clearColors != null )
+			for( i in 0...fragmentOutputs.length ) {
+				var color = clearColors[i];
+				if( color != null ) {
+					ctx.engine.pushTarget(tex[i]);
+					ctx.engine.clear(color);
+					ctx.engine.popTarget();
+				}
+			}
+		ctx.engine.pushTargets(tex);
+		if( clearDepth != null || clearSameColor != null )
+			ctx.engine.clear(clearSameColor, clearDepth);
+		passes = super.draw(passes);
+		ctx.engine.popTarget();
+		return passes;
+	}
+
+}

+ 20 - 10
samples/sao/Main.hx

@@ -6,8 +6,9 @@ class CustomRenderer extends h3d.scene.Renderer {
 
 
 	public var sao : h3d.pass.ScalableAO;
 	public var sao : h3d.pass.ScalableAO;
 	public var saoBlur : h3d.pass.Blur;
 	public var saoBlur : h3d.pass.Blur;
-	var out : h3d.mat.Texture;
 	public var mode = 0;
 	public var mode = 0;
+	public var hasMRT : Bool;
+	var out : h3d.mat.Texture;
 
 
 	public function new() {
 	public function new() {
 		super();
 		super();
@@ -15,17 +16,23 @@ class CustomRenderer extends h3d.scene.Renderer {
 		// 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(2, 3, 2);
 		saoBlur = new h3d.pass.Blur(2, 3, 2);
 		sao.shader.sampleRadius	= 0.2;
 		sao.shader.sampleRadius	= 0.2;
+		hasMRT = h3d.Engine.getCurrent().driver.hasFeature(MultipleRenderTargets);
+		if( hasMRT )
+			def = new h3d.pass.MRT(["color","depth","normal"],0,true);
 	}
 	}
 
 
-	override function process( ctx, passes ) {
-		super.process(ctx, passes);
-
+	override function render() {
+		super.render();
 		if(mode != 1) {
 		if(mode != 1) {
 			var saoTarget = allocTarget("sao",0,false);
 			var saoTarget = allocTarget("sao",0,false);
-			setTarget(saoTarget);
-			sao.apply(depth.getTexture(), normal.getTexture(), ctx.camera);
+			pushTarget(saoTarget);
+			if( hasMRT )
+				sao.apply(def.getTexture(1), def.getTexture(2), ctx.camera);
+			else
+				sao.apply(depth.getTexture(), normal.getTexture(), ctx.camera);
+			popTarget();
 			saoBlur.apply(saoTarget, allocTarget("saoBlurTmp", 1, false));
 			saoBlur.apply(saoTarget, allocTarget("saoBlurTmp", 1, false));
-
+			if( hasMRT ) h3d.pass.Copy.run(def.getTexture(0), null);
 			h3d.pass.Copy.run(saoTarget, null, mode == 0 ? Multiply : null);
 			h3d.pass.Copy.run(saoTarget, null, mode == 0 ? Multiply : null);
 		}
 		}
 	}
 	}
@@ -41,13 +48,17 @@ class Main extends hxd.App {
 
 
 	function initMaterial( m : h3d.mat.MeshMaterial ) {
 	function initMaterial( m : h3d.mat.MeshMaterial ) {
 		m.mainPass.enableLights = true;
 		m.mainPass.enableLights = true;
-		m.addPass(new h3d.mat.Pass("depth", m.mainPass));
-		m.addPass(new h3d.mat.Pass("normal", m.mainPass));
+		if( !Std.instance(s3d.renderer,CustomRenderer).hasMRT ) {
+			m.addPass(new h3d.mat.Pass("depth", m.mainPass));
+			m.addPass(new h3d.mat.Pass("normal", m.mainPass));
+		}
 	}
 	}
 
 
 	override function init() {
 	override function init() {
 		var r = new hxd.Rand(Std.random(0xFFFFFF));
 		var r = new hxd.Rand(Std.random(0xFFFFFF));
 
 
+		s3d.renderer = new CustomRenderer();
+
 		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();
 		floor.translate( -5, -5, 0);
 		floor.translate( -5, -5, 0);
@@ -74,7 +85,6 @@ class Main extends hxd.App {
 		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();
 		time = Math.PI * 0.25;
 		time = Math.PI * 0.25;
 		camdist = 6 * wscale;
 		camdist = 6 * wscale;
 	}
 	}