瀏覽代碼

Refactor default renderer, more imperative

ncannasse 7 年之前
父節點
當前提交
2bf85d45d5

+ 1 - 1
h3d/mat/MaterialSetup.hx

@@ -27,7 +27,7 @@ class MaterialSetup {
 	}
 
 	public function createRenderer() {
-		return new h3d.scene.Renderer();
+		return new h3d.scene.DefaultRenderer();
 	}
 
 	public function createLightSystem() {

+ 1 - 1
h3d/mat/Pass.hx

@@ -195,7 +195,7 @@ class Pass implements hxd.impl.Serializable {
 	}
 
 	public function getDebugShaderCode( scene : h3d.scene.Scene, toHxsl = true ) {
-		var shader = scene.renderer.compileShader(this);
+		var shader = scene.renderer.debugCompileShader(this);
 		if( toHxsl ) {
 			var toString = hxsl.Printer.shaderToString.bind(_, true);
 			return "// vertex:\n" + toString(shader.vertex.data) + "\n\nfragment:\n" + toString(shader.fragment.data);

+ 3 - 3
h3d/pass/Base.hx

@@ -3,10 +3,10 @@ package h3d.pass;
 class Base {
 
 	var ctx : h3d.scene.RenderContext;
-	public var priority : Int = 0;
-	public var forceProcessing : Bool = false;
+	public var name(default, null) : String;
 
-	public function new() {
+	public function new(name) {
+		this.name = name;
 	}
 
 	public function getTexture( index = 0 ) : h3d.mat.Texture {

+ 2 - 2
h3d/pass/Default.hx

@@ -30,8 +30,8 @@ class Default extends Base {
 	@global("global.modelView") var globalModelView : h3d.Matrix;
 	@global("global.modelViewInverse") var globalModelViewInverse : h3d.Matrix;
 
-	public function new() {
-		super();
+	public function new(name) {
+		super(name);
 		manager = new ShaderManager(getOutputs());
 		tcache = new h3d.impl.TextureCache();
 		shaderIdMap = [];

+ 0 - 29
h3d/pass/Depth.hx

@@ -1,29 +0,0 @@
-package h3d.pass;
-
-class Depth extends Default {
-
-	var depthMapId : Int;
-	public var enableSky : Bool = false;
-	public var reduceSize : Int = 0;
-
-	public function new() {
-		super();
-		priority = 10;
-		depthMapId = hxsl.Globals.allocID("depthMap");
-	}
-
-	override function getOutputs() : Array<hxsl.Output> {
-		return [PackFloat(Value("output.depth"))];
-	}
-
-	override function draw( passes ) {
-		var texture = tcache.allocTarget("depthMap", ctx, ctx.engine.width >> reduceSize, ctx.engine.height >> reduceSize, true);
-		ctx.engine.pushTarget(texture);
-		ctx.engine.clear(enableSky ? 0 : 0xFF0000, 1);
-		passes = super.draw(passes);
-		ctx.engine.popTarget();
-		ctx.setGlobalID(depthMapId, { texture : texture });
-		return passes;
-	}
-
-}

+ 1 - 1
h3d/pass/HardwarePick.hx

@@ -31,7 +31,7 @@ class HardwarePick extends Default {
 	public var pickedIndex = -1;
 
 	public function new() {
-		super();
+		super("hwpick");
 		material = new h3d.mat.Pass("");
 		material.blend(One, Zero);
 		texOut = new h3d.mat.Texture(3, 3, [Target]);

+ 2 - 2
h3d/pass/MRT.hx

@@ -10,7 +10,7 @@ class MRTSubPass extends Default {
 	public function new( m, output ) {
 		this.mrt = m;
 		this.output = output;
-		super();
+		super("mrt"+output);
 		this.varId = hxsl.Globals.allocID(mrt.outputNames[output].split(".").pop() + "Map");
 	}
 
@@ -51,7 +51,7 @@ class MRT extends Default {
 		this.clearSameColor = clearSameColor;
 		if( clearDepth ) this.clearDepth = 1.;
 		this.clearColors = clearColors;
-		super();
+		super("mrt");
 	}
 
 	function getOutputName(i:Int) {

+ 0 - 27
h3d/pass/Normal.hx

@@ -1,27 +0,0 @@
-package h3d.pass;
-
-class Normal extends Default {
-
-	var normalMapId : Int;
-
-	public function new() {
-		super();
-		priority = 10;
-		normalMapId = hxsl.Globals.allocID("normalMap");
-	}
-
-	override function getOutputs() : Array<hxsl.Output> {
-		return [PackNormal(Value("output.normal"))];
-	}
-
-	override function draw( passes ) {
-		var texture = tcache.allocTarget("normalMal", ctx, ctx.engine.width, ctx.engine.height);
-		ctx.engine.pushTarget(texture);
-		ctx.engine.clear(0x808080, 1);
-		passes = super.draw(passes);
-		ctx.engine.popTarget();
-		ctx.setGlobalID(normalMapId, texture);
-		return passes;
-	}
-
-}

+ 3 - 3
h3d/pass/CustomOutput.hx → h3d/pass/Output.hx

@@ -1,12 +1,12 @@
 package h3d.pass;
 
-class CustomOutput extends Default {
+class Output extends Default {
 
 	var outputs : Array<hxsl.Output>;
 
-	public function new( outputs ) {
+	public function new( name, outputs ) {
 		this.outputs = outputs;
-		super();
+		super(name);
 	}
 
 	override function getOutputs() {

+ 1 - 2
h3d/pass/ShadowMap.hx

@@ -18,9 +18,8 @@ class ShadowMap extends Default {
 	public var blur : Blur;
 
 	public function new(size) {
-		super();
+		super("shadow");
 		this.size = size;
-		priority = 9;
 		lightCamera = new h3d.Camera();
 		lightCamera.orthoBounds = new h3d.col.Bounds();
 		shadowMapId = hxsl.Globals.allocID("shadow.map");

+ 91 - 0
h3d/scene/DefaultRenderer.hx

@@ -0,0 +1,91 @@
+package h3d.scene;
+
+private typedef SMap<T> = #if flash haxe.ds.UnsafeStringMap<T> #else Map<String,T> #end
+
+class DepthPass extends h3d.pass.Default {
+
+	var depthMapId : Int;
+	public var enableSky : Bool = false;
+	public var reduceSize : Int = 0;
+
+	public function new() {
+		super("depth");
+		depthMapId = hxsl.Globals.allocID("depthMap");
+	}
+
+	override function getOutputs() : Array<hxsl.Output> {
+		return [PackFloat(Value("output.depth"))];
+	}
+
+	override function draw( passes ) {
+		var texture = tcache.allocTarget("depthMap", ctx, ctx.engine.width >> reduceSize, ctx.engine.height >> reduceSize, true);
+		ctx.engine.pushTarget(texture);
+		ctx.engine.clear(enableSky ? 0 : 0xFF0000, 1);
+		passes = super.draw(passes);
+		ctx.engine.popTarget();
+		ctx.setGlobalID(depthMapId, { texture : texture });
+		return passes;
+	}
+
+}
+
+class NormalPass extends h3d.pass.Default {
+
+	var normalMapId : Int;
+
+	public function new() {
+		super("normal");
+		normalMapId = hxsl.Globals.allocID("normalMap");
+	}
+
+	override function getOutputs() : Array<hxsl.Output> {
+		return [PackNormal(Value("output.normal"))];
+	}
+
+	override function draw( passes ) {
+		var texture = tcache.allocTarget("normalMal", ctx, ctx.engine.width, ctx.engine.height);
+		ctx.engine.pushTarget(texture);
+		ctx.engine.clear(0x808080, 1);
+		passes = super.draw(passes);
+		ctx.engine.popTarget();
+		ctx.setGlobalID(normalMapId, texture);
+		return passes;
+	}
+
+}
+class DefaultRenderer extends Renderer {
+
+	var def(get, never) : h3d.pass.Base;
+	public var depth : h3d.pass.Base = new DepthPass();
+	public var normal : h3d.pass.Base = new NormalPass();
+	public var shadow = new h3d.pass.ShadowMap(1024);
+
+	public function new() {
+		super();
+		defaultPass = new h3d.pass.Default("default");
+		allPasses = [defaultPass, depth, normal, shadow];
+	}
+
+	inline function get_def() return defaultPass;
+
+	// can be overriden for benchmark purposes
+	function renderPass(p:h3d.pass.Base, passes) {
+		p.draw(passes);
+	}
+
+	override function render() {
+		if( has("shadow") )
+			renderPass(shadow,get("shadow"));
+
+		if( has("depth") )
+			renderPass(depth,get("depth"));
+
+		if( has("normal") )
+			renderPass(normal,get("normal"));
+
+		renderPass(defaultPass, getSort("default", true) );
+		renderPass(defaultPass, getSort("alpha") );
+		renderPass(defaultPass, get("additive") );
+	}
+
+}

+ 47 - 102
h3d/scene/Renderer.hx

@@ -1,6 +1,6 @@
 package h3d.scene;
 
-class PassGroup {
+class PassObjects {
 	public var name : String;
 	public var passes : h3d.pass.Object;
 	public var rendered : Bool;
@@ -14,86 +14,49 @@ private typedef SMap<T> = #if flash haxe.ds.UnsafeStringMap<T> #else Map<String,
 
 class Renderer {
 
-	var def : h3d.pass.Base;
-	var depth : h3d.pass.Base;
-	var normal : h3d.pass.Base;
-	var shadow : h3d.pass.Base;
-	var passes : SMap<h3d.pass.Base>;
-	var passGroups : SMap<PassGroup>;
-	var allPasses : Array<{ name : String, p : h3d.pass.Base }>;
+	var defaultPass : h3d.pass.Base;
+	var passObjects : SMap<PassObjects>;
+	var allPasses : Array<h3d.pass.Base>;
 	var ctx : RenderContext;
 	var tcache : h3d.impl.TextureCache;
 	var hasSetTarget = false;
 
 	public function new() {
-		passes = new SMap();
 		allPasses = [];
 		tcache = new h3d.impl.TextureCache();
-		passGroups = new SMap();
+		passObjects = new SMap();
 	}
 
 	public function dispose() {
 		for( p in allPasses )
-			p.p.dispose();
-		passes = new SMap();
-		allPasses = [];
-		passGroups = new SMap();
+			p.dispose();
+		passObjects = new SMap();
 		tcache.dispose();
-		def = depth = normal = shadow = null;
-	}
-
-	public function compileShader( pass : h3d.mat.Pass ) {
-		var p = getPass(pass.name);
-		p.setContext(ctx);
-		return p.compileShader(pass);
 	}
 
-	function hasFeature(f) {
-		return h3d.Engine.getCurrent().driver.hasFeature(f);
-	}
-
-	function createDefaultPass( name : String ) : h3d.pass.Base {
-		switch( name ) {
-		case "depth":
-			if( depth != null ) return depth;
-			return depth = new h3d.pass.Depth();
-		case "normal":
-			if( normal != null ) return normal;
-			return normal = new h3d.pass.Normal();
-		case "shadow":
-			if( shadow != null ) return shadow;
-			return shadow = new h3d.pass.ShadowMap(1024);
-		default:
-			if( def != null ) return def;
-			return def = new h3d.pass.Default();
-		}
+	public function getPass<T:h3d.pass.Base>( c : Class<T> ) : T {
+		for( p in allPasses )
+			if( Std.is(p, c) )
+				return cast p;
+		return null;
 	}
 
-	public function getPass( name : String, create = true ) {
-		var p = passes.get(name);
-		if( p == null && create ) {
-			p = createDefaultPass(name);
-			setPass(name, p);
-		}
-		return p;
+	public function getPassByName( name : String ) {
+		for( p in allPasses )
+			if( p.name == name )
+				return p;
+		return null;
 	}
 
-	function getPassPriority( p : { name : String, p : h3d.pass.Base }  ) {
-		var pr = p.p.priority * 10;
-		switch( p.name ) {
-		case "alpha": pr -= 1;
-		case "additive": pr -= 2;
-		}
-		return pr;
+	public function debugCompileShader( pass : h3d.mat.Pass ) {
+		var p = getPassByName(pass.name);
+		if( p == null ) p = defaultPass;
+		p.setContext(ctx);
+		return p.compileShader(pass);
 	}
 
-	public function setPass( name : String, p : h3d.pass.Base ) {
-		for( p in allPasses )
-			if( p.name == name )
-				allPasses.remove(p);
-		passes.set(name, p);
-		allPasses.push({ name : name, p : p });
-		allPasses.sort(function(p1, p2) return getPassPriority(p2) - getPassPriority(p1));
+	function hasFeature(f) {
+		return h3d.Engine.getCurrent().driver.hasFeature(f);
 	}
 
 	@:access(h3d.scene.Object)
@@ -113,22 +76,15 @@ class Renderer {
 		}
 	}
 
-	inline function front2back(passes) {
-		return depthSort(passes, true);
-	}
-
-	inline function back2front(passes) {
-		return depthSort(passes, false);
+	inline function clear( ?color, ?depth, ?stencil ) {
+		ctx.engine.clear(color, depth, stencil);
 	}
 
+	// for legacy purposes
 	inline function allocTarget( name : String, size = 0, depth = true ) {
 		return tcache.allocTarget(name, ctx, ctx.engine.width >> size, ctx.engine.height >> size, depth);
 	}
 
-	inline function clear( ?color, ?depth, ?stencil ) {
-		ctx.engine.clear(color, depth, stencil);
-	}
-
 	function copy( from, to, ?blend ) {
 		h3d.pass.Copy.run(from, to, blend);
 	}
@@ -146,54 +102,43 @@ class Renderer {
 		}
 	}
 
+	function has( name : String ) {
+		return passObjects.get(name) != null;
+	}
+
 	function get( name : String ) {
-		var p = passGroups.get(name);
+		var p = passObjects.get(name);
 		if( p == null ) return null;
 		p.rendered = true;
 		return p.passes;
 	}
 
-	function draw( name : String ) {
-		if( def == null ) def = new h3d.pass.Default();
-		def.draw(get(name));
+	function getSort( name : String, front2Back = false ) {
+		var p = passObjects.get(name);
+		if( p == null ) return null;
+		p.passes = depthSort(p.passes, front2Back);
+		p.rendered = true;
+		return p.passes;
 	}
 
-	function renderPass( name : String, p : h3d.pass.Base, passes ) {
-		return p.draw(passes);
+	function draw( name : String ) {
+		defaultPass.draw(get(name));
 	}
 
 	function render() {
-		for( p in allPasses ) {
-			var pdata = passGroups.get(p.name);
-			if( pdata != null && pdata.rendered )
-				continue;
-			if( pdata != null || p.p.forceProcessing ) {
-				p.p.setContext(ctx);
-				var passes = pdata == null ? null : pdata.passes;
-				if( p.name == "alpha" )
-					passes = depthSort(passes);
-				if( p.name == "default" )
-					passes = depthSort(passes, true);
-				passes = renderPass(p.name, p.p, passes);
-				if( pdata != null ) {
-					pdata.passes = passes;
-					pdata.rendered = true;
-				}
-			}
-		}
+		throw "Not implemented";
 	}
 
-	public function process( passes : Array<PassGroup> ) {
+	public function process( passes : Array<PassObjects> ) {
 		hasSetTarget = false;
-		// alloc passes
-		for( p in passes ) {
-			getPass(p.name).setContext(ctx);
-			passGroups.set(p.name, p);
-		}
+		for( p in allPasses )
+			p.setContext(ctx);
+		for( p in passes )
+			passObjects.set(p.name, p);
 		render();
 		resetTarget();
 		for( p in passes )
-			passGroups.set(p.name, null);
+			passObjects.set(p.name, null);
 	}
 
 }

+ 1 - 1
h3d/scene/Scene.hx

@@ -346,7 +346,7 @@ class Scene extends Object implements h3d.IDrawable implements hxd.SceneEvents.I
 				p = p.next;
 			}
 			prev.next = null;
-			passes.push(new Renderer.PassGroup(curPass.pass.name,curPass));
+			passes.push(new Renderer.PassObjects(curPass.pass.name,curPass));
 			curPass = p;
 		}
 

+ 1 - 1
hxd/inspect/ScenePanel.hx

@@ -104,7 +104,7 @@ private class CustomSceneProps extends SceneProps {
 				j.toggleClass("disable");
 			case 1:
 				var p = new Panel(null,pass.name+" shader");
-				var shader = scene.renderer.compileShader(pass);
+				var shader = scene.renderer.debugCompileShader(pass);
 				var toString = hxsl.Printer.shaderToString;
 				var code = toString(shader.vertex.data) + "\n\n" + toString(shader.fragment.data);
 				p.j.html("<pre class='code'>" + colorize(code) + "</pre>");

+ 3 - 7
hxd/inspect/SceneProps.hx

@@ -90,7 +90,7 @@ class SceneProps {
 			if( ls.shadowLight != null )
 				props.push(PGroup("DirLight", getObjectProps(ls.shadowLight)));
 
-			var s = Std.instance(r.getPass("shadow", false),h3d.pass.ShadowMap);
+			var s = r.getPass(h3d.pass.ShadowMap);
 			if( s != null ) {
 				props.push(PGroup("Shadows",[
 					PRange("size", 64, 2048, function() return s.size, function(sz) s.size = Std.int(sz), 64),
@@ -110,12 +110,8 @@ class SceneProps {
 			if( tp.length > 0 )
 				props.push(PGroup("Textures",tp));
 
-			var pmap = new Map();
-			for( p in @:privateAccess r.allPasses ) {
-				if( pmap.exists(p.p) ) continue;
-				pmap.set(p.p, true);
-				props.push(PGroup("Pass " + p.name, getPassProps(p.p)));
-			}
+			for( p in @:privateAccess r.allPasses )
+				props.push(PGroup("Pass " + p.name, getPassProps(p)));
 			return props;
 
 		case Core:

+ 13 - 9
samples/Sao.hx

@@ -2,7 +2,7 @@ import hxd.Math;
 import h3d.pass.ScalableAO;
 import hxd.Key in K;
 
-class CustomRenderer extends h3d.scene.Renderer {
+class CustomRenderer extends h3d.scene.DefaultRenderer {
 
 	public var sao : h3d.pass.ScalableAO;
 	public var saoBlur : h3d.pass.Blur;
@@ -19,13 +19,16 @@ class CustomRenderer extends h3d.scene.Renderer {
 		saoBlur = new h3d.pass.Blur(3, 3, 2);
 		sao.shader.sampleRadius	= 0.2;
 		hasMRT = h3d.Engine.getCurrent().driver.hasFeature(MultipleRenderTargets);
-		if( hasMRT )
-			def = new h3d.pass.MRT([Value("output.color"), PackFloat(Value("output.depth")), PackNormal(Value("output.normal"))], 0, true);
+		if( hasMRT ) {
+			allPasses.remove(defaultPass);
+			defaultPass = new h3d.pass.MRT([Value("output.color"), PackFloat(Value("output.depth")), PackNormal(Value("output.normal"))], 0, true);
+			allPasses.push(defaultPass);
+		}
 	}
 
-	override function renderPass(name, p:h3d.pass.Base, passes) {
-		bench.measure(name);
-		return super.renderPass(name, p, passes);
+	override function renderPass(p:h3d.pass.Base, passes) {
+		bench.measure(p.name);
+		return super.renderPass(p, passes);
 	}
 
 	override function render() {
@@ -35,7 +38,7 @@ class CustomRenderer extends h3d.scene.Renderer {
 			var saoTarget = allocTarget("sao",0,false);
 			setTarget(saoTarget);
 			if( hasMRT )
-				sao.apply(def.getTexture(1), def.getTexture(2), ctx.camera);
+				sao.apply(defaultPass.getTexture(1), defaultPass.getTexture(2), ctx.camera);
 			else
 				sao.apply(depth.getTexture(), normal.getTexture(), ctx.camera);
 			resetTarget();
@@ -43,8 +46,9 @@ class CustomRenderer extends h3d.scene.Renderer {
 			saoBlur.apply(saoTarget, allocTarget("saoBlurTmp", 0, false));
 			bench.measure("saoBlend");
 			if( hasMRT ) h3d.pass.Copy.run(def.getTexture(0), null);
-			h3d.pass.Copy.run(saoTarget, null, mode == 0 ? Multiply : null);
-		}
+			copy(saoTarget, null, mode == 0 ? Multiply : null);
+		} else if( hasMRT )
+			copy(defaultPass.getTexture(0), null);
 	}
 
 }