diff --git a/include/osg/Image b/include/osg/Image index 28c28429d7d..4b135c1e4bf 100644 --- a/include/osg/Image +++ b/include/osg/Image @@ -439,6 +439,7 @@ class OSG_EXPORT Image : public BufferData void ensureValidSizeForTexturing(GLint maxTextureSize); static bool isPackedType(GLenum type); + static bool isBPTC(GLenum pixelFormat); static GLenum computePixelFormat(GLenum pixelFormat); static GLenum computeFormatDataType(GLenum pixelFormat); diff --git a/include/osg/Texture b/include/osg/Texture index 166584ee860..35c9a399278 100644 --- a/include/osg/Texture +++ b/include/osg/Texture @@ -75,6 +75,13 @@ #define GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT 0x8DBE #endif +#ifndef GL_ARB_texture_compression_bptc + #define GL_COMPRESSED_RGBA_BPTC_UNORM 0x8E8C + #define GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM 0x8E8D + #define GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E + #define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F +#endif + #ifndef GL_IMG_texture_compression_pvrtc #define GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG 0x8C00 #define GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG 0x8C01 diff --git a/src/osg/Image.cpp b/src/osg/Image.cpp index bf55cbf74fe..7e2d0af25ce 100644 --- a/src/osg/Image.cpp +++ b/src/osg/Image.cpp @@ -335,6 +335,20 @@ bool Image::isPackedType(GLenum type) } } +bool Image::isBPTC(GLenum pixelFormat) +{ + switch(pixelFormat) + { + case(GL_COMPRESSED_RGBA_BPTC_UNORM): + case(GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM): + case(GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT): + case(GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT): + return true; + default: + return false; + } +} + GLenum Image::computePixelFormat(GLenum format) { @@ -707,6 +721,11 @@ unsigned int Image::computeNumComponents(GLenum pixelFormat) case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR) : return 4; case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR) : return 4; case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR) : return 4; + // BPTC (BC6H/BC7) + case (GL_COMPRESSED_RGBA_BPTC_UNORM) : return 4; + case (GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM) : return 4; + case (GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT) : return 3; + case (GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT) : return 3; default: { OSG_WARN<<"error pixelFormat = "< 0) { + osg::Vec3i footprint = computeBlockFootprint(pixelFormat); + int blocksWide = (width + footprint.x() - 1) / footprint.x(); + unsigned int size = blockSize * blocksWide; + return roudUpToMultiple(size, packing); + } + + // Non-compressed formats unsigned int pixelSize = computePixelSizeInBits(pixelFormat,type); int widthInBits = width*pixelSize; int packingInBits = packing!=0 ? packing*8 : 8; @@ -1822,6 +1869,14 @@ void Image::flipVertical() return; } + // BPTC (BC6H/BC7) textures cannot be flipped in compressed form due to complex per-block encoding. + // Callers should check isBPTC() and set TOP_LEFT origin instead of calling flipVertical(). + if (Image::isBPTC(_pixelFormat)) + { + OSG_WARN << "Image::flipVertical(): BPTC (BC6H/BC7) textures cannot be flipped in compressed form." << std::endl; + return; + } + unsigned int rowSize = getRowSizeInBytes(); unsigned int rowStep = getRowStepInBytes(); diff --git a/src/osg/Texture.cpp b/src/osg/Texture.cpp index 20cfe56693f..5978009fb0a 100644 --- a/src/osg/Texture.cpp +++ b/src/osg/Texture.cpp @@ -199,10 +199,10 @@ InternalPixelRelations compressedInternalFormats[] = { , { GL_COMPRESSED_SIGNED_RED_RGTC1_EXT , GL_RED , GL_COMPRESSED_SIGNED_RED_RGTC1_EXT } // , { GL_COMPRESSED_RG_RGTC2 , GL_RG , GL_COMPRESSED_RG_RGTC2 } // , { GL_COMPRESSED_SIGNED_RG_RGTC2 , GL_RG , GL_COMPRESSED_SIGNED_RG_RGTC2 } - // , { GL_COMPRESSED_RGBA_BPTC_UNORM , GL_RGBA , GL_COMPRESSED_RGBA_BPTC_UNORM } - // , { GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM , GL_RGBA , GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM } - // , { GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT , GL_RGB , GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT } - // , { GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT , GL_RGB , GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT } + , { GL_COMPRESSED_RGBA_BPTC_UNORM , GL_RGBA , GL_COMPRESSED_RGBA_BPTC_UNORM } + , { GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM , GL_RGBA , GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM } + , { GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT , GL_RGB , GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT } + , { GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT , GL_RGB , GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT } , { GL_COMPRESSED_RGB_S3TC_DXT1_EXT , GL_RGB , GL_COMPRESSED_RGB_S3TC_DXT1_EXT } , { GL_COMPRESSED_RGBA_S3TC_DXT1_EXT , GL_RGBA , GL_COMPRESSED_RGBA_S3TC_DXT1_EXT } @@ -377,6 +377,12 @@ void Texture::TextureProfile::computeSize() case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT: numBitsPerTexel = 8; break; case GL_COMPRESSED_RED_GREEN_RGTC2_EXT: numBitsPerTexel = 8; break; + // BPTC (BC6H/BC7) + case GL_COMPRESSED_RGBA_BPTC_UNORM: numBitsPerTexel = 8; break; + case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM: numBitsPerTexel = 8; break; + case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT: numBitsPerTexel = 8; break; + case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT: numBitsPerTexel = 8; break; + case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG: numBitsPerTexel = 2; break; case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: numBitsPerTexel = 2; break; case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG: numBitsPerTexel = 4; break; @@ -1898,6 +1904,11 @@ bool Texture::isCompressedInternalFormat(GLint internalFormat) case (GL_COMPRESSED_RED_RGTC1_EXT): case (GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT): case (GL_COMPRESSED_RED_GREEN_RGTC2_EXT): + // BPTC (BC6H/BC7) + case (GL_COMPRESSED_RGBA_BPTC_UNORM): + case (GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM): + case (GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT): + case (GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT): case (GL_ETC1_RGB8_OES): case (GL_COMPRESSED_RGB8_ETC2): case (GL_COMPRESSED_SRGB8_ETC2): @@ -1969,6 +1980,9 @@ void Texture::getCompressedSize(GLenum internalFormat, GLint width, GLint height blockSize = 8; else if (internalFormat == GL_COMPRESSED_RED_GREEN_RGTC2_EXT || internalFormat == GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT) blockSize = 16; + // BPTC (BC6H/BC7) - 128 bits per block + else if (internalFormat == GL_COMPRESSED_RGBA_BPTC_UNORM || internalFormat == GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM || internalFormat == GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT || internalFormat == GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT) + blockSize = 16; else if (internalFormat == GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG || internalFormat == GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG) { blockSize = 8 * 4; // Pixel by pixel block size for 2bpp @@ -2397,6 +2411,11 @@ void Texture::applyTexImage2D_load(State& state, GLenum target, const Image* ima case(GL_COMPRESSED_SIGNED_RG11_EAC): case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT: case GL_COMPRESSED_RED_GREEN_RGTC2_EXT: _internalFormat = GL_RG; break; + // BPTC (BC6H/BC7) + case GL_COMPRESSED_RGBA_BPTC_UNORM: + case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM: _internalFormat = GL_RGBA; break; + case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT: + case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT: _internalFormat = GL_RGB; break; } } diff --git a/src/osgPlugins/dds/ReaderWriterDDS.cpp b/src/osgPlugins/dds/ReaderWriterDDS.cpp index 6007ff3e5b7..e4d000a18a8 100644 --- a/src/osgPlugins/dds/ReaderWriterDDS.cpp +++ b/src/osgPlugins/dds/ReaderWriterDDS.cpp @@ -814,6 +814,30 @@ osg::Image* ReadDDSFile(std::istream& _istream, bool flipDDSRead) pixelFormat = GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT; break; + case OSG_DXGI_FORMAT_BC6H_UF16: + internalFormat = GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT; + pixelFormat = GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT; + packing = 4; // 8 bits/pixel. 4 px = 4 bytes + break; + + case OSG_DXGI_FORMAT_BC6H_SF16: + internalFormat = GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT; + pixelFormat = GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT; + packing = 4; // 8 bits/pixel. 4 px = 4 bytes + break; + + case OSG_DXGI_FORMAT_BC7_UNORM: + internalFormat = GL_COMPRESSED_RGBA_BPTC_UNORM; + pixelFormat = GL_COMPRESSED_RGBA_BPTC_UNORM; + packing = 4; // 8 bits/pixel. 4 px = 4 bytes + break; + + case OSG_DXGI_FORMAT_BC7_UNORM_SRGB: + internalFormat = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM; + pixelFormat = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM; + packing = 4; // 8 bits/pixel. 4 px = 4 bytes + break; + default: OSG_WARN << "ReadDDSFile warning: unhandled DX10 pixel format 0x" << std::hex << std::setw(8) << std::setfill('0') @@ -1100,7 +1124,11 @@ osg::Image* ReadDDSFile(std::istream& _istream, bool flipDDSRead) if (mipmap_offsets.size()>0) osgImage->setMipmapLevels(mipmap_offsets); - if (flipDDSRead) { + osgImage->setOrigin(osg::Image::TOP_LEFT); + + // BPTC (BC6H/BC7) textures cannot be flipped in compressed form + if (flipDDSRead && !osg::Image::isBPTC(internalFormat)) + { osgImage->setOrigin(osg::Image::BOTTOM_LEFT); if (!isDXTC || ((s>4 && s%4==0 && t>4 && t%4==0) || s<=4)) // Flip may crash (access violation) or fail for non %4 dimensions (except for s<4). Tested with revision trunk 2013-02-22. {