Răsfoiți Sursa

fixed texture capture with correct alpha support

ncannasse 9 ani în urmă
părinte
comite
92126a8d2f
2 a modificat fișierele cu 44 adăugiri și 2 ștergeri
  1. 30 2
      h3d/mat/Texture.hx
  2. 14 0
      h3d/shader/AlphaChannel.hx

+ 30 - 2
h3d/mat/Texture.hx

@@ -185,10 +185,10 @@ class Texture {
 	}
 
 	/**
-		Downloads the current texture data from the GPU. On some platforms, color might be premultiplied by Alpha.
+		Downloads the current texture data from the GPU. On some platforms, color might be premultiplied by Alpha unless withAlpha = true.
 		Beware, this is a very slow operation that shouldn't be done during rendering.
 	**/
-	public function capturePixels() {
+	public function capturePixels( withAlpha = false ) {
 		#if js
 
 		var e = h3d.Engine.getCurrent();
@@ -199,6 +199,9 @@ class Texture {
 		e.popTarget();
 
 		#else
+
+		var twoPassCapture = #if flash withAlpha #else false #end;
+
 		var e = h3d.Engine.getCurrent();
 		var oldW = e.width, oldH = e.height;
 		var oldF = filter, oldM = mipMap, oldWrap = wrap;
@@ -207,6 +210,11 @@ class Texture {
 		e.driver.clear(new h3d.Vector(0, 0, 0, 0),1,0);
 		var s2d = new h2d.Scene();
 		var b = new h2d.Bitmap(h2d.Tile.fromTexture(this), s2d);
+		var shader = null;
+		if( twoPassCapture ) {
+			shader = new h3d.shader.AlphaChannel();
+			b.addShader(shader); // erase alpha
+		}
 		b.blendMode = None;
 
 		mipMap = None;
@@ -219,6 +227,26 @@ class Texture {
 
 		var pixels = hxd.Pixels.alloc(width, height, ARGB);
 		e.driver.captureRenderBuffer(pixels);
+
+		if( twoPassCapture ) {
+			shader.showAlpha = true;
+			s2d.render(e); // render only alpha channel
+			var alpha = hxd.Pixels.alloc(width, height, ARGB);
+			e.driver.captureRenderBuffer(alpha);
+			var alphaPos = hxd.Pixels.getChannelOffset(alpha.format, 3);
+			var redPos = hxd.Pixels.getChannelOffset(alpha.format, 0);
+			var bpp = hxd.Pixels.bytesPerPixel(alpha.format);
+			for( y in 0...height ) {
+				var p = y * width * bpp;
+				for( x in 0...width ) {
+					pixels.bytes.set(p + alphaPos, alpha.bytes.get(p + redPos)); // copy alpha value only
+					p += bpp;
+				}
+			}
+			alpha.dispose();
+			pixels.flags.unset(AlphaPremultiplied);
+		}
+
 		if( e.width != oldW || e.height != oldH )
 			e.resize(oldW, oldH);
 		e.driver.clear(new h3d.Vector(0, 0, 0, 0));

+ 14 - 0
h3d/shader/AlphaChannel.hx

@@ -0,0 +1,14 @@
+package h3d.shader;
+
+class AlphaChannel extends hxsl.Shader {
+
+	static var SRC = {
+		var pixelColor : Vec4;
+		@const var showAlpha : Bool;
+		function fragment() {
+			if( showAlpha ) pixelColor.rgb = pixelColor.aaa;
+			pixelColor.a = 1.;
+		}
+	}
+
+}