KTX: Fixed cubemap loading.

This commit is contained in:
Branimir Karadžić 2015-11-17 22:10:17 -08:00
parent aa9298b572
commit 9094d162aa
2 changed files with 175 additions and 110 deletions

View file

@ -1859,6 +1859,7 @@ namespace bgfx
_imageContainer.m_hasAlpha = hasAlpha; _imageContainer.m_hasAlpha = hasAlpha;
_imageContainer.m_cubeMap = numFaces > 1; _imageContainer.m_cubeMap = numFaces > 1;
_imageContainer.m_ktx = true; _imageContainer.m_ktx = true;
_imageContainer.m_ktxLE = fromLittleEndian;
return TextureFormat::Unknown != format; return TextureFormat::Unknown != format;
} }
@ -2005,6 +2006,7 @@ namespace bgfx
_imageContainer.m_hasAlpha = hasAlpha; _imageContainer.m_hasAlpha = hasAlpha;
_imageContainer.m_cubeMap = numFaces > 1; _imageContainer.m_cubeMap = numFaces > 1;
_imageContainer.m_ktx = false; _imageContainer.m_ktx = false;
_imageContainer.m_ktxLE = false;
_imageContainer.m_srgb = colorSpace > 0; _imageContainer.m_srgb = colorSpace > 0;
return TextureFormat::Unknown != format; return TextureFormat::Unknown != format;
@ -2051,6 +2053,7 @@ namespace bgfx
_imageContainer.m_hasAlpha = false; _imageContainer.m_hasAlpha = false;
_imageContainer.m_cubeMap = tc.m_cubeMap; _imageContainer.m_cubeMap = tc.m_cubeMap;
_imageContainer.m_ktx = false; _imageContainer.m_ktx = false;
_imageContainer.m_ktxLE = false;
_imageContainer.m_srgb = false; _imageContainer.m_srgb = false;
return true; return true;
@ -2316,6 +2319,55 @@ namespace bgfx
_size = _imageContainer.m_size; _size = _imageContainer.m_size;
} }
const uint8_t* data = (const uint8_t*)_data;
if (_imageContainer.m_ktx)
{
uint32_t width = _imageContainer.m_width;
uint32_t height = _imageContainer.m_height;
uint32_t depth = _imageContainer.m_depth;
for (uint8_t lod = 0, num = _imageContainer.m_numMips; lod < num; ++lod)
{
uint32_t imageSize = bx::toHostEndian(*(const uint32_t*)&data[offset], _imageContainer.m_ktxLE);
offset += sizeof(uint32_t);
width = bx::uint32_max(blockWidth * minBlockX, ( (width + blockWidth - 1) / blockWidth )*blockWidth);
height = bx::uint32_max(blockHeight * minBlockY, ( (height + blockHeight - 1) / blockHeight)*blockHeight);
depth = bx::uint32_max(1, depth);
uint32_t size = width*height*depth*bpp/8;
BX_CHECK(size == imageSize, "KTX: Image size mismatch %d (expected %d).", size, imageSize);
for (uint8_t side = 0, numSides = _imageContainer.m_cubeMap ? 6 : 1; side < numSides; ++side)
{
if (side == _side
&& lod == _lod)
{
_mip.m_width = width;
_mip.m_height = height;
_mip.m_blockSize = blockSize;
_mip.m_size = size;
_mip.m_data = &data[offset];
_mip.m_bpp = bpp;
_mip.m_format = uint8_t(format);
_mip.m_hasAlpha = hasAlpha;
return true;
}
offset += imageSize;
BX_CHECK(offset <= _size, "Reading past size of data buffer! (offset %d, size %d)", offset, _size);
BX_UNUSED(_size);
}
width >>= 1;
height >>= 1;
depth >>= 1;
}
}
else
{
for (uint8_t side = 0, numSides = _imageContainer.m_cubeMap ? 6 : 1; side < numSides; ++side) for (uint8_t side = 0, numSides = _imageContainer.m_cubeMap ? 6 : 1; side < numSides; ++side)
{ {
uint32_t width = _imageContainer.m_width; uint32_t width = _imageContainer.m_width;
@ -2324,9 +2376,6 @@ namespace bgfx
for (uint8_t lod = 0, num = _imageContainer.m_numMips; lod < num; ++lod) for (uint8_t lod = 0, num = _imageContainer.m_numMips; lod < num; ++lod)
{ {
// skip imageSize in KTX format.
offset += _imageContainer.m_ktx ? sizeof(uint32_t) : 0;
width = bx::uint32_max(blockWidth * minBlockX, ( (width + blockWidth - 1) / blockWidth )*blockWidth); width = bx::uint32_max(blockWidth * minBlockX, ( (width + blockWidth - 1) / blockWidth )*blockWidth);
height = bx::uint32_max(blockHeight * minBlockY, ( (height + blockHeight - 1) / blockHeight)*blockHeight); height = bx::uint32_max(blockHeight * minBlockY, ( (height + blockHeight - 1) / blockHeight)*blockHeight);
depth = bx::uint32_max(1, depth); depth = bx::uint32_max(1, depth);
@ -2340,7 +2389,7 @@ namespace bgfx
_mip.m_height = height; _mip.m_height = height;
_mip.m_blockSize = blockSize; _mip.m_blockSize = blockSize;
_mip.m_size = size; _mip.m_size = size;
_mip.m_data = (const uint8_t*)_data + offset; _mip.m_data = &data[offset];
_mip.m_bpp = bpp; _mip.m_bpp = bpp;
_mip.m_format = uint8_t(format); _mip.m_format = uint8_t(format);
_mip.m_hasAlpha = hasAlpha; _mip.m_hasAlpha = hasAlpha;
@ -2357,6 +2406,7 @@ namespace bgfx
depth >>= 1; depth >>= 1;
} }
} }
}
return false; return false;
} }
@ -2367,10 +2417,10 @@ namespace bgfx
uint8_t bpp = _grayscale ? 8 : 32; uint8_t bpp = _grayscale ? 8 : 32;
uint8_t header[18] = {}; uint8_t header[18] = {};
header[2] = type; header[ 2] = type;
header[12] = _width&0xff; header[12] = _width &0xff;
header[13] = (_width>>8)&0xff; header[13] = (_width >>8)&0xff;
header[14] = _height&0xff; header[14] = _height &0xff;
header[15] = (_height>>8)&0xff; header[15] = (_height>>8)&0xff;
header[16] = bpp; header[16] = bpp;
header[17] = 32; header[17] = 32;
@ -2402,60 +2452,42 @@ namespace bgfx
} }
} }
void imageWriteKtx(bx::WriterI* _writer, TextureFormat::Enum _format, bool _cubeMap, uint32_t _width, uint32_t _height, uint32_t _depth, uint8_t _numMips, uint32_t _srcPitch, uint32_t _slicePitch, const void* _src) static int32_t imageWriteKtxHeader(bx::WriterI* _writer, TextureFormat::Enum _format, bool _cubeMap, uint32_t _width, uint32_t _height, uint32_t _depth, uint8_t _numMips)
{ {
BX_UNUSED(_srcPitch, _slicePitch);
bx::write(_writer, "\xabKTX 11\xbb\r\n\x1a\n", 12);
bx::write(_writer, UINT32_C(0x04030201) );
// glType
bx::write(_writer, UINT32_C(0) );
// glTypeSize
bx::write(_writer, UINT32_C(1) );
// glFormat
bx::write(_writer, UINT32_C(0) );
const KtxFormatInfo& tfi = s_translateKtxFormat[_format]; const KtxFormatInfo& tfi = s_translateKtxFormat[_format];
// glInternalFormat int32_t size = 0;
bx::write(_writer, tfi.m_internalFmt); size += bx::write(_writer, "\xabKTX 11\xbb\r\n\x1a\n", 12);
size += bx::write(_writer, UINT32_C(0x04030201) );
size += bx::write(_writer, UINT32_C(0) ); // glType
size += bx::write(_writer, UINT32_C(1) ); // glTypeSize
size += bx::write(_writer, UINT32_C(0) ); // glFormat
size += bx::write(_writer, tfi.m_internalFmt); // glInternalFormat
size += bx::write(_writer, tfi.m_fmt); // glBaseInternalFormat
size += bx::write(_writer, _width);
size += bx::write(_writer, _height);
size += bx::write(_writer, _depth);
size += bx::write(_writer, UINT32_C(0) ); // numberOfArrayElements
size += bx::write(_writer, _cubeMap ? UINT32_C(6) : UINT32_C(0) );
size += bx::write(_writer, uint32_t(_numMips) );
size += bx::write(_writer, UINT32_C(0) ); // Meta-data size.
// glBaseInternalFormat BX_CHECK(size == 64, "KTX: Failed to write header size %d (expected: %d).", size, 64);
bx::write(_writer, tfi.m_fmt); return size;
}
bx::write(_writer, _width); void imageWriteKtx(bx::WriterI* _writer, TextureFormat::Enum _format, bool _cubeMap, uint32_t _width, uint32_t _height, uint32_t _depth, uint8_t _numMips, const void* _src)
{
bx::write(_writer, _height); imageWriteKtxHeader(_writer, _format, _cubeMap, _width, _height, _depth, _numMips);
bx::write(_writer, _depth);
// numberOfArrayElements
bx::write(_writer, UINT32_C(0) );
bx::write(_writer, _cubeMap ? UINT32_C(6) : UINT32_C(0) );
bx::write(_writer, uint32_t(_numMips) );
// Meta-data size.
bx::write(_writer, UINT32_C(0) );
const ImageBlockInfo& blockInfo = s_imageBlockInfo[_format]; const ImageBlockInfo& blockInfo = s_imageBlockInfo[_format];
const uint8_t bpp = blockInfo.bitsPerPixel; const uint8_t bpp = blockInfo.bitsPerPixel;
const uint32_t blockSize = blockInfo.blockSize;
const uint32_t blockWidth = blockInfo.blockWidth; const uint32_t blockWidth = blockInfo.blockWidth;
const uint32_t blockHeight = blockInfo.blockHeight; const uint32_t blockHeight = blockInfo.blockHeight;
const uint32_t minBlockX = blockInfo.minBlockX; const uint32_t minBlockX = blockInfo.minBlockX;
const uint32_t minBlockY = blockInfo.minBlockY; const uint32_t minBlockY = blockInfo.minBlockY;
BX_UNUSED(blockSize);
const uint8_t* src = (const uint8_t*)_src; const uint8_t* src = (const uint8_t*)_src;
for (uint8_t side = 0, numSides = _cubeMap ? 6 : 1; side < numSides; ++side)
{
uint32_t width = _width; uint32_t width = _width;
uint32_t height = _height; uint32_t height = _height;
uint32_t depth = _depth; uint32_t depth = _depth;
@ -2469,14 +2501,43 @@ namespace bgfx
uint32_t size = width*height*depth*bpp/8; uint32_t size = width*height*depth*bpp/8;
bx::write(_writer, size); bx::write(_writer, size);
for (uint8_t side = 0, numSides = _cubeMap ? 6 : 1; side < numSides; ++side)
{
bx::write(_writer, src, size); bx::write(_writer, src, size);
src += size; src += size;
}
width >>= 1; width >>= 1;
height >>= 1; height >>= 1;
depth >>= 1; depth >>= 1;
} }
} }
void imageWriteKtx(bx::WriterI* _writer, ImageContainer& _imageContainer, const void* _data, uint32_t _size)
{
imageWriteKtxHeader(_writer
, TextureFormat::Enum(_imageContainer.m_format)
, _imageContainer.m_cubeMap
, _imageContainer.m_width
, _imageContainer.m_height
, _imageContainer.m_depth
, _imageContainer.m_numMips
);
for (uint32_t lod = 0, num = _imageContainer.m_numMips; lod < num; ++lod)
{
ImageMip mip;
imageGetRawData(_imageContainer, 0, lod, _data, _size, mip);
bx::write(_writer, mip.m_size);
for (uint8_t side = 0, numSides = _imageContainer.m_cubeMap ? 6 : 1; side < numSides; ++side)
{
if (imageGetRawData(_imageContainer, side, lod, _data, _size, mip) )
{
bx::write(_writer, mip.m_data, mip.m_size);
}
}
}
} }
} // namespace bgfx } // namespace bgfx

View file

@ -23,6 +23,7 @@ namespace bgfx
bool m_hasAlpha; bool m_hasAlpha;
bool m_cubeMap; bool m_cubeMap;
bool m_ktx; bool m_ktx;
bool m_ktxLE;
bool m_srgb; bool m_srgb;
}; };
@ -105,7 +106,10 @@ namespace bgfx
void imageWriteTga(bx::WriterI* _writer, uint32_t _width, uint32_t _height, uint32_t _srcPitch, const void* _src, bool _grayscale, bool _yflip); void imageWriteTga(bx::WriterI* _writer, uint32_t _width, uint32_t _height, uint32_t _srcPitch, const void* _src, bool _grayscale, bool _yflip);
/// ///
void imageWriteKtx(bx::WriterI* _writer, TextureFormat::Enum _format, bool _cubeMap, uint32_t _width, uint32_t _height, uint32_t _depth, uint8_t _numMips, uint32_t _srcPitch, uint32_t _slicePitch, const void* _src); void imageWriteKtx(bx::WriterI* _writer, TextureFormat::Enum _format, bool _cubeMap, uint32_t _width, uint32_t _height, uint32_t _depth, uint8_t _numMips, const void* _src);
///
void imageWriteKtx(bx::WriterI* _writer, ImageContainer& _imageContainer, const void* _data, uint32_t _size);
/// ///
bool imageParse(ImageContainer& _imageContainer, bx::ReaderSeekerI* _reader); bool imageParse(ImageContainer& _imageContainer, bx::ReaderSeekerI* _reader);