瀏覽代碼

added pass dynamic parameters for layered object draw

Nicolas Cannasse 11 年之前
父節點
當前提交
d6d6e49060
共有 4 個文件被更改,包括 46 次插入30 次删除
  1. 6 1
      h3d/mat/Pass.hx
  2. 26 19
      h3d/pass/Base.hx
  3. 4 0
      h3d/scene/RenderContext.hx
  4. 10 10
      h3d/scene/Skin.hx

+ 6 - 1
h3d/mat/Pass.hx

@@ -14,6 +14,11 @@ class Pass {
 	var nextPass : Pass;
 
 	public var enableLights : Bool;
+	/**
+		Inform the pass system that the parameters will be modified in object draw() command,
+		so they will be manually uploaded by calling RenderContext.uploadParams.
+	**/
+	public var dynamicParameters : Bool;
 
 	@:bits public var culling : Face;
 	@:bits public var depthWrite : Bool;
@@ -26,7 +31,7 @@ class Pass {
 	@:bits public var blendAlphaOp : Operation;
 	@:bits(4) public var colorMask : Int;
 
-	public function new(name, shaders, ?parent) {
+	public function new(name, ?shaders, ?parent) {
 		this.parentPass = parent;
 		this.shaders = shaders;
 		setPassName(name);

+ 26 - 19
h3d/pass/Base.hx

@@ -43,17 +43,6 @@ class Base {
 		return manager.compileShaders(out);
 	}
 
-	function initBuffer( s : hxsl.RuntimeShader, shaders : Array<hxsl.Shader> ) {
-		if( cachedBuffer == null )
-			cachedBuffer = new h3d.shader.Buffers(s);
-		else
-			cachedBuffer.grow(s);
-		var buf = cachedBuffer;
-		manager.fillGlobals(buf, s);
-		manager.fillParams(buf, s, shaders);
-		return buf;
-	}
-
 	@:access(h3d.scene)
 	function setupShaders( passes : Object ) {
 		var p = passes;
@@ -95,6 +84,12 @@ class Base {
 		return 0;
 	}
 
+	function uploadParams() {
+		manager.fillParams(cachedBuffer, ctx.drawPass.shader, ctx.drawPass.shaders);
+		ctx.engine.uploadShaderBuffers(cachedBuffer, Params);
+		ctx.engine.uploadShaderBuffers(cachedBuffer, Textures);
+	}
+
 	@:access(h3d.scene)
 	public function draw( ctx : h3d.scene.RenderContext, passes : Object ) {
 		this.ctx = ctx;
@@ -103,17 +98,29 @@ class Base {
 		setGlobals();
 		setupShaders(passes);
 		passes = haxe.ds.ListSort.sortSingleLinked(passes, sortByShader);
+		ctx.uploadParams = uploadParams;
 		var p = passes;
+		var buf = cachedBuffer, prevShader = null;
 		while( p != null ) {
 			globalModelView = p.obj.absPos;
-			//if( p.shader.hasGlobal(globalModelViewInverseId) )
-			globalModelViewInverse = p.obj.getInvPos();
-			ctx.engine.selectShader(p.shader);
-			var buf = initBuffer(p.shader, p.shaders);
-			ctx.engine.selectMaterial(p.pass);
-			ctx.engine.uploadShaderBuffers(buf, Globals);
-			ctx.engine.uploadShaderBuffers(buf, Params);
-			ctx.engine.uploadShaderBuffers(buf, Textures);
+			if( p.shader.hasGlobal(globalModelViewInverse_id.toInt()) )
+				globalModelViewInverse = p.obj.getInvPos();
+			if( prevShader != p.shader ) {
+				prevShader = p.shader;
+				ctx.engine.selectShader(p.shader);
+				ctx.engine.selectMaterial(p.pass);
+				if( buf == null )
+					buf = cachedBuffer = new h3d.shader.Buffers(p.shader);
+				else
+					buf.grow(p.shader);
+				manager.fillGlobals(buf, p.shader);
+				ctx.engine.uploadShaderBuffers(buf, Globals);
+			}
+			if( !p.pass.dynamicParameters ) {
+				manager.fillParams(buf, p.shader, p.shaders);
+				ctx.engine.uploadShaderBuffers(buf, Params);
+				ctx.engine.uploadShaderBuffers(buf, Textures);
+			}
 			ctx.drawPass = p;
 			p.obj.draw(ctx);
 			p = p.next;

+ 4 - 0
h3d/scene/RenderContext.hx

@@ -13,6 +13,8 @@ class RenderContext {
 
 	public var sharedGlobals : Map<Int,Dynamic>;
 
+	public var uploadParams : Void -> Void;
+
 	var pool : ObjectPass;
 	var passes : ObjectPass;
 	var lights : Light;
@@ -38,6 +40,7 @@ class RenderContext {
 		drawPass = null;
 		passes = null;
 		lights = null;
+		uploadParams = null;
 		time += elapsedTime;
 		frame++;
 	}
@@ -62,6 +65,7 @@ class RenderContext {
 
 	public function done() {
 		drawPass = null;
+		uploadParams = null;
 		// move passes to pool, and erase data
 		var p = passes, prev = null;
 		while( p != null ) {

+ 10 - 10
h3d/scene/Skin.hx

@@ -120,8 +120,10 @@ class Skin extends MultiMaterial {
 		primitive = s.primitive;
 		skinShader = new h3d.shader.Skin();
 		for( m in materials )
-			if( m != null )
+			if( m != null ) {
 				m.mainPass.addShader(skinShader);
+				if( skinData.splitJoints != null ) m.mainPass.dynamicParameters = true;
+			}
 		currentRelPose = [];
 		currentAbsPose = [];
 		currentPalette = [];
@@ -156,7 +158,7 @@ class Skin extends MultiMaterial {
 				if( bid >= 0 )
 					currentPalette[bid].multiply3x4(j.transPos, m);
 			}
-			paletteChanged = true;
+			skinShader.bonesMatrixes = currentPalette;
 			if( jointsAbsPosInv != null ) jointsAbsPosInv._44 = 0; // mark as invalid
 			jointsUpdated = false;
 		} else
@@ -165,16 +167,14 @@ class Skin extends MultiMaterial {
 
 	override function draw( ctx : RenderContext ) {
 		if( splitPalette == null ) {
-			if( paletteChanged ) {
-				paletteChanged = false;
-				skinShader.bonesMatrixes = currentPalette;
-			}
 			super.draw(ctx);
 		} else {
-			var i = ctx.drawPass.index;
-			skinShader.bonesMatrixes = splitPalette[i];
-			primitive.selectMaterial(i);
-			super.draw(ctx);
+			for( i in 0...splitPalette.length ) {
+				skinShader.bonesMatrixes = splitPalette[i];
+				primitive.selectMaterial(i);
+				ctx.uploadParams();
+				primitive.render(ctx.engine);
+			}
 		}
 		if( showJoints )
 			throw "TODO"; //ctx.addPass(drawJoints);