Explorar el Código

keep absolute coordinates when processing filters, close #111

ncannasse hace 10 años
padre
commit
657c5f6b3d
Se han modificado 3 ficheros con 57 adiciones y 17 borrados
  1. 30 7
      h2d/RenderContext.hx
  2. 20 10
      h2d/Sprite.hx
  3. 7 0
      h3d/shader/Base2d.hx

+ 30 - 7
h2d/RenderContext.hx

@@ -24,6 +24,7 @@ class RenderContext extends h3d.impl.RenderContext {
 	var s2d : Scene;
 	var targetsStack : Array<{ t : h3d.mat.Texture, x : Int, y : Int, w : Int, h : Int }>;
 	var hasUVPos : Bool;
+	var inFilter : Bool;
 
 	var curX : Int;
 	var curY : Int;
@@ -59,6 +60,7 @@ class RenderContext extends h3d.impl.RenderContext {
 		stride = 0;
 		curX = 0;
 		curY = 0;
+		inFilter = false;
 		curWidth = s2d.width;
 		curHeight = s2d.height;
 		manager.globals.set("time", time);
@@ -66,6 +68,8 @@ class RenderContext extends h3d.impl.RenderContext {
 		baseShader.pixelAlign = #if flash true #else false #end;
 		baseShader.halfPixelInverse.set(0.5 / engine.width, 0.5 / engine.height);
 		baseShader.viewport.set( -s2d.width * 0.5, -s2d.height * 0.5, 2 / s2d.width, -2 / s2d.height);
+		baseShader.filterMatrixA.set(1, 0, 0);
+		baseShader.filterMatrixB.set(0, 1, 0);
 		baseShaderList.next = null;
 		initShaders(baseShaderList);
 		engine.selectMaterial(pass);
@@ -175,19 +179,38 @@ class RenderContext extends h3d.impl.RenderContext {
 	@:access(h2d.Drawable)
 	public function drawTile( obj : h2d.Drawable, tile : h2d.Tile ) {
 
+		var matA, matB, matC, matD, absX, absY;
+		if( inFilter ) {
+			var f1 = baseShader.filterMatrixA;
+			var f2 = baseShader.filterMatrixB;
+			matA = obj.matA * f1.x + obj.matB * f1.y;
+			matB = obj.matA * f2.x + obj.matB * f2.y;
+			matC = obj.matC * f1.x + obj.matD * f1.y;
+			matD = obj.matC * f2.x + obj.matD * f2.y;
+			absX = obj.absX * f1.x + obj.absY * f1.y + f1.z;
+			absY = obj.absX * f2.x + obj.absY * f2.y + f2.z;
+		} else {
+			matA = obj.matA;
+			matB = obj.matB;
+			matC = obj.matC;
+			matD = obj.matD;
+			absX = obj.absX;
+			absY = obj.absY;
+		}
+
 		// check if our tile is outside of the viewport
-		if( obj.matB == 0 && obj.matC == 0 ) {
+		if( matB == 0 && matC == 0 ) {
 			var tx = tile.dx + tile.width * 0.5;
 			var ty = tile.dy + tile.height * 0.5;
 			var tr = (tile.width > tile.height ? tile.width : tile.height) * 1.5 * hxd.Math.max(hxd.Math.abs(obj.matA),hxd.Math.abs(obj.matD));
-			var cx = obj.absX + tx * obj.matA - curX;
-			var cy = obj.absY + ty * obj.matD - curY;
+			var cx = absX + tx * matA - curX;
+			var cy = absY + ty * matD - curY;
 			if( cx < -tr || cy < -tr || cx - tr > curWidth || cy - tr > curHeight ) return;
 		} else {
 			var xMin = 1e20, yMin = 1e20, xMax = -1e20, yMax = -1e20;
 			inline function calc(x:Int, y:Int) {
-				var px = (x + tile.dx) * obj.matA + (y + tile.dy) * obj.matC;
-				var py = (x + tile.dx) * obj.matB + (y + tile.dy) * obj.matD;
+				var px = (x + tile.dx) * matA + (y + tile.dy) * matC;
+				var py = (x + tile.dx) * matB + (y + tile.dy) * matD;
 				if( px < xMin ) xMin = px;
 				if( px > xMax ) xMax = px;
 				if( py < yMin ) yMin = py;
@@ -199,8 +222,8 @@ class RenderContext extends h3d.impl.RenderContext {
 			calc(tile.width, 0);
 			calc(0, tile.height);
 			calc(tile.width, tile.height);
-			var cx = obj.absX - curX;
-			var cy = obj.absY - curY;
+			var cx = absX - curX;
+			var cy = absY - curY;
 			if( cx + xMax < 0 || cy + yMax < 0 || cx + xMin > curWidth || cy + yMin > curHeight )
 				return;
 		}

+ 20 - 10
h2d/Sprite.hx

@@ -483,21 +483,31 @@ class Sprite {
 
 		// reset transform and update childs
 		var oldAlpha = ctx.globalAlpha;
-		var oldA = matA, oldB = matB, oldC = matC, oldD = matD, oldX = absX, oldY = absY;
-		matA = 1; matB = 0; matC = 0; matD = 1; absX = 0; absY = 0;
+		var shader = @:privateAccess ctx.baseShader;
+		var oldA = shader.filterMatrixA.clone();
+		var oldB = shader.filterMatrixB.clone();
+		var oldF = @:privateAccess ctx.inFilter;
+
+		// 2x3 inverse matrix
+		var invDet = 1 / (matA * matD - matB * matC);
+		var invA = matD * invDet;
+		var invB = -matB * invDet;
+		var invC = -matC * invDet;
+		var invD = matA * invDet;
+		var invX = -(absX * invA + absY * invC);
+		var invY = -(absX * invB + absY * invD);
+
+		@:privateAccess ctx.inFilter = true;
+		shader.filterMatrixA.set(invA, invC, invX);
+		shader.filterMatrixB.set(invB, invD, invY);
 		ctx.globalAlpha = 1;
-		for( c in childs )
-			c.posChanged = true;
 		draw(ctx);
 		for( c in childs )
 			c.drawRec(ctx);
-		matA = oldA;
-		matB = oldB;
-		matC = oldC;
-		matD = oldD;
-		absX = oldX;
-		absY = oldY;
 		ctx.flush();
+		shader.filterMatrixA.load(oldA);
+		shader.filterMatrixB.load(oldB);
+		@:privateAccess ctx.inFilter = oldF;
 
 		var final = h2d.Tile.fromTexture(t);
 		final.dx = xMin;

+ 7 - 0
h3d/shader/Base2d.hx

@@ -29,6 +29,8 @@ class Base2d extends hxsl.Shader {
 		@param var color : Vec4;
 		@param var absoluteMatrixA : Vec3;
 		@param var absoluteMatrixB : Vec3;
+		@param var filterMatrixA : Vec3;
+		@param var filterMatrixB : Vec3;
 		@const var hasUVPos : Bool;
 		@param var uvPos : Vec4;
 
@@ -51,6 +53,11 @@ class Base2d extends hxsl.Shader {
 		}
 
 		function vertex() {
+			// transform from global to render texture coordinates
+			var tmp = vec3(absolutePosition.xy, 1);
+			absolutePosition.x = tmp.dot(filterMatrixA);
+			absolutePosition.y = tmp.dot(filterMatrixB);
+			// transform to viewport
 			absolutePosition.xy = (absolutePosition.xy + viewport.xy) * viewport.zw;
 			// http://msdn.microsoft.com/en-us/library/windows/desktop/bb219690(v=vs.85).aspx
 			if( pixelAlign ) absolutePosition.xy -= halfPixelInverse;