Browse Source

added support for 16 bit unorm textures and png 16 bits decoding

Nicolas Cannasse 2 years ago
parent
commit
6ddb623c85
6 changed files with 57 additions and 22 deletions
  1. 3 0
      h3d/impl/DX12Driver.hx
  2. 4 1
      h3d/impl/DirectXDriver.hx
  3. 26 6
      h3d/impl/GlDriver.hx
  4. 1 0
      hxd/PixelFormat.hx
  5. 2 2
      hxd/Pixels.hx
  6. 21 13
      hxd/res/Image.hx

+ 3 - 0
h3d/impl/DX12Driver.hx

@@ -1165,6 +1165,9 @@ class DX12Driver extends h3d.impl.Driver {
 		case RGB10A2: R10G10B10A2_UNORM;
 		case RG11B10UF: R11G11B10_FLOAT;
 		case SRGB_ALPHA: R8G8B8A8_UNORM_SRGB;
+		case R16U: R16_UNORM;
+		case RG16U: R16G16_UNORM;
+		case RGBA16U: R16G16B16A16_UNORM;
 		case S3TC(n):
 			switch( n ) {
 			case 1: BC1_UNORM;

+ 4 - 1
h3d/impl/DirectXDriver.hx

@@ -388,7 +388,7 @@ class DirectXDriver extends h3d.impl.Driver {
 
 	override function isSupportedFormat( fmt : hxd.PixelFormat ) {
 		return switch( fmt ) {
-		case RGB8, RGB16F, ARGB, BGRA, SRGB: false;
+		case RGB8, RGB16F, ARGB, BGRA, SRGB, RGB16U: false;
 		default: true;
 		}
 	}
@@ -408,6 +408,9 @@ class DirectXDriver extends h3d.impl.Driver {
 		case RGB10A2: R10G10B10A2_UNORM;
 		case RG11B10UF: R11G11B10_FLOAT;
 		case SRGB_ALPHA: R8G8B8A8_UNORM_SRGB;
+		case R16U: R16_UNORM;
+		case RG16U: R16G16_UNORM;
+		case RGBA16U: R16G16B16A16_UNORM;
 		case S3TC(n):
 			switch( n ) {
 			case 1: BC1_UNORM;

+ 26 - 6
h3d/impl/GlDriver.hx

@@ -809,10 +809,10 @@ class GlDriver extends Driver {
 		case GL.RGB: GL.RGB;
 		case GL.R11F_G11F_B10F: GL.RGB;
 		case GL.RGB10_A2: GL.RGBA;
-		case GL.RED, GL.R8, GL.R16F, GL.R32F: GL.RED;
-		case GL.RG, GL.RG8, GL.RG16F, GL.RG32F: GL.RG;
-		case GL.RGB16F, GL.RGB32F: GL.RGB;
-		case 0x83F1, 0x83F2, 0x83F3: GL.RGBA;
+		case GL.RED, GL.R8, GL.R16F, GL.R32F, 0x822A: GL.RED;
+		case GL.RG, GL.RG8, GL.RG16F, GL.RG32F, 0x822C: GL.RG;
+		case GL.RGB16F, GL.RGB32F, 0x8054: GL.RGB;
+		case 0x83F1, 0x83F2, 0x83F3, 0x805B: GL.RGBA;
 		default: throw "Invalid format " + t.internalFmt;
 		}
 	}
@@ -868,6 +868,18 @@ class GlDriver extends Driver {
 		case RG16F:
 			tt.internalFmt = GL.RG16F;
 			tt.pixelFmt = GL.HALF_FLOAT;
+		case R16U:
+			tt.internalFmt = 0x822A; // GL.R16
+			tt.pixelFmt = GL.UNSIGNED_SHORT;
+		case RG16U:
+			tt.internalFmt = 0x822C; // GL.RG16
+			tt.pixelFmt = GL.UNSIGNED_SHORT;
+		case RGB16U:
+			tt.internalFmt = 0x8054; // GL.RGB16
+			tt.pixelFmt = GL.UNSIGNED_SHORT;
+		case RGBA16U:
+			tt.internalFmt = 0x805B; // GL.RGBA16
+			tt.pixelFmt = GL.UNSIGNED_SHORT;
 		case R32F:
 			tt.internalFmt = GL.R32F;
 			tt.pixelFmt = GL.FLOAT;
@@ -898,6 +910,12 @@ class GlDriver extends Driver {
 		default:
 			throw "Unsupported texture format "+t.format;
 		}
+
+		#if js
+		if( tt.pixelFmt == GL.UNSIGNED_SHORT && !has16Bits )
+			throw "16 bit textures requires EXT_texture_norm16 extension";
+		#end
+
 		t.lastFrame = frame;
 		t.flags.unset(WasCleared);
 		gl.bindTexture(bind, tt.t);
@@ -1194,7 +1212,7 @@ class GlDriver extends Driver {
 		#end
 		var buffer : ArrayBufferView = switch( t.format ) {
 		case RGBA32F, R32F, RG32F, RGB32F: new Float32Array(@:privateAccess pixels.bytes.b.buffer, pixels.offset, dataLen>>2);
-		case RGBA16F, R16F, RG16F, RGB16F: new Uint16Array(@:privateAccess pixels.bytes.b.buffer, pixels.offset, dataLen>>1);
+		case RGBA16F, R16F, RG16F, RGB16F, RGBA16U, R16U, RG16U, RGB16U: new Uint16Array(@:privateAccess pixels.bytes.b.buffer, pixels.offset, dataLen>>1);
 		case RGB10A2, RG11B10UF: new Uint32Array(@:privateAccess pixels.bytes.b.buffer, pixels.offset, dataLen>>2);
 		default: new Uint8Array(@:privateAccess pixels.bytes.b.buffer, pixels.offset, dataLen);
 		}
@@ -1622,6 +1640,7 @@ class GlDriver extends Driver {
 
 	#if js
 	var features : Map<Feature,Bool> = new Map();
+	var has16Bits : Bool;
 	function makeFeatures() {
 		for( f in Type.allEnums(Feature) )
 			features.set(f,checkFeature(f));
@@ -1629,6 +1648,7 @@ class GlDriver extends Driver {
 			maxCompressedTexturesSupport = 3;
 		if( glES < 3 )
 			gl.getExtension("WEBGL_depth_texture");
+		has16Bits = gl.getExtension("EXT_texture_norm16") != null; // 16 bit textures
 	}
 	function checkFeature( f : Feature ) {
 		return switch( f ) {
@@ -1696,7 +1716,7 @@ class GlDriver extends Driver {
 		var buffer : ArrayBufferView = @:privateAccess pixels.bytes.b;
 		switch( curTarget.format ) {
 		case RGBA32F, R32F, RG32F, RGB32F: buffer = new Float32Array(buffer.buffer);
-		case RGBA16F, R16F, RG16F, RGB16F: buffer = new Uint16Array(buffer.buffer);
+		case RGBA16F, R16F, RG16F, RGB16F, RGBA16U, R16U, RG16U, RGB16U: buffer = new Uint16Array(buffer.buffer);
 		case RGB10A2, RG11B10UF: buffer = new Uint32Array(buffer.buffer);
 		default:
 		}

+ 1 - 0
hxd/PixelFormat.hx

@@ -20,6 +20,7 @@ enum PixelFormat {
 	RGB10A2;
 	RG11B10UF; // unsigned float
 	R16U;
+	RG16U;
 	RGB16U;
 	RGBA16U;
 	S3TC( v : Int );

+ 2 - 2
hxd/Pixels.hx

@@ -549,7 +549,7 @@ class Pixels {
 		case R16U, R16F: 2;
 		case R32F: 4;
 		case RG8: 2;
-		case RG16F: 4;
+		case RG16U, RG16F: 4;
 		case RG32F: 8;
 		case RGB8: 3;
 		case RGB16U, RGB16F: 6;
@@ -583,7 +583,7 @@ class Pixels {
 		return switch( format ) {
 		case R8, R16F, R32F, R16U:
 			if( channel == R ) 0 else -1;
-		case RG8, RG16F, RG32F:
+		case RG8, RG16F, RG16U, RG32F:
 			var p = calcStride(1,format);
 			[0, p, -1, -1][channel.toInt()];
 		case RGB8, RGB16F, RGB32F, RGB16U:

+ 21 - 13
hxd/res/Image.hx

@@ -124,12 +124,14 @@ class Image extends Resource {
 					inf.width = f.readInt32();
 					inf.height = f.readInt32();
 					var colbits = f.readByte();
-					inf.pixelFormat = switch( colbits ) {
-					case 8: BGRA;
-					case 16: R16U;
-					case 48: RGB16U;
-					case 64: RGBA16U;
-					default: throw "Unsupported png format "+colbits+"("+entry.path+")";
+					var colType = f.readByte();
+					inf.pixelFormat = switch( [colbits, colType] ) {
+					case [8,_]: BGRA; // TODO : grayscale png image
+					case [16,0]: R16U;
+					case [16,2]: RGBA16U; // RGB16U is not supported on DirectX !
+					case [16,4]: RG16U; // gray + alpha
+					case [16,6]: RGBA16U;
+					default: throw "Unsupported png format "+colbits+"/"+colType+"("+entry.path+")";
 					}
 					break;
 				}
@@ -296,14 +298,18 @@ class Image extends Resource {
 			pixels = decodePNG(bytes, inf.width, inf.height, fmt);
 			if( pixels == null ) throw "Failed to decode PNG " + entry.path;
 			#else
-			if( inf.pixelFormat != BGRA )
-				throw "No support to decode "+inf.pixelFormat+" on this platform ("+entry.path+")";
 			var png = new format.png.Reader(new haxe.io.BytesInput(bytes));
 			png.checkCRC = false;
-			// we only support BGRA decoding here
-			pixels = Pixels.alloc(inf.width, inf.height, BGRA);
+			pixels = Pixels.alloc(inf.width, inf.height, inf.pixelFormat);
 			var pdata = png.read();
-			format.png.Tools.extract32(pdata, pixels.bytes, false);
+			switch( inf.pixelFormat ) {
+			case BGRA:
+				format.png.Tools.extract32(pdata, pixels.bytes, false);
+			case R16U, RG16U, RGB16U, RGBA16U:
+				format.png.Tools.extract(pdata, pixels.bytes, inf.pixelFormat == RGBA16U && format.png.Tools.getHeader(pdata).color.match(ColTrue(false)));
+			default:
+				throw "No support to decode "+inf.pixelFormat+" on this platform ("+entry.path+")";
+			}
 			#end
 		case Gif:
 			var bytes = entry.getBytes();
@@ -436,6 +442,7 @@ class Image extends Resource {
 		case R16U: cast 12;
 		case RGB16U: cast 13;
 		case RGBA16U: cast 14;
+		case RG16U: cast 15;
 		default:
 			outFmt = BGRA;
 			BGRA;
@@ -446,6 +453,9 @@ class Image extends Resource {
 		case R16U:
 			stride = 1;
 			pxsize = 2;
+		case RG16U:
+			stride = 2;
+			pxsize = 4;
 		case RGB16U:
 			stride = 3;
 			pxsize = 6;
@@ -603,8 +613,6 @@ class Image extends Resource {
 			flags.push(MipMapped);
 			flags.push(ManualMipMapGen);
 		}
-		if( fmt == R16U )
-			throw "Unsupported texture format "+fmt+" for "+entry.path;
 		if( inf.layerCount > 1 )
 			tex = new h3d.mat.TextureArray(inf.width, inf.height, inf.layerCount, flags, fmt);
 		else