From 041f26a7c59d531f6a398b47db218b21625ea00a Mon Sep 17 00:00:00 2001 From: BStringhamVRSK <40642629+BStringhamVRSK@users.noreply.github.com> Date: Wed, 15 Jan 2020 11:26:29 -0700 Subject: [PATCH] Implemented sRGB support for DXT encoded textures (#2026) * Added sRGB support for DXT compressed textures - OpenGL * Added sRGB support for DXT compressed textures - Vulkan and Metal * Added detection if OpenGL driver supports sRGB compressed textures (EXT_texture_sRGB extension) * Fixed whitespace to use spaces rather than tabs * Test for GL_EXT_texture_sRGB or GL_EXT_texture_compression_s3tc_srgb support for sRGB DXT compressed textures * GL ES uses GL_EXT_texture_compression_s3tc_srgb instead of GL_EXT_texture_sRGB --- filament/backend/include/backend/DriverEnums.h | 8 +++++++- filament/backend/src/BackendUtils.cpp | 8 ++++++++ filament/backend/src/CommandStream.cpp | 4 ++++ filament/backend/src/metal/MetalEnums.h | 4 ++++ filament/backend/src/opengl/GLUtils.h | 14 ++++++++++++++ filament/backend/src/opengl/OpenGLContext.cpp | 2 ++ filament/backend/src/opengl/OpenGLContext.h | 2 ++ filament/backend/src/opengl/OpenGLDriver.cpp | 6 +++++- filament/backend/src/vulkan/VulkanUtility.cpp | 4 ++++ 9 files changed, 50 insertions(+), 2 deletions(-) diff --git a/filament/backend/include/backend/DriverEnums.h b/filament/backend/include/backend/DriverEnums.h index bba497fb1c..db5ca4c707 100644 --- a/filament/backend/include/backend/DriverEnums.h +++ b/filament/backend/include/backend/DriverEnums.h @@ -261,6 +261,7 @@ enum class CompressedPixelDataType : uint16_t { // Available everywhere except Android/iOS DXT1_RGB, DXT1_RGBA, DXT3_RGBA, DXT5_RGBA, + DXT1_SRGB, DXT1_SRGBA, DXT3_SRGBA, DXT5_SRGBA, // ASTC formats are available with a GLES extension RGBA_ASTC_4x4, @@ -414,6 +415,7 @@ enum class TextureFormat : uint16_t { // Available everywhere except Android/iOS DXT1_RGB, DXT1_RGBA, DXT3_RGBA, DXT5_RGBA, + DXT1_SRGB, DXT1_SRGBA, DXT3_SRGBA, DXT5_SRGBA, // ASTC formats are available with a GLES extension RGBA_ASTC_4x4, @@ -468,7 +470,11 @@ static constexpr bool isETC2Compression(TextureFormat format) noexcept { //! returns whether this format is an ETC3 compressed format static constexpr bool isS3TCCompression(TextureFormat format) noexcept { - return format >= TextureFormat::DXT1_RGB && format <= TextureFormat::DXT5_RGBA; + return format >= TextureFormat::DXT1_RGB && format <= TextureFormat::DXT5_SRGBA; +} + +static constexpr bool isS3TCSRGBCompression(TextureFormat format) noexcept { + return format >= TextureFormat::DXT1_SRGB && format <= TextureFormat::DXT5_SRGBA; } //! Texture Cubemap Face diff --git a/filament/backend/src/BackendUtils.cpp b/filament/backend/src/BackendUtils.cpp index 55ecc32f3e..84f42aba28 100644 --- a/filament/backend/src/BackendUtils.cpp +++ b/filament/backend/src/BackendUtils.cpp @@ -117,10 +117,14 @@ size_t getFormatSize(TextureFormat format) noexcept { case TextureFormat::DXT1_RGB: case TextureFormat::DXT1_RGBA: + case TextureFormat::DXT1_SRGB: + case TextureFormat::DXT1_SRGBA: return 8; case TextureFormat::DXT3_RGBA: + case TextureFormat::DXT3_SRGBA: case TextureFormat::DXT5_RGBA: + case TextureFormat::DXT5_SRGBA: return 16; // The block size for ASTC compression is always 16 bytes. @@ -175,8 +179,12 @@ size_t getBlockWidth(TextureFormat format) noexcept { case TextureFormat::DXT1_RGB: case TextureFormat::DXT1_RGBA: + case TextureFormat::DXT1_SRGB: + case TextureFormat::DXT1_SRGBA: case TextureFormat::DXT3_RGBA: + case TextureFormat::DXT3_SRGBA: case TextureFormat::DXT5_RGBA: + case TextureFormat::DXT5_SRGBA: return 4; case TextureFormat::RGBA_ASTC_4x4: diff --git a/filament/backend/src/CommandStream.cpp b/filament/backend/src/CommandStream.cpp index 52374b3c66..c732ecc626 100644 --- a/filament/backend/src/CommandStream.cpp +++ b/filament/backend/src/CommandStream.cpp @@ -363,9 +363,13 @@ io::ostream& operator<<(io::ostream& out, TextureFormat format) { CASE(TextureFormat, ETC2_EAC_RGBA8) CASE(TextureFormat, ETC2_EAC_SRGBA8) CASE(TextureFormat, DXT1_RGB) + CASE(TextureFormat, DXT1_SRGB) CASE(TextureFormat, DXT1_RGBA) + CASE(TextureFormat, DXT1_SRGBA) CASE(TextureFormat, DXT3_RGBA) + CASE(TextureFormat, DXT3_SRGBA) CASE(TextureFormat, DXT5_RGBA) + CASE(TextureFormat, DXT5_SRGBA) CASE(TextureFormat, UNUSED) CASE(TextureFormat, RGBA_ASTC_4x4) CASE(TextureFormat, RGBA_ASTC_5x4) diff --git a/filament/backend/src/metal/MetalEnums.h b/filament/backend/src/metal/MetalEnums.h index d05bbba699..8adb6f4e79 100644 --- a/filament/backend/src/metal/MetalEnums.h +++ b/filament/backend/src/metal/MetalEnums.h @@ -233,10 +233,14 @@ constexpr inline MTLPixelFormat getMetalFormat(TextureFormat format) noexcept { // DXT (BC) formats are only available on macOS desktop. // See https://en.wikipedia.org/wiki/S3_Texture_Compression#S3TC_format_comparison case TextureFormat::DXT1_RGBA: return MTLPixelFormatBC1_RGBA; + case TextureFormat::DXT1_SRGBA: return MTLPixelFormatBC1_RGBA_sRGB; case TextureFormat::DXT3_RGBA: return MTLPixelFormatBC2_RGBA; + case TextureFormat::DXT3_SRGBA: return MTLPixelFormatBC2_RGBA_sRGB; case TextureFormat::DXT5_RGBA: return MTLPixelFormatBC3_RGBA; + case TextureFormat::DXT5_SRGBA: return MTLPixelFormatBC3_RGBA_sRGB; case TextureFormat::DXT1_RGB: return MTLPixelFormatInvalid; + case TextureFormat::DXT1_SRGB: return MTLPixelFormatInvalid; #endif #if defined(IOS) diff --git a/filament/backend/src/opengl/GLUtils.h b/filament/backend/src/opengl/GLUtils.h index 410d8df9aa..7f66fcad6f 100644 --- a/filament/backend/src/opengl/GLUtils.h +++ b/filament/backend/src/opengl/GLUtils.h @@ -390,6 +390,20 @@ constexpr /* inline */ GLenum getInternalFormat(backend::TextureFormat format) n return 0; #endif +#if defined(GL_EXT_texture_sRGB) || defined(GL_EXT_texture_compression_s3tc_srgb) + case TextureFormat::DXT1_SRGB: return GL_COMPRESSED_SRGB_S3TC_DXT1_EXT; + case TextureFormat::DXT1_SRGBA: return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT; + case TextureFormat::DXT3_SRGBA: return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT; + case TextureFormat::DXT5_SRGBA: return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT; +#else + case TextureFormat::DXT1_SRGB: + case TextureFormat::DXT1_SRGBA: + case TextureFormat::DXT3_SRGBA: + case TextureFormat::DXT5_SRGBA: + // this should not happen + return 0; +#endif + #if defined(GL_KHR_texture_compression_astc_hdr) case TextureFormat::RGBA_ASTC_4x4: return GL_COMPRESSED_RGBA_ASTC_4x4_KHR; case TextureFormat::RGBA_ASTC_5x4: return GL_COMPRESSED_RGBA_ASTC_5x4_KHR; diff --git a/filament/backend/src/opengl/OpenGLContext.cpp b/filament/backend/src/opengl/OpenGLContext.cpp index 531bee6533..f4549effb7 100644 --- a/filament/backend/src/opengl/OpenGLContext.cpp +++ b/filament/backend/src/opengl/OpenGLContext.cpp @@ -189,6 +189,7 @@ void OpenGLContext::initExtensionsGLES(GLint major, GLint minor, ExtentionSet co ext.texture_compression_s3tc = hasExtension(exts, "WEBGL_compressed_texture_s3tc"); ext.EXT_multisampled_render_to_texture = hasExtension(exts, "GL_EXT_multisampled_render_to_texture"); ext.KHR_debug = hasExtension(exts, "GL_KHR_debug"); + ext.EXT_texture_compression_s3tc_srgb = hasExtension(exts, "GL_EXT_texture_compression_s3tc_srgb"); // ES 3.2 implies EXT_color_buffer_float if (major >= 3 && minor >= 2) { ext.EXT_color_buffer_float = true; @@ -205,6 +206,7 @@ void OpenGLContext::initExtensionsGL(GLint major, GLint minor, ExtentionSet cons ext.EXT_color_buffer_float = true; // Assumes core profile. ext.APPLE_color_buffer_packed_float = true; // Assumes core profile. ext.KHR_debug = major >= 4 && minor >= 3; + ext.EXT_texture_sRGB = hasExtension(exts, "GL_EXT_texture_sRGB"); } void OpenGLContext::bindBuffer(GLenum target, GLuint buffer) noexcept { diff --git a/filament/backend/src/opengl/OpenGLContext.h b/filament/backend/src/opengl/OpenGLContext.h index e844619244..5aab4ab343 100644 --- a/filament/backend/src/opengl/OpenGLContext.h +++ b/filament/backend/src/opengl/OpenGLContext.h @@ -122,6 +122,8 @@ public: bool APPLE_color_buffer_packed_float = false; bool EXT_multisampled_render_to_texture = false; bool KHR_debug = false; + bool EXT_texture_sRGB = false; + bool EXT_texture_compression_s3tc_srgb = false; } ext; struct { diff --git a/filament/backend/src/opengl/OpenGLDriver.cpp b/filament/backend/src/opengl/OpenGLDriver.cpp index de35250bce..59d9ac8f76 100644 --- a/filament/backend/src/opengl/OpenGLDriver.cpp +++ b/filament/backend/src/opengl/OpenGLDriver.cpp @@ -1259,7 +1259,11 @@ bool OpenGLDriver::isTextureFormatSupported(TextureFormat format) { return gl.ext.texture_compression_etc2; } if (isS3TCCompression(format)) { - return gl.ext.texture_compression_s3tc; + if (isS3TCSRGBCompression(format)) { + return gl.ext.texture_compression_s3tc && (gl.ext.EXT_texture_sRGB || gl.ext.EXT_texture_compression_s3tc_srgb); + } else { + return gl.ext.texture_compression_s3tc; + } } return getInternalFormat(format) != 0; } diff --git a/filament/backend/src/vulkan/VulkanUtility.cpp b/filament/backend/src/vulkan/VulkanUtility.cpp index 1afc3001b5..7a82582ac8 100644 --- a/filament/backend/src/vulkan/VulkanUtility.cpp +++ b/filament/backend/src/vulkan/VulkanUtility.cpp @@ -173,9 +173,13 @@ VkFormat getVkFormat(TextureFormat format) { // Compressed textures. case TextureFormat::DXT1_RGB: return VK_FORMAT_BC1_RGB_UNORM_BLOCK; + case TextureFormat::DXT1_SRGB: return VK_FORMAT_BC1_RGB_SRGB_BLOCK; case TextureFormat::DXT1_RGBA: return VK_FORMAT_BC1_RGBA_UNORM_BLOCK; + case TextureFormat::DXT1_SRGBA: return VK_FORMAT_BC1_RGBA_SRGB_BLOCK; case TextureFormat::DXT3_RGBA: return VK_FORMAT_BC2_UNORM_BLOCK; + case TextureFormat::DXT3_SRGBA: return VK_FORMAT_BC2_SRGB_BLOCK; case TextureFormat::DXT5_RGBA: return VK_FORMAT_BC3_UNORM_BLOCK; + case TextureFormat::DXT5_SRGBA: return VK_FORMAT_BC3_SRGB_BLOCK; case TextureFormat::RGBA_ASTC_4x4: return VK_FORMAT_ASTC_4x4_UNORM_BLOCK; case TextureFormat::RGBA_ASTC_5x4: return VK_FORMAT_ASTC_5x4_UNORM_BLOCK;