浏览代码

h2d correctly working with custom shaders

Nicolas Cannasse 11 年之前
父节点
当前提交
62bf6a8015
共有 7 个文件被更改,包括 150 次插入189 次删除
  1. 41 169
      h2d/Drawable.hx
  2. 60 16
      h2d/RenderContext.hx
  3. 5 1
      h3d/pass/Pass.hx
  4. 2 2
      h3d/shader/Base2d.hx
  5. 21 0
      h3d/shader/ColorAdd.hx
  6. 21 0
      h3d/shader/ColorMatrix.hx
  7. 0 1
      samples/2d/Main.hx

+ 41 - 169
h2d/Drawable.hx

@@ -1,100 +1,17 @@
 package h2d;
 
-/*
-private class DrawableShader extends h3d.impl.Shader {
-
-	static var SRC = {
-		var input : {
-			pos : Float2,
-			uv : Float2,
-			valpha : Float,
-			vcolor : Float4,
-		};
-		var tuv : Float2;
-		var tcolor : Float4;
-		var talpha : Float;
-
-		var hasVertexColor : Bool;
-		var hasVertexAlpha : Bool;
-		var uvScale : Float2;
-		var uvPos : Float2;
-		var skew : Float;
-		var zValue : Float;
-
-		function vertex( size : Float3, matA : Float3, matB : Float3 ) {
-			var tmp : Float4;
-			var spos = input.pos.xyw;
-			if( size != null ) spos *= size;
-			tmp.x = spos.dp3(matA);
-			tmp.y = spos.dp3(matB);
-			tmp.z = zValue;
-			tmp.w = skew != null ? 1 - skew * input.pos.y : 1;
-			out = tmp;
-			var t = input.uv;
-			if( uvScale != null ) t *= uvScale;
-			if( uvPos != null ) t += uvPos;
-			tuv = t;
-			if( hasVertexColor ) tcolor = input.vcolor;
-			if( hasVertexAlpha ) talpha = input.valpha;
-		}
-		
-		var hasAlpha : Bool;
-		var killAlpha : Bool;
-		
-		var alpha : Float;
-		var colorAdd : Float4;
-		var colorMul : Float4;
-		var colorMatrix : M44;
-
-		var hasAlphaMap : Bool;
-		var alphaMap : Texture;
-		var alphaUV : Float4;
-		var filter : Bool;
-		
-		var sinusDeform : Float3;
-		var tileWrap : Bool;
-
-		var hasMultMap : Bool;
-		var multMapFactor : Float;
-		var multMap : Texture;
-		var multUV : Float4;
-		var hasColorKey : Bool;
-		var colorKey : Int;
-
-		function fragment( tex : Texture ) {
-			var col = tex.get(sinusDeform != null ? [tuv.x + sin(tuv.y * sinusDeform.y + sinusDeform.x) * sinusDeform.z, tuv.y] : tuv, filter = ! !filter, wrap = tileWrap);
-			if( hasColorKey ) {
-				var cdiff = col.rgb - colorKey.rgb;
-				kill(cdiff.dot(cdiff) - 0.00001);
-			}
-			if( killAlpha ) kill(col.a - 0.001);
-			if( hasVertexAlpha ) col.a *= talpha;
-			if( hasVertexColor ) col *= tcolor;
-			if( hasAlphaMap ) col.a *= alphaMap.get(tuv * alphaUV.zw + alphaUV.xy).r;
-			if( hasMultMap ) col *= multMap.get(tuv * multUV.zw + multUV.xy) * multMapFactor;
-			if( hasAlpha ) col.a *= alpha;
-			if( colorMatrix != null ) col *= colorMatrix;
-			if( colorMul != null ) col *= colorMul;
-			if( colorAdd != null ) col += colorAdd;
-			out = col;
-		}
-
-
-	}
-	
-}
-*/
-
 class Drawable extends Sprite {
 	
 	public var color : h3d.Vector;
 	public var alpha(get, set) : Float;
 	public var blendMode : BlendMode;
+	var shaders : Array<hxsl.Shader>;
 	
 	function new(parent) {
 		super(parent);
 		blendMode = Normal;
 		color = new h3d.Vector(1, 1, 1, 1);
+		shaders = [];
 	}
 	
 	inline function get_alpha() {
@@ -105,10 +22,34 @@ class Drawable extends Sprite {
 		return color.a = v;
 	}
 	
+	public function getDebugShaderCode( toHxsl = true ) {
+		var shader = @:privateAccess {
+			var ctx = getScene().ctx;
+			var shaders : Array<hxsl.Shader> = [ctx.baseShader];
+			shaders = shaders.concat(this.shaders);
+			ctx.manager.compileShaders(shaders);
+		}
+		var toString = toHxsl ? function(d) return hxsl.Printer.shaderToString(d,true) : hxsl.GlslOut.toGlsl;
+		return "VERTEX=\n" + toString(shader.vertex.data) + "\n\nFRAGMENT=\n" + toString(shader.fragment.data);
+	}
+	
+	public inline function getShaders() {
+		return new hxd.impl.ArrayIterator<hxsl.Shader>(shaders);
+	}
+	
+	public function addShader<T:hxsl.Shader>( s : T ) : T {
+		this.shaders.push(s);
+		return s;
+	}
+	
+	public function removeShader( s : hxsl.Shader ) {
+		return this.shaders.remove(s);
+	}
+	
 	function emitTile( ctx : RenderContext, tile : Tile ) {
 		if( tile == null )
 			tile = new Tile(null, 0, 0, 5, 5);
-		ctx.beginDraw(tile.getTexture(), 8);
+		ctx.beginDraw(tile.getTexture(), 8, blendMode, shaders);
 
 		var ax = absX + tile.dx * matA + tile.dy * matC;
 		var ay = absY + tile.dx * matB + tile.dy * matD;
@@ -127,8 +68,16 @@ class Drawable extends Sprite {
 		emit(color.b);
 		emit(color.a);
 		
-		emit(ax + matA);
-		emit(ay + matB);
+		
+		var tw = tile.width;
+		var th = tile.height;
+		var dx1 = tw * matA;
+		var dy1 = tw * matB;
+		var dx2 = th * matC;
+		var dy2 = th * matD;
+		
+		emit(ax + dx1);
+		emit(ay + dy1);
 		emit(tile.u2);
 		emit(tile.v);
 		emit(color.r);
@@ -136,8 +85,8 @@ class Drawable extends Sprite {
 		emit(color.b);
 		emit(color.a);
 		
-		emit(ax + matC);
-		emit(ay + matD);
+		emit(ax + dx2);
+		emit(ay + dy2);
 		emit(tile.u);
 		emit(tile.v2);
 		emit(color.r);
@@ -145,8 +94,8 @@ class Drawable extends Sprite {
 		emit(color.b);
 		emit(color.a);
 
-		emit(ax + matA + matC);
-		emit(ay + matB + matD);
+		emit(ax + dx1 + dx2);
+		emit(ay + dy1 + dy2);
 		emit(tile.u2);
 		emit(tile.v2);
 		emit(color.r);
@@ -156,82 +105,5 @@ class Drawable extends Sprite {
 
 		ctx.bufPos = pos;
 	}
-
-	/*
-	function drawTile( engine, tile ) {
-		//setupShader(engine, tile, HAS_SIZE | HAS_UV_POS | HAS_UV_SCALE);
-		//engine.renderQuadBuffer(Tools.getCoreObjects().planBuffer);
-	}
-
-	/*
-	function setupShader( engine : h3d.Engine, tile : h2d.Tile, options : Int ) {
-		var core = Tools.getCoreObjects();
-		var shader = shader;
-		var mat = core.tmpMaterial;
-
-		if( tile == null )
-			tile = new Tile(core.getEmptyTexture(), 0, 0, 5, 5);
-
-		switch( blendMode ) {
-		case Normal:
-			mat.blend(SrcAlpha, OneMinusSrcAlpha);
-		case None:
-			mat.blend(One, Zero);
-		case Add:
-			mat.blend(SrcAlpha, One);
-		case SoftAdd:
-			mat.blend(OneMinusDstColor, One);
-		case Multiply:
-			mat.blend(DstColor, OneMinusSrcAlpha);
-		case Erase:
-			mat.blend(Zero, OneMinusSrcAlpha);
-		}
-
-		if( options & HAS_SIZE != 0 ) {
-			var tmp = core.tmpSize;
-			// adds 1/10 pixel size to prevent precision loss after scaling
-			tmp.x = tile.width + 0.1;
-			tmp.y = tile.height + 0.1;
-			tmp.z = 1;
-			shader.size = tmp;
-		}
-		if( options & HAS_UV_POS != 0 ) {
-			core.tmpUVPos.x = tile.u;
-			core.tmpUVPos.y = tile.v;
-			shader.uvPos = core.tmpUVPos;
-		}
-		if( options & HAS_UV_SCALE != 0 ) {
-			core.tmpUVScale.x = tile.u2 - tile.u;
-			core.tmpUVScale.y = tile.v2 - tile.v;
-			shader.uvScale = core.tmpUVScale;
-		}
-		
-		if( shader.hasAlphaMap ) {
-			shader.alphaMap = alphaMap.getTexture();
-			shader.alphaUV = new h3d.Vector(alphaMap.u, alphaMap.v, (alphaMap.u2 - alphaMap.u) / tile.u2, (alphaMap.v2 - alphaMap.v) / tile.v2);
-		}
-
-		if( shader.hasMultMap ) {
-			shader.multMap = multiplyMap.getTexture();
-			shader.multUV = new h3d.Vector(multiplyMap.u, multiplyMap.v, (multiplyMap.u2 - multiplyMap.u) / tile.u2, (multiplyMap.v2 - multiplyMap.v) / tile.v2);
-		}
-		
-		var cm = writeAlpha ? 15 : 7;
-		if( mat.colorMask != cm ) mat.colorMask = cm;
-		
-		var tmp = core.tmpMatA;
-		tmp.x = matA;
-		tmp.y = matC;
-		tmp.z = absX + tile.dx * matA + tile.dy * matC;
-		shader.matA = tmp;
-		var tmp = core.tmpMatB;
-		tmp.x = matB;
-		tmp.y = matD;
-		tmp.z = absY + tile.dx * matB + tile.dy * matD;
-		shader.matB = tmp;
-		shader.tex = tile.getTexture();
-		mat.shader = shader;
-		engine.selectMaterial(mat);
-	}*/
 	
 }

+ 60 - 16
h2d/RenderContext.hx

@@ -11,13 +11,14 @@ class RenderContext {
 	public var bufPos : Int;
 	
 	var texture : h3d.mat.Texture;
-	var shader : h3d.shader.Base2d;
+	var baseShader : h3d.shader.Base2d;
 	var manager : h3d.shader.Manager;
 	var compiledShader : hxsl.RuntimeShader;
 	var buffers : h3d.shader.Buffers;
 	var pass : h3d.pass.Pass;
 	var currentShaders : Array<hxsl.Shader>;
 	var stride : Int;
+	var blendMode : BlendMode;
 	
 	public function new() {
 		frame = 0;
@@ -26,17 +27,19 @@ class RenderContext {
 		buffer = new hxd.FloatBuffer();
 		bufPos = 0;
 		manager = new h3d.shader.Manager(["output.position", "output.color"]);
+		pass = new h3d.pass.Pass("",[]);
+		pass.depth(true, Always);
+		pass.culling = None;
+		baseShader = new h3d.shader.Base2d();
+		baseShader.zValue = 0.;
 	}
 	
 	public function begin() {
 		texture = null;
 		bufPos = 0;
 		stride = 0;
-		if( shader == null ) {
-			shader = new h3d.shader.Base2d();
-			shader.zValue = 0.;
-			initShaders([shader]);
-		}
+		if( compiledShader == null )
+			initShaders([baseShader]);
 		@:privateAccess {
 			engine.driver.selectShader(compiledShader);
 			engine.driver.selectMaterial(pass);
@@ -49,10 +52,6 @@ class RenderContext {
 		compiledShader = manager.compileShaders(shaders);
 		buffers = new h3d.shader.Buffers(compiledShader);
 		manager.fillGlobals(buffers, compiledShader);
-		pass = new h3d.pass.Pass("",[]);
-		pass.blend(SrcAlpha, OneMinusSrcAlpha);
-		pass.depth(true, Always);
-		pass.culling = None;
 	}
 	
 	public function end() {
@@ -62,9 +61,27 @@ class RenderContext {
 	
 	public function flush() {
 		if( bufPos == 0 ) return;
-		shader.texture = texture;
+		baseShader.texture = texture;
+		switch( blendMode ) {
+		case Normal:
+			pass.blend(SrcAlpha, OneMinusSrcAlpha);
+		case None:
+			pass.blend(One, Zero);
+		case Add:
+			pass.blend(SrcAlpha, One);
+		case SoftAdd:
+			pass.blend(OneMinusDstColor, One);
+		case Multiply:
+			pass.blend(DstColor, OneMinusSrcAlpha);
+		case Erase:
+			pass.blend(Zero, OneMinusSrcAlpha);
+		}
 		manager.fillParams(buffers, compiledShader, currentShaders);
-		@:privateAccess engine.driver.uploadShaderBuffers(buffers, Params);
+		@:privateAccess {
+			engine.driver.selectMaterial(pass);
+			engine.driver.uploadShaderBuffers(buffers, Params);
+			engine.driver.uploadShaderBuffers(buffers, Textures);
+		}
 		var nverts = Std.int(bufPos / stride);
 		var tmp = engine.mem.alloc(nverts, stride, 4);
 		tmp.uploadVector(buffer, 0, nverts);
@@ -72,15 +89,42 @@ class RenderContext {
 		tmp.dispose();
 		bufPos = 0;
 		texture = null;
-		trace(nverts);
-		trace(buffer);
 	}
 	
-	public function beginDraw( texture : h3d.mat.Texture, stride : Int ) {
-		if( texture != this.texture || stride != this.stride )
+	public function beginDraw( texture : h3d.mat.Texture, stride : Int, blendMode : BlendMode, shaders : Array<hxsl.Shader> ) {
+		if( texture != this.texture || stride != this.stride || blendMode != this.blendMode )
 			flush();
+		var shaderChanged = false, paramsChanged = false;
+		if( shaders.length + 1 != currentShaders.length )
+			shaderChanged = true;
+		else {
+			for( i in 0...shaders.length ) {
+				var s = shaders[i];
+				var t = currentShaders[i + 1];
+				if( s == t ) continue;
+				paramsChanged = true;
+				s.updateConstants(manager.globals);
+				@:privateAccess {
+					if( s.instance != t.instance )
+						shaderChanged = true;
+				}
+			}
+		}
+		if( shaderChanged ) {
+			flush();
+			var ns = shaders.copy();
+			ns.unshift(baseShader);
+			initShaders(ns);
+		} else if( paramsChanged ) {
+			flush();
+			// copy so the next flush will fetch their params
+			for( i in 0...shaders.length )
+				currentShaders[i+1] = shaders[i];
+		}
+			
 		this.texture = texture;
 		this.stride = stride;
+		this.blendMode = blendMode;
 	}
 
 }

+ 5 - 1
h3d/pass/Pass.hx

@@ -63,7 +63,11 @@ class Pass {
 	public function removeShader(s) {
 		return shaders.remove(s);
 	}
-	
+
+	public inline function getShaders() {
+		return new hxd.impl.ArrayIterator<hxsl.Shader>(shaders);
+	}
+
 	function getShadersRec() {
 		if( parentPass == null )
 			return shaders;

+ 2 - 2
h3d/shader/Base2d.hx

@@ -20,7 +20,7 @@ class Base2d extends hxsl.Shader {
 		
 		var spritePosition : Vec4;
 		var pixelColor : Vec4;
-		var calculateUV : Vec2;
+		@var var calculateUV : Vec2;
 
 		function __init__() {
 			spritePosition = vec4(input.position, zValue, 1);
@@ -34,7 +34,7 @@ class Base2d extends hxsl.Shader {
 		}
 		
 		function fragment() {
-			output.color = vec4(1,1,1,1);
+			output.color = pixelColor;
 		}
 		
 	};

+ 21 - 0
h3d/shader/ColorAdd.hx

@@ -0,0 +1,21 @@
+package h3d.shader;
+
+class ColorAdd extends hxsl.Shader {
+
+	static var SRC = {
+		var pixelColor : Vec4;
+		
+		@param var color : Vec3;
+
+		function fragment() {
+			pixelColor.rgb += color;
+		}
+		
+	};
+	
+	public function new( ?color : Int ) {
+		super();
+		if( color != null ) this.color.setColor(color);
+	}
+
+}

+ 21 - 0
h3d/shader/ColorMatrix.hx

@@ -0,0 +1,21 @@
+package h3d.shader;
+
+class ColorMatrix extends hxsl.Shader {
+
+	static var SRC = {
+		var pixelColor : Vec4;
+		
+		@param var matrix : Mat4;
+
+		function fragment() {
+			pixelColor *= matrix;
+		}
+		
+	};
+	
+	public function new( ?m : Array<Float> ) {
+		super();
+		if( m != null ) this.matrix.load(m) else this.matrix.identity();
+	}
+
+}

+ 0 - 1
samples/2d/Main.hx

@@ -37,7 +37,6 @@ class Main extends hxd.App {
 	
 	override function update(dt:Float) {
 		spr.rotation += 0.01 * dt;
-		hxd.System.setLoop(function() { } );
 	}
 	
 	static function main() {