diff --git a/Backends/HTML5-Worker/kha/Image.hx b/Backends/HTML5-Worker/kha/Image.hx index bc055620b..257fb7214 100644 --- a/Backends/HTML5-Worker/kha/Image.hx +++ b/Backends/HTML5-Worker/kha/Image.hx @@ -109,6 +109,8 @@ class Image implements Canvas implements Resource { bytes = Bytes.alloc(2 * width * height); case RGBA64: bytes = Bytes.alloc(8 * width * height); + case RGBA64U: + bytes = Bytes.alloc(8 * width * height); case A32: bytes = Bytes.alloc(4 * width * height); case A16: @@ -177,6 +179,7 @@ class Image implements Canvas implements Resource { case RGBA128: 16; case DEPTH16: 2; case RGBA64: 8; + case RGBA64U: 8; case A32: 4; case A16: 2; default: 4; diff --git a/Backends/HTML5/kha/SystemImpl.hx b/Backends/HTML5/kha/SystemImpl.hx index f9960ea42..316925d83 100644 --- a/Backends/HTML5/kha/SystemImpl.hx +++ b/Backends/HTML5/kha/SystemImpl.hx @@ -393,7 +393,6 @@ class SystemImpl { antialias: options.framebuffer.samplesPerPixel > 1, stencil: true }); // preserveDrawingBuffer: true } ); Warning: preserveDrawingBuffer can cause huge performance issues on mobile browsers - SystemImpl.gl.pixelStorei(GL.UNPACK_PREMULTIPLY_ALPHA_WEBGL, 1); halfFloat = {HALF_FLOAT_OES: 0x140B}; // GL_HALF_FLOAT depthTexture = {UNSIGNED_INT_24_8_WEBGL: 0x84FA}; // GL_UNSIGNED_INT_24_8 @@ -422,7 +421,6 @@ class SystemImpl { antialias: options.framebuffer.samplesPerPixel > 1, stencil: true }); // preserveDrawingBuffer: true } ); WARNING: preserveDrawingBuffer causes huge performance issues (on mobile browser)! - SystemImpl.gl.pixelStorei(GL.UNPACK_PREMULTIPLY_ALPHA_WEBGL, 1); SystemImpl.gl.getExtension("OES_texture_float"); SystemImpl.gl.getExtension("OES_texture_float_linear"); halfFloat = SystemImpl.gl.getExtension("OES_texture_half_float"); diff --git a/Backends/HTML5/kha/WebGLImage.hx b/Backends/HTML5/kha/WebGLImage.hx index 9164a3ccc..3585d8f57 100644 --- a/Backends/HTML5/kha/WebGLImage.hx +++ b/Backends/HTML5/kha/WebGLImage.hx @@ -51,6 +51,8 @@ class WebGLImage extends Image { static inline var GL_R16F = 0x822D; static inline var GL_R32F = 0x822E; static inline var GL_RED = 0x1903; + static inline var GL_RGBA16UI = 0x8D76; + static inline var GL_RGBA_INTEGER = 0x8D99; static inline var GL_DEPTH_COMPONENT24 = 0x81A6; static inline var GL_DEPTH24_STENCIL8 = 0x88F0; static inline var GL_DEPTH32F_STENCIL8 = 0x8CAD; @@ -209,8 +211,11 @@ class WebGLImage extends Image { SystemImpl.gl.bindTexture(GL.TEXTURE_2D, texture); // Sys.gl.pixelStorei(Sys.gl.UNPACK_FLIP_Y_WEBGL, true); - SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MAG_FILTER, GL.LINEAR); - SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MIN_FILTER, GL.LINEAR); + // Integer-format textures cannot use linear filtering in webgl2 + final isIntegerFormat = myFormat == RGBA64U; + final filter = isIntegerFormat ? GL.NEAREST : GL.LINEAR; + SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MAG_FILTER, filter); + SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MIN_FILTER, filter); SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_WRAP_S, GL.CLAMP_TO_EDGE); SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_WRAP_T, GL.CLAMP_TO_EDGE); if (renderTarget) { @@ -227,6 +232,8 @@ class WebGLImage extends Image { SystemImpl.halfFloat.HALF_FLOAT_OES, null); case RGBA32: SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, GL.RGBA, realWidth, realHeight, 0, GL.RGBA, GL.UNSIGNED_BYTE, null); + case RGBA64U: + SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, GL_RGBA16UI, realWidth, realHeight, 0, GL_RGBA_INTEGER, GL.UNSIGNED_SHORT, null); case A32: SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, SystemImpl.gl2 ? GL_R32F : GL.ALPHA, realWidth, realHeight, 0, SystemImpl.gl2 ? GL_RED : GL.ALPHA, GL.FLOAT, null); @@ -288,7 +295,10 @@ class WebGLImage extends Image { SystemImpl.gl.bindFramebuffer(GL.FRAMEBUFFER, null); } else if (video != null) { + // premultiply alpha for dom videos + SystemImpl.gl.pixelStorei(GL.UNPACK_PREMULTIPLY_ALPHA_WEBGL, 1); SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, GL.RGBA, GL.RGBA, GL.UNSIGNED_BYTE, video); + SystemImpl.gl.pixelStorei(GL.UNPACK_PREMULTIPLY_ALPHA_WEBGL, 0); } else { switch (myFormat) { @@ -302,8 +312,13 @@ class WebGLImage extends Image { SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, GL.RGBA, myWidth, myHeight, 0, GL.RGBA, GL.UNSIGNED_BYTE, image); } else { + // premultiply alpha for dom images + SystemImpl.gl.pixelStorei(GL.UNPACK_PREMULTIPLY_ALPHA_WEBGL, 1); SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, GL.RGBA, GL.RGBA, GL.UNSIGNED_BYTE, image); + SystemImpl.gl.pixelStorei(GL.UNPACK_PREMULTIPLY_ALPHA_WEBGL, 0); } + case RGBA64U: + SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, GL_RGBA16UI, myWidth, myHeight, 0, GL_RGBA_INTEGER, GL.UNSIGNED_SHORT, image); case A32: SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, SystemImpl.gl2 ? GL_R32F : GL.ALPHA, myWidth, myHeight, 0, SystemImpl.gl2 ? GL_RED : GL.ALPHA, GL.FLOAT, image); @@ -313,7 +328,10 @@ class WebGLImage extends Image { case L8: SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, GL.LUMINANCE, myWidth, myHeight, 0, GL.LUMINANCE, GL.UNSIGNED_BYTE, image); default: + // premultiply alpha for dom images + SystemImpl.gl.pixelStorei(GL.UNPACK_PREMULTIPLY_ALPHA_WEBGL, 1); SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, GL.RGBA, GL.RGBA, GL.UNSIGNED_BYTE, image); + SystemImpl.gl.pixelStorei(GL.UNPACK_PREMULTIPLY_ALPHA_WEBGL, 0); } } SystemImpl.gl.bindTexture(GL.TEXTURE_2D, null); @@ -419,6 +437,7 @@ class WebGLImage extends Image { case RGBA128: 16; case DEPTH16: 2; case RGBA64: 8; + case RGBA64U: 8; case A32: 4; case A16: 2; default: 4; @@ -429,6 +448,8 @@ class WebGLImage extends Image { return switch (myFormat) { case RGBA32, L8: new Uint8Array(bytes.getData()); + case RGBA64U: + new Uint16Array(bytes.getData()); case RGBA128, RGBA64, A32, A16: new Float32Array(bytes.getData()); default: @@ -453,8 +474,10 @@ class WebGLImage extends Image { SystemImpl.gl.bindTexture(GL.TEXTURE_2D, texture); // Sys.gl.pixelStorei(Sys.gl.UNPACK_FLIP_Y_WEBGL, true); - SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MAG_FILTER, GL.LINEAR); - SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MIN_FILTER, GL.LINEAR); + final isIntegerFormat = myFormat == RGBA64U; + final filter = isIntegerFormat ? GL.NEAREST : GL.LINEAR; + SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MAG_FILTER, filter); + SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MIN_FILTER, filter); SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_WRAP_S, GL.CLAMP_TO_EDGE); SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_WRAP_T, GL.CLAMP_TO_EDGE); @@ -475,8 +498,7 @@ class WebGLImage extends Image { SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, GL.RGBA, width, height, 0, GL.RGBA, GL.UNSIGNED_BYTE, bytesToArray(rgbaBytes)); } case RGBA128: - SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, SystemImpl.gl2 ? GL_RGBA32F : GL.RGBA, width, height, 0, GL.RGBA, GL.FLOAT, - bytesToArray(bytes)); + SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, SystemImpl.gl2 ? GL_RGBA32F : GL.RGBA, width, height, 0, GL.RGBA, GL.FLOAT, bytesToArray(bytes)); case RGBA64: SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, SystemImpl.gl2 ? GL_RGBA16F : GL.RGBA, width, height, 0, GL.RGBA, SystemImpl.halfFloat.HALF_FLOAT_OES, bytesToArray(bytes)); @@ -488,6 +510,10 @@ class WebGLImage extends Image { SystemImpl.halfFloat.HALF_FLOAT_OES, bytesToArray(bytes)); case RGBA32: SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, GL.RGBA, width, height, 0, GL.RGBA, GL.UNSIGNED_BYTE, bytesToArray(bytes)); + case RGBA64U: + SystemImpl.gl.pixelStorei(GL.UNPACK_ALIGNMENT, 2); + SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, GL_RGBA16UI, width, height, 0, GL_RGBA_INTEGER, GL.UNSIGNED_SHORT, bytesToArray(bytes)); + SystemImpl.gl.pixelStorei(GL.UNPACK_ALIGNMENT, 4); default: SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, GL.RGBA, width, height, 0, GL.RGBA, GL.UNSIGNED_BYTE, bytesToArray(bytes)); } @@ -509,7 +535,7 @@ class WebGLImage extends Image { switch (myFormat) { case RGBA128, A32: pixels = new Float32Array(Std.int(formatByteSize(myFormat) / 4) * width * height); - case RGBA64, A16: + case RGBA64, A16, RGBA64U: pixels = new Uint16Array(Std.int(formatByteSize(myFormat) / 2) * width * height); case RGBA32, L8: pixels = new Uint8Array(formatByteSize(myFormat) * width * height); @@ -525,6 +551,8 @@ class WebGLImage extends Image { SystemImpl.gl.readPixels(0, 0, myWidth, myHeight, GL.RGBA, SystemImpl.halfFloat.HALF_FLOAT_OES, pixels); case RGBA32: SystemImpl.gl.readPixels(0, 0, myWidth, myHeight, GL.RGBA, GL.UNSIGNED_BYTE, pixels); + case RGBA64U: + SystemImpl.gl.readPixels(0, 0, myWidth, myHeight, GL_RGBA_INTEGER, GL.UNSIGNED_SHORT, pixels); case A32: SystemImpl.gl.readPixels(0, 0, myWidth, myHeight, SystemImpl.gl2 ? GL_RED : GL.ALPHA, GL.FLOAT, pixels); case A16: @@ -575,6 +603,14 @@ class WebGLImage extends Image { SystemImpl.halfFloat.HALF_FLOAT_OES, cast(mipmaps[i], WebGLImage).image); } } + else if (myFormat == TextureFormat.RGBA64U) { + SystemImpl.gl.pixelStorei(GL.UNPACK_ALIGNMENT, 2); + for (i in 0...mipmaps.length) { + SystemImpl.gl.texImage2D(GL.TEXTURE_2D, i + 1, GL_RGBA16UI, mipmaps[i].width, mipmaps[i].height, 0, GL_RGBA_INTEGER, GL.UNSIGNED_SHORT, + cast(mipmaps[i], WebGLImage).image); + } + SystemImpl.gl.pixelStorei(GL.UNPACK_ALIGNMENT, 4); + } else { for (i in 0...mipmaps.length) { SystemImpl.gl.texImage2D(GL.TEXTURE_2D, i + 1, GL.RGBA, GL.RGBA, GL.UNSIGNED_BYTE, cast(mipmaps[i], WebGLImage).image); diff --git a/Backends/Kore-HL/kha/Image.hx b/Backends/Kore-HL/kha/Image.hx index 4168f8f6c..1fd3a6f99 100644 --- a/Backends/Kore-HL/kha/Image.hx +++ b/Backends/Kore-HL/kha/Image.hx @@ -103,6 +103,8 @@ class Image implements Canvas implements Resource { return 5; case A16: // Target16BitRedFloat return 6; + case RGBA64U: // Target64BitInteger + return 7; default: return 0; } @@ -142,6 +144,8 @@ class Image implements Canvas implements Resource { return 5; case A16: return 7; + case RGBA64U: + return 8; default: return 1; // Grey8 } @@ -154,7 +158,7 @@ class Image implements Canvas implements Resource { if (renderTarget) image.initRenderTarget(width, height, getDepthBufferBits(depthStencil), getRenderTargetFormat(format), getStencilBufferBits(depthStencil)); else - image.init(width, height, format); + image.init(width, height, getTextureFormat(format)); return image; } @@ -334,6 +338,7 @@ class Image implements Canvas implements Resource { case RGBA128: 16; case DEPTH16: 2; case RGBA64: 8; + case RGBA64U: 8; case A32: 4; case A16: 2; default: 4; diff --git a/Backends/Kore-HL/kha/graphics4/CubeMap.hx b/Backends/Kore-HL/kha/graphics4/CubeMap.hx index e038d86e4..03bb7c3f1 100644 --- a/Backends/Kore-HL/kha/graphics4/CubeMap.hx +++ b/Backends/Kore-HL/kha/graphics4/CubeMap.hx @@ -38,6 +38,8 @@ class CubeMap implements Canvas implements Resource { return 3; case DEPTH16: // Target16BitDepth return 4; + case RGBA64U: // Target64BitInteger + return 7; default: return 0; } @@ -75,6 +77,8 @@ class CubeMap implements Canvas implements Resource { return 4; case A32: return 5; + case RGBA64U: + return 8; default: return 1; // Grey 8 } diff --git a/Backends/Kore-hxcpp/kha/Image.hx b/Backends/Kore-hxcpp/kha/Image.hx index 24eab5843..70717d787 100644 --- a/Backends/Kore-hxcpp/kha/Image.hx +++ b/Backends/Kore-hxcpp/kha/Image.hx @@ -195,6 +195,8 @@ class Image implements Canvas implements Resource { return 5; // Target8BitRed case A16: return 6; // Target16BitRedFloat + case RGBA64U: + return 7; // Target64BitInteger default: return 0; } @@ -234,6 +236,8 @@ class Image implements Canvas implements Resource { return 5; case A16: return 7; + case RGBA64U: + return 8; default: return 1; // Grey8 } @@ -519,6 +523,7 @@ class Image implements Canvas implements Resource { case RGBA128: 16; case DEPTH16: 2; case RGBA64: 8; + case RGBA64U: 8; case A32: 4; case A16: 2; default: 4; diff --git a/Backends/Kore-hxcpp/kha/graphics4/CubeMap.hx b/Backends/Kore-hxcpp/kha/graphics4/CubeMap.hx index 46e8b5aa7..f678e5851 100644 --- a/Backends/Kore-hxcpp/kha/graphics4/CubeMap.hx +++ b/Backends/Kore-hxcpp/kha/graphics4/CubeMap.hx @@ -37,6 +37,8 @@ class CubeMap implements Canvas implements Resource { return 3; case DEPTH16: // Target16BitDepth return 4; + case RGBA64U: // Target64BitInteger + return 7; default: return 0; } @@ -74,6 +76,8 @@ class CubeMap implements Canvas implements Resource { return 4; case A32: return 5; + case RGBA64U: + return 8; default: return 1; // Grey 8 } diff --git a/Backends/Krom/kha/Image.hx b/Backends/Krom/kha/Image.hx index 1139799b2..b20af7727 100644 --- a/Backends/Krom/kha/Image.hx +++ b/Backends/Krom/kha/Image.hx @@ -36,6 +36,8 @@ class Image implements Canvas implements Resource { return 5; // Target8BitRed case A16: return 6; // Target16BitRedFloat + case RGBA64U: + return 7; // Target64BitInteger default: return 0; } @@ -75,6 +77,8 @@ class Image implements Canvas implements Resource { return 5; case A16: return 7; + case RGBA64U: + return 8; default: return 1; // Grey8 } @@ -198,6 +202,7 @@ class Image implements Canvas implements Resource { case RGBA128: 16; case DEPTH16: 2; case RGBA64: 8; + case RGBA64U: 8; case A32: 4; case A16: 2; default: 4; diff --git a/Backends/Krom/kha/graphics4/CubeMap.hx b/Backends/Krom/kha/graphics4/CubeMap.hx index 5d0631308..fba47e035 100644 --- a/Backends/Krom/kha/graphics4/CubeMap.hx +++ b/Backends/Krom/kha/graphics4/CubeMap.hx @@ -24,6 +24,8 @@ class CubeMap implements Canvas implements Resource { return 3; case DEPTH16: // Target16BitDepth return 4; + case RGBA64U: // Target64BitInteger + return 7; default: return 0; } @@ -61,6 +63,8 @@ class CubeMap implements Canvas implements Resource { return 4; case A32: return 5; + case RGBA64U: + return 8; default: return 1; // Grey8 } diff --git a/Sources/kha/graphics4/TextureFormat.hx b/Sources/kha/graphics4/TextureFormat.hx index ce2db7479..97ab374f9 100644 --- a/Sources/kha/graphics4/TextureFormat.hx +++ b/Sources/kha/graphics4/TextureFormat.hx @@ -8,4 +8,5 @@ enum abstract TextureFormat(Int) to Int { var RGBA64 = 4; // Half floats var A32 = 5; // Float var A16 = 6; // Half float + var RGBA64U = 7; // 16-bit uint }