Explorar el Código

Add capturePixels optional sub region argument (#509)

Pavel Alexandrov hace 6 años
padre
commit
f40c668c6f
Se han modificado 4 ficheros con 53 adiciones y 12 borrados
  1. 25 5
      h3d/impl/DirectXDriver.hx
  2. 1 1
      h3d/impl/Driver.hx
  3. 24 4
      h3d/impl/GlDriver.hx
  4. 3 2
      h3d/mat/Texture.hx

+ 25 - 5
h3d/impl/DirectXDriver.hx

@@ -501,13 +501,23 @@ class DirectXDriver extends h3d.impl.Driver {
 		tmp.release();
 	}
 
-	override function capturePixels(tex:h3d.mat.Texture, layer:Int, mipLevel:Int) : hxd.Pixels {
-		var pixels = hxd.Pixels.alloc(tex.width >> mipLevel, tex.height >> mipLevel, tex.format);
-		captureTexPixels(pixels, tex, layer, mipLevel);
+	override function capturePixels(tex:h3d.mat.Texture, layer:Int, mipLevel:Int, ?region:h2d.col.IBounds) : hxd.Pixels {
+		var pixels : hxd.Pixels;
+		if (region != null) {
+			if (region.xMax > tex.width) region.xMax = tex.width;
+			if (region.yMax > tex.height) region.yMax = tex.height;
+			if (region.xMin < 0) region.xMin = 0;
+			if (region.yMin < 0) region.yMin = 0;
+			pixels = hxd.Pixels.alloc(region.width >> mipLevel, region.height >> mipLevel, tex.format);
+			captureTexPixels(pixels, tex, layer, mipLevel, region.xMin, region.yMin);
+		} else {
+			pixels = hxd.Pixels.alloc(tex.width >> mipLevel, tex.height >> mipLevel, tex.format);
+			captureTexPixels(pixels, tex, layer, mipLevel);
+		}
 		return pixels;
 	}
 
-	function captureTexPixels( pixels: hxd.Pixels, tex:h3d.mat.Texture, layer:Int, mipLevel:Int)  {
+	function captureTexPixels( pixels: hxd.Pixels, tex:h3d.mat.Texture, layer:Int, mipLevel:Int, x : Int = 0, y : Int = 0)  {
 		var desc = new Texture2dDesc();
 		desc.width = pixels.width;
 		desc.height = pixels.height;
@@ -518,7 +528,17 @@ class DirectXDriver extends h3d.impl.Driver {
 		if( tmp == null )
 			throw "Capture failed: can't create tmp texture";
 
-		tmp.copySubresourceRegion(0,0,0,0,tex.t.res,tex.t.mips * layer + mipLevel, null);
+		if (x != 0 || y != 0) {
+			box.left = x;
+			box.right = x + desc.width;
+			box.top = y;
+			box.bottom = y + desc.height;
+			box.back = 1;
+			box.front = 0;
+			tmp.copySubresourceRegion(0,0,0,0,tex.t.res,tex.t.mips * layer + mipLevel, box);
+		} else {
+			tmp.copySubresourceRegion(0,0,0,0,tex.t.res,tex.t.mips * layer + mipLevel, null);
+		}
 
 		var pitch = 0;
 		var bpp = hxd.Pixels.getBytesPerPixel(tex.format);

+ 1 - 1
h3d/impl/Driver.hx

@@ -173,7 +173,7 @@ class Driver {
 	public function captureRenderBuffer( pixels : hxd.Pixels ) {
 	}
 
-	public function capturePixels( tex : h3d.mat.Texture, layer : Int, mipLevel : Int ) : hxd.Pixels {
+	public function capturePixels( tex : h3d.mat.Texture, layer : Int, mipLevel : Int, ?region : h2d.col.IBounds ) : hxd.Pixels {
 		throw "Can't capture pixels on this platform";
 		return null;
 	}

+ 24 - 4
h3d/impl/GlDriver.hx

@@ -1382,7 +1382,24 @@ class GlDriver extends Driver {
 		}
 	}
 
-	override function capturePixels(tex:h3d.mat.Texture, layer:Int, mipLevel:Int) {
+	override function capturePixels(tex:h3d.mat.Texture, layer:Int, mipLevel:Int, ?region:h2d.col.IBounds) {
+		
+		var pixels : hxd.Pixels;
+		var x : Int, y : Int;
+		if (region != null) {
+			if (region.xMax > tex.width) region.xMax = tex.width;
+			if (region.yMax > tex.height) region.yMax = tex.height;
+			if (region.xMin < 0) region.xMin = 0;
+			if (region.yMin < 0) region.yMin = 0;
+			pixels = hxd.Pixels.alloc(region.width >> mipLevel, region.height >> mipLevel, tex.format);
+			x = region.xMin;
+			y = region.yMin;
+		} else {
+			pixels = hxd.Pixels.alloc(tex.width >> mipLevel, tex.height >> mipLevel, tex.format);
+			x = 0;
+			y = 0;
+		}
+		
 		var old = curTarget;
 		var oldCount = numTargets;
 		var oldLayer = curTargetLayer;
@@ -1394,8 +1411,7 @@ class GlDriver extends Driver {
 					gl.framebufferTexture2D(GL.FRAMEBUFFER, GL.COLOR_ATTACHMENT0+i,GL.TEXTURE_2D,null,0);
 		}
 		setRenderTarget(tex, layer, mipLevel);
-		var pixels = hxd.Pixels.alloc(tex.width >> mipLevel, tex.height >> mipLevel, tex.format);
-		captureRenderBuffer(pixels);
+		captureSubRenderBuffer(pixels, x, y);
 		setRenderTarget(old, oldLayer, oldMip);
 		if( oldCount > 1 ) {
 			for( i in 1...oldCount )
@@ -1573,6 +1589,10 @@ class GlDriver extends Driver {
 	#end
 
 	override function captureRenderBuffer( pixels : hxd.Pixels ) {
+		captureSubRenderBuffer(pixels, 0, 0);
+	}
+
+	function captureSubRenderBuffer( pixels : hxd.Pixels, x : Int, y : Int ) {
 		if( curTarget == null )
 			throw "Can't capture main render buffer in GL";
 		discardError();
@@ -1588,7 +1608,7 @@ class GlDriver extends Driver {
 		var buffer = @:privateAccess pixels.bytes.b;
 		#end
 		#if (js || hl)
-		gl.readPixels(0, 0, pixels.width, pixels.height, getChannels(curTarget.t), curTarget.t.pixelFmt, buffer);
+		gl.readPixels(x, y, pixels.width, pixels.height, getChannels(curTarget.t), curTarget.t.pixelFmt, buffer);
 		var error = gl.getError();
 		if( error != 0 ) throw "Failed to capture pixels (error "+error+")";
 		@:privateAccess pixels.innerFormat = curTarget.format;

+ 3 - 2
h3d/mat/Texture.hx

@@ -300,15 +300,16 @@ class Texture {
 		Downloads the current texture data from the GPU.
 		Beware, this is a very slow operation that shouldn't be done during rendering.
 	**/
-	public function capturePixels( face = 0, mipLevel = 0 ) : hxd.Pixels {
+	public function capturePixels( face = 0, mipLevel = 0, ?region:h2d.col.IBounds ) : hxd.Pixels {
 		#if flash
 		if( flags.has(Cube) ) throw "Can't capture cube texture on this platform";
+		if( region != null ) throw "Can't capture texture region on this platform";
 		if( face != 0 || mipLevel != 0 ) throw "Can't capture face/mipLevel on this platform";
 		return capturePixelsFlash();
 		#else
 		var old = lastFrame;
 		preventAutoDispose();
-		var pix = mem.driver.capturePixels(this, face, mipLevel);
+		var pix = mem.driver.capturePixels(this, face, mipLevel, region);
 		lastFrame = old;
 		return pix;
 		#end