瀏覽代碼

fixed alpha correctness wrt filters (Add,Alpha only for now)
moved blendMode from Drawable+Filter to h2d.Object (allow post filter blend)

Nicolas Cannasse 6 年之前
父節點
當前提交
ab2138bd30
共有 4 個文件被更改,包括 31 次插入34 次删除
  1. 0 13
      h2d/Drawable.hx
  2. 16 14
      h2d/Object.hx
  3. 15 2
      h2d/RenderContext.hx
  4. 0 5
      h2d/filter/Filter.hx

+ 0 - 13
h2d/Drawable.hx

@@ -11,11 +11,6 @@ class Drawable extends Object {
 	**/
 	public var color(default,default) : h3d.Vector;
 
-	/**
-		The blendMode of the object (default Alpha)
-	**/
-	public var blendMode : BlendMode;
-
 	/**
 		By enabling smoothing, scaling the object up or down will use hardware bilinear filtering resulting in less crisp aspect.
 		By default smooth is null and then Scene.defaultSmooth value is used.
@@ -46,7 +41,6 @@ class Drawable extends Object {
 
 	function new(parent : h2d.Object) {
 		super(parent);
-		blendMode = Alpha;
 		color = new h3d.Vector(1, 1, 1, 1);
 	}
 
@@ -190,13 +184,6 @@ class Drawable extends Object {
 		return false;
 	}
 
-	override function emitFilterTile( ctx, tile ) {
-		var oldBlend = blendMode;
-		if( filter.blendMode != null ) blendMode = filter.blendMode;
-		emitTile(ctx, tile);
-		if( filter.blendMode != null ) blendMode = oldBlend;
-	}
-
 	override function emitTile( ctx : RenderContext, tile : Tile ) {
 		if( tile == null )
 			tile = new Tile(null, 0, 0, 5, 5);

+ 16 - 14
h2d/Object.hx

@@ -69,6 +69,13 @@ class Object {
 	**/
 	public var filter(default,set) : h2d.filter.Filter;
 
+	/**
+		The blendMode of the object (default Alpha). 
+		If there is no filter active, only apply to the current object (not inherited by children)  
+		If there is a filter active, tells how the filter is blended with background.
+	**/
+	public var blendMode : BlendMode;
+
 	var matA : Float;
 	var matB : Float;
 	var matC : Float;
@@ -86,6 +93,7 @@ class Object {
 	public function new( ?parent : Object ) {
 		matA = 1; matB = 0; matC = 0; matD = 1; absX = 0; absY = 0;
 		x = 0; y = 0; scaleX = 1; scaleY = 1; rotation = 0;
+		blendMode = Alpha;
 		posChanged = parent != null;
 		visible = true;
 		children = [];
@@ -725,21 +733,15 @@ class Object {
 		if( finalTile == null )
 			return;
 
-		ctx.globalAlpha = oldAlpha * alpha;
-		emitFilterTile(ctx, finalTile);
-		ctx.globalAlpha = oldAlpha;
-		ctx.flush();
-	}
-
-	function emitFilterTile( ctx, tile ) {
-		if( filter.blendMode != null ) {
-			if( nullDrawable == null )
-				nullDrawable = @:privateAccess new h2d.Drawable(null);
-			nullDrawable.blendMode = filter.blendMode;
+		@:privateAccess {
+			ctx.currentBlend = null;
+			ctx.inFilterBlend = blendMode;
+			ctx.globalAlpha = oldAlpha * alpha;
+			emitTile(ctx, finalTile);
+			ctx.globalAlpha = oldAlpha;
+			ctx.flush();
+			ctx.inFilterBlend = null;
 		}
-		emitTile(ctx, tile);
-		if( filter.blendMode != null )
-			nullDrawable.blendMode = Alpha;
 	}
 
 	function drawRec( ctx : RenderContext ) {

+ 15 - 2
h2d/RenderContext.hx

@@ -33,6 +33,7 @@ class RenderContext extends h3d.impl.RenderContext {
 	var hasUVPos : Bool;
 	var filterStack : Array<h2d.Object>;
 	var inFilter : Object;
+	var inFilterBlend : BlendMode;
 
 	var curX : Int;
 	var curY : Int;
@@ -58,8 +59,6 @@ class RenderContext extends h3d.impl.RenderContext {
 		pass = new h3d.mat.Pass("",null);
 		pass.depth(true, Always);
 		pass.culling = None;
-		currentBlend = Alpha;
-		pass.setBlendMode(currentBlend);
 		baseShader = new h3d.shader.Base2d();
 		baseShader.setPriority(100);
 		baseShader.zValue = 0.;
@@ -179,6 +178,7 @@ class RenderContext extends h3d.impl.RenderContext {
 		curY = startY;
 		curWidth = width;
 		curHeight = height;
+		currentBlend = null;
 		if( hasRenderZone ) clearRenderZone();
 	}
 
@@ -267,9 +267,22 @@ class RenderContext extends h3d.impl.RenderContext {
 		texture.wrap = currentObj.tileWrap && (currentObj.filter == null || inFilter != null) ? Repeat : Clamp;
 		var blend = currentObj.blendMode;
 		if( inFilter == currentObj && blend == Erase ) blend = Add; // add THEN erase
+		if( inFilterBlend != null ) blend = inFilterBlend;
 		if( blend != currentBlend ) {
 			currentBlend = blend;
 			pass.setBlendMode(blend);
+			#if flash
+			// flash does not allow blend separate operations
+			// this will get us good color but wrong alpha
+			#else
+			// accummulate correctly alpha values
+			if( blend == Alpha || blend == Add ) {
+				pass.blendAlphaSrc = One;
+				// when merging
+				if( inFilterBlend != null )
+					pass.blendSrc = One;
+			}
+			#end
 		}
 		manager.fillParams(buffers, compiledShader, currentShaders);
 		engine.selectMaterial(pass);

+ 0 - 5
h2d/filter/Filter.hx

@@ -9,11 +9,6 @@ class Filter {
 	public var boundsExtend : Float = 0.;
 	public var smooth = false;
 
-	/**
-		When set, will use this blend mode when merging the filtered output to screen.
-	**/
-	public var blendMode : Null<h2d.BlendMode>;
-
 	function new() {
 	}