浏览代码

give access to hxd.Pixels.bytesPerPixel, fixed RGBA32F handling in GL/DX

Nicolas Cannasse 7 年之前
父节点
当前提交
3801755ecc
共有 6 个文件被更改,包括 45 次插入26 次删除
  1. 3 3
      h3d/impl/DirectXDriver.hx
  2. 6 2
      h3d/impl/GlDriver.hx
  3. 2 2
      h3d/mat/TextureChannels.hx
  4. 20 18
      hxd/Pixels.hx
  5. 1 1
      hxd/fmt/hsd/Serializer.hx
  6. 13 0
      samples/ShaderAdvanced.hx

+ 3 - 3
h3d/impl/DirectXDriver.hx

@@ -500,7 +500,7 @@ class DirectXDriver extends h3d.impl.Driver {
 		tmp.copySubresourceRegion(0,0,0,0,tex.t.res,tex.t.mips * layer + mipLevel, null);
 
 		var pitch = 0;
-		var bpp = hxd.Pixels.bytesPerPixel(tex.format);
+		var bpp = hxd.Pixels.getBytesPerPixel(tex.format);
 		var ptr = tmp.map(0, Read, true, pitch);
 		if( pitch == desc.width * bpp )
 			@:privateAccess pixels.bytes.b.blit(0, ptr, 0, desc.width * desc.height * bpp);
@@ -521,11 +521,11 @@ class DirectXDriver extends h3d.impl.Driver {
 	}
 
 	override function uploadTexturePixels(t:h3d.mat.Texture, pixels:hxd.Pixels, mipLevel:Int, side:Int) {
-		pixels.convert(RGBA);
+		pixels.convert(t.format);
 		pixels.setFlip(false);
 		if( hasDeviceError ) return;
 		if( mipLevel >= t.t.mips ) throw "Mip level outside texture range : " + mipLevel + " (max = " + (t.t.mips - 1) + ")";
-		t.t.res.updateSubresource(mipLevel + side * t.t.mips, null, (pixels.bytes:hl.Bytes).offset(pixels.offset), pixels.width * hxd.Pixels.bytesPerPixel(pixels.format), 0);
+		t.t.res.updateSubresource(mipLevel + side * t.t.mips, null, (pixels.bytes:hl.Bytes).offset(pixels.offset), pixels.width * pixels.bytesPerPixel, 0);
 		updateResCount++;
 	}
 

+ 6 - 2
h3d/impl/GlDriver.hx

@@ -1008,11 +1008,15 @@ class GlDriver extends Driver {
 		pixels.convert(t.format);
 		pixels.setFlip(false);
 		#if hl
-		gl.texImage2D(face, mipLevel, t.t.internalFmt, pixels.width, pixels.height, 0, getChannels(t.t), t.t.pixelFmt, streamData(pixels.bytes.getData(),pixels.offset,pixels.width*pixels.height*4));
+		gl.texImage2D(face, mipLevel, t.t.internalFmt, pixels.width, pixels.height, 0, getChannels(t.t), t.t.pixelFmt, streamData(pixels.bytes.getData(),pixels.offset,pixels.width*pixels.height*pixels.bytesPerPixel));
 		#elseif lime
 		gl.texImage2D(face, mipLevel, t.t.internalFmt, pixels.width, pixels.height, 0, getChannels(t.t), t.t.pixelFmt, bytesToUint8Array(pixels.bytes));
 		#else
-		gl.texImage2D(face, mipLevel, t.t.internalFmt, pixels.width, pixels.height, 0, getChannels(t.t), t.t.pixelFmt, bytesToUint8Array(pixels.bytes));
+		var buffer = switch( t.format ) {
+		case RGBA32F: new Float32Array(pixels.bytes.getData());
+		default: bytesToUint8Array(pixels.bytes);
+		}
+		gl.texImage2D(face, mipLevel, t.t.internalFmt, pixels.width, pixels.height, 0, getChannels(t.t), t.t.pixelFmt, buffer);
 		#end
 		restoreBind();
 	}

+ 2 - 2
h3d/mat/TextureChannels.hx

@@ -33,9 +33,9 @@ class TextureChannels extends Texture {
 	function setPixelsInner( c : hxd.Pixels.Channel, src : hxd.Pixels, srcChannel : hxd.Pixels.Channel ) {
 		if( src.width != width || src.height != height )
 			throw "Size mismatch : " + src.width + "x" + src.height + " should be " + width + "x" + height;
-		var bpp = hxd.Pixels.bytesPerPixel(pixels.format);
+		var bpp = pixels.bytesPerPixel;
 		var off = hxd.Pixels.getChannelOffset(pixels.format, c);
-		var srcBpp = hxd.Pixels.bytesPerPixel(src.format);
+		var srcBpp = src.bytesPerPixel;
 		var srcOff = hxd.Pixels.getChannelOffset(src.format, srcChannel);
 		for( y in 0...height ) {
 			var r = (y * src.width * srcBpp) + srcOff;

+ 20 - 18
hxd/Pixels.hx

@@ -43,7 +43,7 @@ abstract PixelsFloat(Pixels) to Pixels {
 	}
 
 	@:from public static function fromPixels(p:Pixels) : PixelsFloat {
-		p.convert(RGBA16F);
+		p.convert(RGBA32F);
 		p.setFlip(false);
 		return cast p;
 	}
@@ -66,7 +66,7 @@ class Pixels {
 	public var height : Int;
 	public var offset : Int;
 	public var flags: haxe.EnumFlags<Flags>;
-	var bpp : Int;
+	public var bytesPerPixel(default,null) : Int;
 	var innerFormat(default, set) : PixelFormat;
 
 	public function new(width : Int, height : Int, bytes : haxe.io.Bytes, format : hxd.PixelFormat, offset = 0) {
@@ -89,7 +89,7 @@ class Pixels {
 
 	function set_innerFormat(fmt) {
 		this.innerFormat = fmt;
-		bpp = bytesPerPixel(fmt);
+		bytesPerPixel = getBytesPerPixel(fmt);
 		return fmt;
 	}
 
@@ -100,11 +100,11 @@ class Pixels {
 	public function sub( x : Int, y : Int, width : Int, height : Int ) {
 		if( x < 0 || y < 0 || x + width > this.width || y + height > this.height )
 			throw "Pixels.sub() outside bounds";
-		var out = haxe.io.Bytes.alloc(width * height * bpp);
-		var stride = width * bpp;
+		var out = haxe.io.Bytes.alloc(width * height * bytesPerPixel);
+		var stride = width * bytesPerPixel;
 		var outP = 0;
 		for( dy in 0...height ) {
-			var p = (x + yflip(y + dy) * this.width) * bpp + offset;
+			var p = (x + yflip(y + dy) * this.width) * bytesPerPixel + offset;
 			out.blit(outP, this.bytes, p, stride);
 			outP += stride;
 		}
@@ -122,6 +122,7 @@ class Pixels {
 			throw "Pixels.blit() outside src bounds";
 		willChange();
 		src.convert(format);
+		var bpp = bytesPerPixel;
 		var stride = width * bpp;
 		for( dy in 0...height ) {
 			var srcP = (srcX + src.yflip(dy + srcY) * src.width) * bpp + src.offset;
@@ -134,7 +135,7 @@ class Pixels {
 		var mask = preserveMask;
 		willChange();
 		if( color == 0 && mask == 0 ) {
-			bytes.fill(offset, width * height * bpp, 0);
+			bytes.fill(offset, width * height * bytesPerPixel, 0);
 			return;
 		}
 		switch( format ) {
@@ -168,8 +169,8 @@ class Pixels {
 		var p = offset;
 		var dl = 0;
 		if( flags.has(FlipY) ) {
-			p += ((height - 1) * width) * bpp;
-			dl = -width * 2 * bpp;
+			p += ((height - 1) * width) * bytesPerPixel;
+			dl = -width * 2 * bytesPerPixel;
 		}
 		switch(format) {
 		case BGRA:
@@ -210,6 +211,7 @@ class Pixels {
 		while( tw < w ) tw <<= 1;
 		while( th < h ) th <<= 1;
 		if( w == tw && h == th ) return this;
+		var bpp = bytesPerPixel;
 		var out = haxe.io.Bytes.alloc(tw * th * bpp);
 		var p = 0, b = offset;
 		for( y in 0...h ) {
@@ -235,8 +237,8 @@ class Pixels {
 
 	function copyInner() {
 		var old = bytes;
-		bytes = haxe.io.Bytes.alloc(width * height * bpp);
-		bytes.blit(0, old, offset, width * height * bpp);
+		bytes = haxe.io.Bytes.alloc(width * height * bytesPerPixel);
+		bytes.blit(0, old, offset, width * height * bytesPerPixel);
 		offset = 0;
 		flags.unset(ReadOnly);
 	}
@@ -248,10 +250,10 @@ class Pixels {
 	public function setFlip( b : Bool ) {
 		#if js if( b == null ) b = false; #end
 		if( flags.has(FlipY) == b ) return;
-		if( this.bpp != 4 ) throw "TODO";
 		willChange();
 		if( b ) flags.set(FlipY) else flags.unset(FlipY);
-		var stride = width * bpp;
+		var stride = width * bytesPerPixel;
+		if( stride%4 != 0 ) invalidFormat();
 		for( y in 0...height >> 1 ) {
 			var p1 = y * stride + offset;
 			var p2 = (height - 1 - y) * stride + offset;
@@ -322,7 +324,7 @@ class Pixels {
 	}
 
 	public function getPixel(x, y) : Int {
-		var p = ((x + yflip(y) * width) * bpp) + offset;
+		var p = ((x + yflip(y) * width) * bytesPerPixel) + offset;
 		switch(format) {
 		case BGRA:
 			return bytes.getInt32(p);
@@ -337,7 +339,7 @@ class Pixels {
 	}
 
 	public function setPixel(x, y, color) : Void {
-		var p = ((x + yflip(y) * width) * bpp) + offset;
+		var p = ((x + yflip(y) * width) * bytesPerPixel) + offset;
 		willChange();
 		switch(format) {
 		case BGRA:
@@ -375,14 +377,14 @@ class Pixels {
 		p.flags = flags;
 		p.flags.unset(ReadOnly);
 		if( bytes != null ) {
-			var size = width * height * bpp;
+			var size = width * height * bytesPerPixel;
 			p.bytes = haxe.io.Bytes.alloc(size);
 			p.bytes.blit(0, bytes, offset, size);
 		}
 		return p;
 	}
 
-	public static function bytesPerPixel( format : PixelFormat ) {
+	public static function getBytesPerPixel( format : PixelFormat ) {
 		return switch( format ) {
 		case ALPHA8: 1;
 		case ARGB, BGRA, RGBA, SRGB, SRGB_ALPHA: 4;
@@ -415,7 +417,7 @@ class Pixels {
 	}
 
 	public static function alloc( width, height, format : PixelFormat ) {
-		return new Pixels(width, height, haxe.io.Bytes.alloc(width * height * bytesPerPixel(format)), format);
+		return new Pixels(width, height, haxe.io.Bytes.alloc(width * height * getBytesPerPixel(format)), format);
 	}
 
 }

+ 1 - 1
hxd/fmt/hsd/Serializer.hx

@@ -41,7 +41,7 @@ class Serializer extends hxbit.Serializer {
 			for( face in 0...(t.flags.has(Cube) ? 6 : 1) ) {
 				var pix = t.capturePixels(face);
 				pix.convert(fmt);
-				addBytesSub(pix.bytes, 0, t.width * t.height * hxd.Pixels.bytesPerPixel(pix.format));
+				addBytesSub(pix.bytes, 0, t.width * t.height * pix.bytesPerPixel);
 			}
 			return true;
 		}

+ 13 - 0
samples/ShaderAdvanced.hx

@@ -66,6 +66,19 @@ class ShaderAdvanced extends hxd.App {
 		tarr.textures.clear(0xFF4040,1,0);
 		tarr.textures.clear(0x40FF40,1,1);
 		tarr.textures.clear(0x4040FF,1,2);
+
+		// rgba 32F read/write
+		var tex = new h3d.mat.Texture(1,1,[Target],RGBA32F);
+		tex.clear(0x804020,1);
+		var pixels : hxd.Pixels.PixelsFloat = tex.capturePixels();
+		var color = pixels.getPixelF(0,0).toColor();
+		if( color != 0xFF804020 ) throw StringTools.hex(color);
+		pixels.setPixelF(0,0,new h3d.Vector(1,2,3,4));
+		tex.uploadPixels(pixels);
+		pixels = tex.capturePixels();
+		var v = pixels.getPixelF(0,0);
+		if( v.r != 1 || v.g != 2 || v.b != 3 || v.a != 4 ) throw v.toString();
+
 	}
 
 	override function update(dt:Float) {