diff --git a/src/textures.js b/src/textures.js index 145940a1..f8ecb891 100644 --- a/src/textures.js +++ b/src/textures.js @@ -400,71 +400,71 @@ function getTextureInternalFormatInfo(internalFormat) { const t = {}; // compressed texture formats // s3tc:https://registry.khronos.org/OpenGL/extensions/EXT/EXT_texture_compression_s3tc.txt - t[COMPRESSED_RGB_S3TC_DXT1_EXT] = { textureFormat: COMPRESSED_RGB_S3TC_DXT1_EXT, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_RGBA_S3TC_DXT1_EXT] = { textureFormat: COMPRESSED_RGBA_S3TC_DXT1_EXT, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_RGBA_S3TC_DXT3_EXT] = { textureFormat: COMPRESSED_RGBA_S3TC_DXT3_EXT, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_RGBA_S3TC_DXT5_EXT] = { textureFormat: COMPRESSED_RGBA_S3TC_DXT5_EXT, colorRenderable: false, textureFilterable: true }; + t[COMPRESSED_RGB_S3TC_DXT1_EXT] = { textureFormat: COMPRESSED_RGB_S3TC_DXT1_EXT, colorRenderable: false, textureFilterable: true, bytesPerTexel: 0.5 }; + t[COMPRESSED_RGBA_S3TC_DXT1_EXT] = { textureFormat: COMPRESSED_RGBA_S3TC_DXT1_EXT, colorRenderable: false, textureFilterable: true, bytesPerTexel: 0.5 }; + t[COMPRESSED_RGBA_S3TC_DXT3_EXT] = { textureFormat: COMPRESSED_RGBA_S3TC_DXT3_EXT, colorRenderable: false, textureFilterable: true, bytesPerTexel: 1 }; + t[COMPRESSED_RGBA_S3TC_DXT5_EXT] = { textureFormat: COMPRESSED_RGBA_S3TC_DXT5_EXT, colorRenderable: false, textureFilterable: true, bytesPerTexel: 1 }; // https://registry.khronos.org/OpenGL/extensions/EXT/EXT_texture_compression_s3tc_srgb.txt - t[COMPRESSED_SRGB_S3TC_DXT1_EXT] = { textureFormat: COMPRESSED_SRGB_S3TC_DXT1_EXT, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT] = { textureFormat: COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT] = { textureFormat: COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT] = { textureFormat: COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, colorRenderable: false, textureFilterable: true }; + t[COMPRESSED_SRGB_S3TC_DXT1_EXT] = { textureFormat: COMPRESSED_SRGB_S3TC_DXT1_EXT, colorRenderable: false, textureFilterable: true, bytesPerTexel: 0.5 }; + t[COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT] = { textureFormat: COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, colorRenderable: false, textureFilterable: true, bytesPerTexel: 0.5 }; + t[COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT] = { textureFormat: COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, colorRenderable: false, textureFilterable: true, bytesPerTexel: 1 }; + t[COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT] = { textureFormat: COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, colorRenderable: false, textureFilterable: true, bytesPerTexel: 1 }; // https://registry.khronos.org/OpenGL/extensions/OES/OES_compressed_ETC1_RGB8_texture.txt - t[COMPRESSED_RGB_ETC1_WEBGL] = { textureFormat: COMPRESSED_RGB_ETC1_WEBGL, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_R11_EAC] = { textureFormat: COMPRESSED_R11_EAC, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_SIGNED_R11_EAC] = { textureFormat: COMPRESSED_SIGNED_R11_EAC, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_RG11_EAC] = { textureFormat: COMPRESSED_RG11_EAC, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_SIGNED_RG11_EAC] = { textureFormat: COMPRESSED_SIGNED_RG11_EAC, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_RGB8_ETC2] = { textureFormat: COMPRESSED_RGB8_ETC2, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_SRGB8_ETC2] = { textureFormat: COMPRESSED_SRGB8_ETC2, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2] = { textureFormat: COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2] = { textureFormat: COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_RGBA8_ETC2_EAC] = { textureFormat: COMPRESSED_RGBA8_ETC2_EAC, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_SRGB8_ALPHA8_ETC2_EAC] = { textureFormat: COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, colorRenderable: false, textureFilterable: true }; + t[COMPRESSED_RGB_ETC1_WEBGL] = { textureFormat: COMPRESSED_RGB_ETC1_WEBGL, colorRenderable: false, textureFilterable: true, bytesPerTexel: 0.5 }; + t[COMPRESSED_R11_EAC] = { textureFormat: COMPRESSED_R11_EAC, colorRenderable: false, textureFilterable: true, bytesPerTexel: 0.5 }; + t[COMPRESSED_SIGNED_R11_EAC] = { textureFormat: COMPRESSED_SIGNED_R11_EAC, colorRenderable: false, textureFilterable: true, bytesPerTexel: 0.5 }; + t[COMPRESSED_RG11_EAC] = { textureFormat: COMPRESSED_RG11_EAC, colorRenderable: false, textureFilterable: true, bytesPerTexel: 1 }; + t[COMPRESSED_SIGNED_RG11_EAC] = { textureFormat: COMPRESSED_SIGNED_RG11_EAC, colorRenderable: false, textureFilterable: true, bytesPerTexel: 1 }; + t[COMPRESSED_RGB8_ETC2] = { textureFormat: COMPRESSED_RGB8_ETC2, colorRenderable: false, textureFilterable: true, bytesPerTexel: 0.5 }; + t[COMPRESSED_SRGB8_ETC2] = { textureFormat: COMPRESSED_SRGB8_ETC2, colorRenderable: false, textureFilterable: true, bytesPerTexel: 0.5 }; + t[COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2] = { textureFormat: COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, colorRenderable: false, textureFilterable: true, bytesPerTexel: 0.5 }; + t[COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2] = { textureFormat: COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, colorRenderable: false, textureFilterable: true, bytesPerTexel: 0.5 }; + t[COMPRESSED_RGBA8_ETC2_EAC] = { textureFormat: COMPRESSED_RGBA8_ETC2_EAC, colorRenderable: false, textureFilterable: true, bytesPerTexel: 1 }; + t[COMPRESSED_SRGB8_ALPHA8_ETC2_EAC] = { textureFormat: COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, colorRenderable: false, textureFilterable: true, bytesPerTexel: 1 }; // https://registry.khronos.org/OpenGL/extensions/IMG/IMG_texture_compression_pvrtc.txt - t[COMPRESSED_RGB_PVRTC_4BPPV1_IMG] = { textureFormat: COMPRESSED_RGB_PVRTC_4BPPV1_IMG, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_RGB_PVRTC_2BPPV1_IMG] = { textureFormat: COMPRESSED_RGB_PVRTC_2BPPV1_IMG, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_RGBA_PVRTC_4BPPV1_IMG] = { textureFormat: COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_RGBA_PVRTC_2BPPV1_IMG] = { textureFormat: COMPRESSED_RGBA_PVRTC_2BPPV1_IMG, colorRenderable: false, textureFilterable: true }; + t[COMPRESSED_RGB_PVRTC_4BPPV1_IMG] = { textureFormat: COMPRESSED_RGB_PVRTC_4BPPV1_IMG, colorRenderable: false, textureFilterable: true, bytesPerTexel: 1 }; + t[COMPRESSED_RGB_PVRTC_2BPPV1_IMG] = { textureFormat: COMPRESSED_RGB_PVRTC_2BPPV1_IMG, colorRenderable: false, textureFilterable: true, bytesPerTexel: 1 }; + t[COMPRESSED_RGBA_PVRTC_4BPPV1_IMG] = { textureFormat: COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, colorRenderable: false, textureFilterable: true, bytesPerTexel: 1 }; + t[COMPRESSED_RGBA_PVRTC_2BPPV1_IMG] = { textureFormat: COMPRESSED_RGBA_PVRTC_2BPPV1_IMG, colorRenderable: false, textureFilterable: true, bytesPerTexel: 1 }; // https://registry.khronos.org/OpenGL/extensions/KHR/KHR_texture_compression_astc_hdr.txt - t[COMPRESSED_RGBA_ASTC_4x4_KHR] = { textureFormat: COMPRESSED_RGBA_ASTC_4x4_KHR, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_RGBA_ASTC_5x4_KHR] = { textureFormat: COMPRESSED_RGBA_ASTC_5x4_KHR, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_RGBA_ASTC_5x5_KHR] = { textureFormat: COMPRESSED_RGBA_ASTC_5x5_KHR, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_RGBA_ASTC_6x5_KHR] = { textureFormat: COMPRESSED_RGBA_ASTC_6x5_KHR, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_RGBA_ASTC_6x6_KHR] = { textureFormat: COMPRESSED_RGBA_ASTC_6x6_KHR, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_RGBA_ASTC_8x5_KHR] = { textureFormat: COMPRESSED_RGBA_ASTC_8x5_KHR, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_RGBA_ASTC_8x6_KHR] = { textureFormat: COMPRESSED_RGBA_ASTC_8x6_KHR, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_RGBA_ASTC_8x8_KHR] = { textureFormat: COMPRESSED_RGBA_ASTC_8x8_KHR, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_RGBA_ASTC_10x5_KHR] = { textureFormat: COMPRESSED_RGBA_ASTC_10x5_KHR, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_RGBA_ASTC_10x6_KHR] = { textureFormat: COMPRESSED_RGBA_ASTC_10x6_KHR, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_RGBA_ASTC_10x8_KHR] = { textureFormat: COMPRESSED_RGBA_ASTC_10x8_KHR, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_RGBA_ASTC_10x10_KHR] = { textureFormat: COMPRESSED_RGBA_ASTC_10x10_KHR, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_RGBA_ASTC_12x10_KHR] = { textureFormat: COMPRESSED_RGBA_ASTC_12x10_KHR, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_RGBA_ASTC_12x12_KHR] = { textureFormat: COMPRESSED_RGBA_ASTC_12x12_KHR, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR] = { textureFormat: COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR] = { textureFormat: COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR] = { textureFormat: COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR] = { textureFormat: COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR] = { textureFormat: COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR] = { textureFormat: COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR] = { textureFormat: COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR] = { textureFormat: COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR] = { textureFormat: COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR] = { textureFormat: COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR] = { textureFormat: COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR] = { textureFormat: COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR] = { textureFormat: COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR] = { textureFormat: COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR, colorRenderable: false, textureFilterable: true }; + t[COMPRESSED_RGBA_ASTC_4x4_KHR] = { textureFormat: COMPRESSED_RGBA_ASTC_4x4_KHR, colorRenderable: false, textureFilterable: true, bytesPerTexel: 1 }; + t[COMPRESSED_RGBA_ASTC_5x4_KHR] = { textureFormat: COMPRESSED_RGBA_ASTC_5x4_KHR, colorRenderable: false, textureFilterable: true, bytesPerTexel: 0.8 }; + t[COMPRESSED_RGBA_ASTC_5x5_KHR] = { textureFormat: COMPRESSED_RGBA_ASTC_5x5_KHR, colorRenderable: false, textureFilterable: true, bytesPerTexel: 0.64 }; + t[COMPRESSED_RGBA_ASTC_6x5_KHR] = { textureFormat: COMPRESSED_RGBA_ASTC_6x5_KHR, colorRenderable: false, textureFilterable: true, bytesPerTexel: 0.53375 }; + t[COMPRESSED_RGBA_ASTC_6x6_KHR] = { textureFormat: COMPRESSED_RGBA_ASTC_6x6_KHR, colorRenderable: false, textureFilterable: true, bytesPerTexel: 0.445 }; + t[COMPRESSED_RGBA_ASTC_8x5_KHR] = { textureFormat: COMPRESSED_RGBA_ASTC_8x5_KHR, colorRenderable: false, textureFilterable: true, bytesPerTexel: 0.4 }; + t[COMPRESSED_RGBA_ASTC_8x6_KHR] = { textureFormat: COMPRESSED_RGBA_ASTC_8x6_KHR, colorRenderable: false, textureFilterable: true, bytesPerTexel: 0.33375 }; + t[COMPRESSED_RGBA_ASTC_8x8_KHR] = { textureFormat: COMPRESSED_RGBA_ASTC_8x8_KHR, colorRenderable: false, textureFilterable: true, bytesPerTexel: 0.25 }; + t[COMPRESSED_RGBA_ASTC_10x5_KHR] = { textureFormat: COMPRESSED_RGBA_ASTC_10x5_KHR, colorRenderable: false, textureFilterable: true, bytesPerTexel: 0.32 }; + t[COMPRESSED_RGBA_ASTC_10x6_KHR] = { textureFormat: COMPRESSED_RGBA_ASTC_10x6_KHR, colorRenderable: false, textureFilterable: true, bytesPerTexel: 0.26625 }; + t[COMPRESSED_RGBA_ASTC_10x8_KHR] = { textureFormat: COMPRESSED_RGBA_ASTC_10x8_KHR, colorRenderable: false, textureFilterable: true, bytesPerTexel: 0.2 }; + t[COMPRESSED_RGBA_ASTC_10x10_KHR] = { textureFormat: COMPRESSED_RGBA_ASTC_10x10_KHR, colorRenderable: false, textureFilterable: true, bytesPerTexel: 0.16 }; + t[COMPRESSED_RGBA_ASTC_12x10_KHR] = { textureFormat: COMPRESSED_RGBA_ASTC_12x10_KHR, colorRenderable: false, textureFilterable: true, bytesPerTexel: 0.13375 }; + t[COMPRESSED_RGBA_ASTC_12x12_KHR] = { textureFormat: COMPRESSED_RGBA_ASTC_12x12_KHR, colorRenderable: false, textureFilterable: true, bytesPerTexel: 0.11125 }; + t[COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR] = { textureFormat: COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR, colorRenderable: false, textureFilterable: true, bytesPerTexel: 1 }; + t[COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR] = { textureFormat: COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR, colorRenderable: false, textureFilterable: true, bytesPerTexel: 0.8 }; + t[COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR] = { textureFormat: COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR, colorRenderable: false, textureFilterable: true, bytesPerTexel: 0.64 }; + t[COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR] = { textureFormat: COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR, colorRenderable: false, textureFilterable: true, bytesPerTexel: 0.53375 }; + t[COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR] = { textureFormat: COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR, colorRenderable: false, textureFilterable: true, bytesPerTexel: 0.445 }; + t[COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR] = { textureFormat: COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR, colorRenderable: false, textureFilterable: true, bytesPerTexel: 0.4 }; + t[COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR] = { textureFormat: COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR, colorRenderable: false, textureFilterable: true, bytesPerTexel: 0.33375 }; + t[COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR] = { textureFormat: COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR, colorRenderable: false, textureFilterable: true, bytesPerTexel: 0.25 }; + t[COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR] = { textureFormat: COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR, colorRenderable: false, textureFilterable: true, bytesPerTexel: 0.32 }; + t[COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR] = { textureFormat: COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR, colorRenderable: false, textureFilterable: true, bytesPerTexel: 0.26625 }; + t[COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR] = { textureFormat: COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR, colorRenderable: false, textureFilterable: true, bytesPerTexel: 0.2 }; + t[COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR] = { textureFormat: COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR, colorRenderable: false, textureFilterable: true, bytesPerTexel: 0.16 }; + t[COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR] = { textureFormat: COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR, colorRenderable: false, textureFilterable: true, bytesPerTexel: 0.13375 }; + t[COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR] = { textureFormat: COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR, colorRenderable: false, textureFilterable: true, bytesPerTexel: 0.11125 }; // https://registry.khronos.org/OpenGL/extensions/EXT/EXT_texture_compression_bptc.txt - t[COMPRESSED_RGBA_BPTC_UNORM_EXT] = { textureFormat: COMPRESSED_RGBA_BPTC_UNORM_EXT, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT] = { textureFormat: COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT] = { textureFormat: COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT] = { textureFormat: COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT, colorRenderable: false, textureFilterable: true }; + t[COMPRESSED_RGBA_BPTC_UNORM_EXT] = { textureFormat: COMPRESSED_RGBA_BPTC_UNORM_EXT, colorRenderable: false, textureFilterable: true, bytesPerTexel: 1 }; + t[COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT] = { textureFormat: COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT, colorRenderable: false, textureFilterable: true, bytesPerTexel: 1 }; + t[COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT] = { textureFormat: COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT, colorRenderable: false, textureFilterable: true, bytesPerTexel: 1 }; + t[COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT] = { textureFormat: COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT, colorRenderable: false, textureFilterable: true, bytesPerTexel: 1 }; // https://registry.khronos.org/OpenGL/extensions/EXT/EXT_texture_compression_rgtc.txt - t[COMPRESSED_RED_RGTC1_EXT] = { textureFormat: COMPRESSED_RED_RGTC1_EXT, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_SIGNED_RED_RGTC1_EXT] = { textureFormat: COMPRESSED_SIGNED_RED_RGTC1_EXT, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_RED_GREEN_RGTC2_EXT] = { textureFormat: COMPRESSED_RED_GREEN_RGTC2_EXT, colorRenderable: false, textureFilterable: true }; - t[COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT] = { textureFormat: COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT, colorRenderable: false, textureFilterable: true }; + t[COMPRESSED_RED_RGTC1_EXT] = { textureFormat: COMPRESSED_RED_RGTC1_EXT, colorRenderable: false, textureFilterable: true, bytesPerTexel: 1 }; + t[COMPRESSED_SIGNED_RED_RGTC1_EXT] = { textureFormat: COMPRESSED_SIGNED_RED_RGTC1_EXT, colorRenderable: false, textureFilterable: true, bytesPerTexel: 1 }; + t[COMPRESSED_RED_GREEN_RGTC2_EXT] = { textureFormat: COMPRESSED_RED_GREEN_RGTC2_EXT, colorRenderable: false, textureFilterable: true, bytesPerTexel: 1 }; + t[COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT] = { textureFormat: COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT, colorRenderable: false, textureFilterable: true, bytesPerTexel: 1 }; for (const info of Object.values(t)) { info.compressed = true; @@ -539,6 +539,68 @@ function isCompressedInternalFormat(internalFormat) { return !!info.compressed; } + +/** + * Get the bytesPerTexel for a given internalFormat + * + * @param {number} internalFormat The internal format + * @returns the corresponding bytesPerTexel + * @private + */ +function getbytesPerTexelForInternalFormat(internalFormat) { + const info = getTextureInternalFormatInfo(internalFormat); + if (!info) { + throw "unknown internal format"; + } + return info.bytesPerTexel; +} + +/** + * Set skip state to defaults + * @param {module:twgl.TextureOptions} [options] A TextureOptions object with whatever parameters you want set. + * @param {(number[]|ArrayBufferView)} buffer An array or typed arry with compressed texture data. + * @param {number} width The width parameter from texImage2D etc.. + * @param {number} height The height parameter from texImage2D etc.. + * @private + */ +function createCompressedTextureLevelBuffers(options, buffer, width, height) { + const internalFormat = options.internalFormat; + const levels = options.level || 1; + const blockWidth = options.blockWidth || 4; + const blockHeight = options.blockHeight || 4; + // The byte-size of the first level buffer + const buffers = new Array(levels); + const bytesPerTexel = getbytesPerTexelForInternalFormat(internalFormat); + + let offset = buffer.byteOffset; + + let levelWidth = width; + let levelHeight = height; + let alignedLevelWidth = (levelWidth + blockWidth - 1) & ~(blockWidth - 1); + let alignedLevelHeight = (levelHeight + blockHeight - 1) & ~(blockHeight - 1); + + let levelSize = alignedLevelWidth * alignedLevelHeight * bytesPerTexel; + for (let i = 0; i < levels; i++) { + buffers[i] = { + levelID: i, + levelWidth: levels > 1 ? levelWidth : alignedLevelWidth, + levelHeight: levels > 1 ? levelHeight : alignedLevelHeight, + levelBuffer: new Uint8Array(buffer.buffer, offset, levelSize), + }; + + offset += levelSize; + + // Calculate levelBuffer dimensions for next iteration + levelWidth = (levelWidth >> 1) || 1; + levelHeight = (levelHeight >> 1) || 1; + alignedLevelWidth = (levelWidth + blockWidth - 1) & ~(blockWidth - 1); + alignedLevelHeight = (levelHeight + blockHeight - 1) & ~(blockHeight - 1); + levelSize = alignedLevelWidth * alignedLevelHeight * bytesPerTexel; + } + + return buffers; +} + /** * Returns true if value is power of 2 * @param {number} value number to check. @@ -685,8 +747,10 @@ function setDefaults(newDefaults) { * @typedef {Object} TextureOptions * @property {number} [target] the type of texture `gl.TEXTURE_2D` or `gl.TEXTURE_CUBE_MAP`. Defaults to `gl.TEXTURE_2D`. * @property {number} [level] the mip level to affect. Defaults to 0. Note, if set auto will be considered false unless explicitly set to true. - * @property {number} [width] the width of the texture. Only used if src is an array or typed array or null. - * @property {number} [height] the height of a texture. Only used if src is an array or typed array or null. + * @property {number} [width] the width of the texture. Only used if internalFormat is an array or typed array or null. + * @property {number} [height] the height of a texture. Only used if internalFormat is an array or typed array or null. + * @property {number} [blockWidth] the width of the compressed texture block width size. Only used if internalFormat is an array or typed array or null.. + * @property {number} [blockHeight] the height of the compressed texture block height size. Only used if internalFormat is an array or typed array or null.. * @property {number} [depth] the depth of a texture. Only used if src is an array or type array or null and target is `TEXTURE_3D` . * @property {number} [min] the min filter setting (eg. `gl.LINEAR`). Defaults to `gl.NEAREST_MIPMAP_LINEAR` * or if texture is not a power of 2 on both dimensions then defaults to `gl.LINEAR`. @@ -1699,7 +1763,11 @@ function setTextureFromArray(gl, tex, src, options) { const offset = faceSize * f.ndx; const data = src.subarray(offset, offset + faceSize); if (compressed) { - gl.compressedTexImage2D(f.face, level, internalFormat, width, height, 0, data); + const levelBuffers = createCompressedTextureLevelBuffers(options, data, width, height); + levelBuffers.forEach(levelBufferData => { + const { levelID, levelWidth, levelHeight, levelBuffer } = levelBufferData; + gl.compressedTexImage2D(f.face, levelID, internalFormat, levelWidth, levelHeight, 0, levelBuffer); + }); } else { gl.texImage2D(f.face, level, internalFormat, width, height, 0, format, type, data); } @@ -1708,7 +1776,11 @@ function setTextureFromArray(gl, tex, src, options) { gl.texImage3D(target, level, internalFormat, width, height, depth, 0, format, type, src); } else { if (compressed) { - gl.compressedTexImage2D(target, level, internalFormat, width, height, 0, src); + const levelBuffers = createCompressedTextureLevelBuffers(options, src, width, height); + levelBuffers.forEach(levelBufferData => { + const { levelID, levelWidth, levelHeight, levelBuffer } = levelBufferData; + gl.compressedTexImage2D(target, levelID, internalFormat, levelWidth, levelHeight, 0, levelBuffer); + }); } else { gl.texImage2D(target, level, internalFormat, width, height, 0, format, type, src); } diff --git a/test/tests/texture-tests.js b/test/tests/texture-tests.js index 01a1f300..2dcf569e 100644 --- a/test/tests/texture-tests.js +++ b/test/tests/texture-tests.js @@ -204,22 +204,26 @@ describe('texture tests', () => { gl.deleteTexture(texture); }); - itWebGL2(`test compressed texture format WEBGL_compressed_texture_s3tc`, ['WEBGL_compressed_texture_s3tc'], async() => { + itWebGL2(`test compressed texture format WEBGL_compressed_texture_s3tc with mipmap levels`, ['WEBGL_compressed_texture_s3tc'], async() => { const {gl} = createContext2(); twgl.addExtensionsToContext(gl); setCanvasAndViewportSizeTo1x1(gl); const red = [255, 0, 0, 255]; const internalFormat = gl.COMPRESSED_RGB_S3TC_DXT1_EXT; - const red_4x4 = new Uint16Array([ - 0b11111_000000_00000, - 0b11111_000000_00000, - 0, 0, + const red_4x4_mipmap_level_3 = new Uint8Array([ + 0, 248, 0, 248, + 0, 0, 0, 0, 0, + 248, 0, 248, 0, + 0, 0, 0, 0, + 248, 0, 248, + 0, 0, 0, 0, ]); const width = 4; const height = 4; + const level = 3; - const texture = twgl.createTexture(gl, { src: red_4x4, width, height, internalFormat }); + const texture = twgl.createTexture(gl, { src: red_4x4_mipmap_level_3, width, height, internalFormat, level }); assertNoWebGLError(gl); const prg = create1PixelTextureRenderingProgram(gl); @@ -232,6 +236,7 @@ describe('texture tests', () => { gl.deleteTexture(texture); }); + itWebGL2(`test compressed texture format WEBGL_compressed_texture_s3tc cubemap`, ['WEBGL_compressed_texture_s3tc'], async() => { const {gl} = createContext2(); twgl.addExtensionsToContext(gl);