فهرست منبع

use new sort api, separate get passes from sorting and only perform sort-by-material if no other sort was set (close #623)

Nicolas Cannasse 6 سال پیش
والد
کامیت
5cb3350309

+ 1 - 1
h3d/pass/Base.hx

@@ -21,7 +21,7 @@ class Base {
 	public function dispose() {
 	}
 
-	public function draw( passes : PassList ) {
+	public function draw( passes : PassList, ?sort : h3d.pass.PassList -> Void ) {
 	}
 
 }

+ 6 - 22
h3d/pass/Default.hx

@@ -6,11 +6,7 @@ class Default extends Base {
 
 	var manager : ShaderManager;
 	var globals(get, never) : hxsl.Globals;
-	var shaderCount : Int = 1;
-	var textureCount : Int = 1;
-	var shaderIdMap : Array<Int>;
-	var textureIdMap : Array<Int>;
-	var sortPasses = true;
+	var defaultSort = new SortByMaterial().sort;
 
 	inline function get_globals() return manager.globals;
 
@@ -31,8 +27,6 @@ class Default extends Base {
 	public function new(name) {
 		super(name);
 		manager = new ShaderManager(getOutputs());
-		shaderIdMap = [];
-		textureIdMap = [];
 		initGlobals();
 	}
 
@@ -92,27 +86,17 @@ class Default extends Base {
 	}
 
 	@:access(h3d.scene)
-	override function draw( passes : h3d.pass.PassList ) {
+	override function draw( passes : h3d.pass.PassList, ?sort : h3d.pass.PassList -> Void ) {
 		if( passes.isEmpty() )
 			return;
 		for( g in ctx.sharedGlobals )
 			globals.fastSet(g.gid, g.value);
 		setGlobals();
 		setupShaders(passes);
-		if( sortPasses ) {
-			var shaderStart = shaderCount, textureStart = textureCount;
-			for( p in passes ) {
-				if( shaderIdMap[p.shader.id] < shaderStart #if js || shaderIdMap[p.shader.id] == null #end )
-					shaderIdMap[p.shader.id] = shaderCount++;
-				if( textureIdMap[p.texture] < textureStart #if js || textureIdMap[p.shader.id] == null #end )
-					textureIdMap[p.texture] = textureCount++;
-			}
-			passes.sort(function(o1, o2) {
-				var d = shaderIdMap[o1.shader.id] - shaderIdMap[o2.shader.id];
-				if( d != 0 ) return d;
-				return textureIdMap[o1.texture] - textureIdMap[o2.texture];
-			});
-		}
+		if( sort == null )
+			defaultSort(passes);
+		else
+			sort(passes);
 		ctx.currentManager = manager;
 		var buf = ctx.shaderBuffers, prevShader = null;
 		for( p in passes ) {

+ 2 - 2
h3d/pass/DefaultShadowMap.hx

@@ -24,8 +24,8 @@ class DefaultShadowMap extends DirShadowMap {
 		shadowBiasId = hxsl.Globals.allocID("shadow.bias");
 	}
 
-	override function draw( passes ) {
-		super.draw(passes);
+	override function draw( passes, ?sort ) {
+		super.draw(passes, sort);
 		ctx.setGlobalID(shadowMapId, { texture : dshader.shadowMap, channel : format == h3d.mat.Texture.nativeFormat ? hxsl.Channel.PackedFloat : hxsl.Channel.R });
 		ctx.setGlobalID(shadowProjId, getShadowProj());
 		ctx.setGlobalID(shadowColorId, color);

+ 2 - 2
h3d/pass/DirShadowMap.hx

@@ -185,7 +185,7 @@ class DirShadowMap extends Shadows {
 		return true;
 	}
 
-	override function draw( passes ) {
+	override function draw( passes, ?sort ) {
 		if( !filterPasses(passes) )
 			return;
 
@@ -215,7 +215,7 @@ class DirShadowMap extends Shadows {
 
 		ctx.engine.pushTarget(texture);
 		ctx.engine.clear(0xFFFFFF, 1);
-		super.draw(passes);
+		super.draw(passes, sort);
 		if( border != null ) border.render();
 		ctx.engine.popTarget();
 

+ 2 - 2
h3d/pass/HardwarePick.hx

@@ -63,7 +63,7 @@ class HardwarePick extends Default {
 		fixedColor.colorID.setColor(0xFF000000 | (++colorID));
 	}
 
-	override function draw(passes:h3d.pass.PassList) {
+	override function draw(passes:h3d.pass.PassList,?sort) {
 
 		for( cur in passes ) @:privateAccess {
 			// force all materials to use opaque blend
@@ -78,7 +78,7 @@ class HardwarePick extends Default {
 		ctx.engine.pushTarget(texOut);
 		ctx.engine.clear(0xFF000000, 1);
 		ctx.extraShaders = ctx.allocShaderList(fixedColor);
-		super.draw(passes);
+		super.draw(passes,sort);
 		ctx.extraShaders = null;
 		ctx.engine.popTarget();
 

+ 2 - 2
h3d/pass/PointShadowMap.hx

@@ -138,7 +138,7 @@ class PointShadowMap extends Shadows {
 		return tex;
 	}
 
-	override function draw( passes ) {
+	override function draw( passes, ?sort ) {
 		if( !filterPasses(passes) )
 			return;
 
@@ -177,7 +177,7 @@ class PointShadowMap extends Shadows {
 
 			var save = passes.save();
 			cullPasses(passes, function(col) return col.inFrustum(lightCamera.frustum));
-			super.draw(passes);
+			super.draw(passes,sort);
 			passes.load(save);
 			ctx.engine.popTarget();
 		}

+ 30 - 0
h3d/pass/SortByMaterial.hx

@@ -0,0 +1,30 @@
+package h3d.pass;
+
+class SortByMaterial {
+
+	var shaderCount : Int = 1;
+	var textureCount : Int = 1;
+	var shaderIdMap : Array<Int>;
+	var textureIdMap : Array<Int>;
+
+	public function new() {
+		shaderIdMap = [];
+		textureIdMap = [];
+	}
+
+	public function sort( passes : PassList ) {
+		var shaderStart = shaderCount, textureStart = textureCount;
+		for( p in passes ) {
+			if( shaderIdMap[p.shader.id] < shaderStart #if js || shaderIdMap[p.shader.id] == null #end )
+				shaderIdMap[p.shader.id] = shaderCount++;
+			if( textureIdMap[p.texture] < textureStart #if js || textureIdMap[p.shader.id] == null #end )
+				textureIdMap[p.texture] = textureCount++;
+		}
+		passes.sort(function(o1, o2) {
+			var d = shaderIdMap[o1.shader.id] - shaderIdMap[o2.shader.id];
+			if( d != 0 ) return d;
+			return textureIdMap[o1.texture] - textureIdMap[o2.texture];
+		});
+	}
+
+}

+ 2 - 2
h3d/pass/SpotShadowMap.hx

@@ -102,7 +102,7 @@ class SpotShadowMap extends Shadows {
 		return true;
 	}
 
-	override function draw( passes ) {
+	override function draw( passes, ?sort ) {
 		if( !filterPasses(passes) )
 			return;
 
@@ -118,7 +118,7 @@ class SpotShadowMap extends Shadows {
 
 		ctx.engine.pushTarget(texture);
 		ctx.engine.clear(0xFFFFFF, 1);
-		super.draw(passes);
+		super.draw(passes, sort);
 		if( border != null ) border.render();
 		ctx.engine.popTarget();
 

+ 6 - 9
h3d/scene/Renderer.hx

@@ -26,6 +26,8 @@ class Renderer extends hxd.impl.AnyProps {
 	var emptyPasses = new h3d.pass.PassList();
 	var ctx : RenderContext;
 	var hasSetTarget = false;
+	var frontToBack : h3d.pass.PassList -> Void;
+	var backToFront : h3d.pass.PassList -> Void;
 
 	public var effects : Array<h3d.impl.RendererFX> = [];
 
@@ -35,6 +37,9 @@ class Renderer extends hxd.impl.AnyProps {
 		allPasses = [];
 		passObjects = new SMap();
 		props = getDefaultProps();
+		// pre allocate closures
+		frontToBack = depthSort.bind(true);
+		backToFront = depthSort.bind(false);
 	}
 
 	public function dispose() {
@@ -82,7 +87,7 @@ class Renderer extends hxd.impl.AnyProps {
 	}
 
 	@:access(h3d.scene.Object)
-	function depthSort( passes : h3d.pass.PassList, frontToBack = false ) {
+	function depthSort( frontToBack, passes : h3d.pass.PassList ) {
 		var cam = ctx.camera.m;
 		for( p in passes ) {
 			var z = p.obj.absPos._41 * cam._13 + p.obj.absPos._42 * cam._23 + p.obj.absPos._43 * cam._33 + cam._43;
@@ -137,14 +142,6 @@ class Renderer extends hxd.impl.AnyProps {
 		return p.passes;
 	}
 
-	function getSort( name : String, front2Back = false ) {
-		var p = passObjects.get(name);
-		if( p == null ) return emptyPasses;
-		depthSort(p.passes, front2Back);
-		p.rendered = true;
-		return p.passes;
-	}
-
 	function draw( name : String ) {
 		defaultPass.draw(get(name));
 	}

+ 8 - 8
h3d/scene/fwd/Renderer.hx

@@ -16,11 +16,11 @@ class DepthPass extends h3d.pass.Default {
 		return [PackFloat(Value("output.depth"))];
 	}
 
-	override function draw( passes ) {
+	override function draw( passes, ?sort ) {
 		var texture = ctx.textures.allocTarget("depthMap", ctx.engine.width, ctx.engine.height, true);
 		ctx.engine.pushTarget(texture);
 		ctx.engine.clear(enableSky ? 0 : 0xFF0000, 1);
-		super.draw(passes);
+		super.draw(passes, sort);
 		ctx.engine.popTarget();
 		ctx.setGlobalID(depthMapId, { texture : texture });
 	}
@@ -40,11 +40,11 @@ class NormalPass extends h3d.pass.Default {
 		return [PackNormal(Value("output.normal"))];
 	}
 
-	override function draw( passes ) {
+	override function draw( passes, ?sort ) {
 		var texture = ctx.textures.allocTarget("normalMap", ctx.engine.width, ctx.engine.height);
 		ctx.engine.pushTarget(texture);
 		ctx.engine.clear(0x808080, 1);
-		super.draw(passes);
+		super.draw(passes, sort);
 		ctx.engine.popTarget();
 		ctx.setGlobalID(normalMapId, texture);
 	}
@@ -67,8 +67,8 @@ class Renderer extends h3d.scene.Renderer {
 	inline function get_def() return defaultPass;
 
 	// can be overriden for benchmark purposes
-	function renderPass(p:h3d.pass.Base, passes) {
-		p.draw(passes);
+	function renderPass(p:h3d.pass.Base, passes, ?sort) {
+		p.draw(passes, sort);
 	}
 
 	override function render() {
@@ -81,8 +81,8 @@ class Renderer extends h3d.scene.Renderer {
 		if( has("normal") )
 			renderPass(normal,get("normal"));
 
-		renderPass(defaultPass, getSort("default", true) );
-		renderPass(defaultPass, getSort("alpha") );
+		renderPass(defaultPass, get("default") );
+		renderPass(defaultPass, get("alpha"), backToFront );
 		renderPass(defaultPass, get("additive") );
 	}
 

+ 4 - 4
h3d/scene/pbr/Renderer.hx

@@ -180,15 +180,15 @@ class Renderer extends h3d.scene.Renderer {
 		passes.reset();
 	}
 
-	function renderPass(p:h3d.pass.Base, passes) {
+	function renderPass(p:h3d.pass.Base, passes, ?sort) {
 		cullPasses(passes, function(col) return col.inFrustum(ctx.camera.frustum));
-		p.draw(passes);
+		p.draw(passes, sort);
 		passes.reset();
 	}
 
 	function mainDraw() {
-		renderPass(output, getSort("default", true));
-		renderPass(output, getSort("alpha"));
+		renderPass(output, get("default"), frontToBack);
+		renderPass(output, get("alpha"), backToFront);
 		renderPass(output, get("additive"));
 	}