Merge pull request #3 from bkaradzic/master

Sync to tip
This commit is contained in:
Andrew Willmott
2018-07-23 16:05:07 +01:00
committed by GitHub
11 changed files with 2125 additions and 640 deletions

View File

@@ -50,9 +50,9 @@ namespace nvtt
for (uint32_t blockX = 0; blockX < ZOH::Tile::TILE_W; ++blockX)
{
nv::Vector4 color = srcRgba[blockY*srcRgbaStride + blockX];
zohTile.data[blockY][blockX].x = float(int16_t(bx::halfFromFloat(color.x) ) );
zohTile.data[blockY][blockX].y = float(int16_t(bx::halfFromFloat(color.y) ) );
zohTile.data[blockY][blockX].z = float(int16_t(bx::halfFromFloat(color.z) ) );
zohTile.data[blockY][blockX].x = float(int16_t(bx::halfFromFloat(bx::max(color.x, 0.0f) ) ) );
zohTile.data[blockY][blockX].y = float(int16_t(bx::halfFromFloat(bx::max(color.y, 0.0f) ) ) );
zohTile.data[blockY][blockX].z = float(int16_t(bx::halfFromFloat(bx::max(color.z, 0.0f) ) ) );
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -9,7 +9,7 @@
#include <stdint.h> // uint32_t
#include <stdlib.h> // NULL
#define BIMG_API_VERSION UINT32_C(6)
#define BIMG_API_VERSION UINT32_C(7)
namespace bx
{
@@ -73,7 +73,7 @@ namespace bimg
ASTC6x6, //!< ASTC 6x6 3.56 BPP
ASTC8x5, //!< ASTC 8x5 3.20 BPP
ASTC8x6, //!< ASTC 8x6 2.67 BPP
ASTC10x5, //!< ASTC 10x5 2.56 BPP
ASTC10x5, //!< ASTC 10x5 2.56 BPP
Unknown, // Compressed formats above.
@@ -334,6 +334,16 @@ namespace bimg
, const void* _src
);
///
void imageRgba32fDownsample2x2(
void* _dst
, uint32_t _width
, uint32_t _height
, uint32_t _depth
, uint32_t _srcPitch
, const void* _src
);
///
void imageRgba32fDownsample2x2NormalMap(
void* _dst
@@ -493,6 +503,18 @@ namespace bimg
, bx::Error* _err
);
///
int32_t imageWriteHdr(
bx::WriterI* _writer
, uint32_t _width
, uint32_t _height
, uint32_t _srcPitch
, const void* _src
, TextureFormat::Enum _format
, bool _yflip
, bx::Error* _err
);
///
int32_t imageWriteDds(
bx::WriterI* _writer
@@ -628,14 +650,6 @@ namespace bimg
, ImageMip& _mip
);
///
ImageContainer* imageCubemapFromLatLongRgba32F(
bx::AllocatorI* _allocator
, const ImageContainer& _input
, bool _useBilinearInterpolation
, bx::Error* _err
);
} // namespace bimg
#endif // BIMG_IMAGE_H_HEADER_GUARD

View File

@@ -127,6 +127,49 @@ namespace bimg
, float _alphaRef
);
///
ImageContainer* imageCubemapFromLatLongRgba32F(
bx::AllocatorI* _allocator
, const ImageContainer& _input
, bool _useBilinearInterpolation
, bx::Error* _err
);
///
ImageContainer* imageCubemapFromStripRgba32F(
bx::AllocatorI* _allocator
, const ImageContainer& _input
, bx::Error* _err
);
///
ImageContainer* imageGenerateMips(
bx::AllocatorI* _allocator
, const ImageContainer& _image
);
struct LightingModel
{
enum Enum
{
Phong,
PhongBrdf,
Blinn,
BlinnBrdf,
Ggx,
Count
};
};
///
ImageContainer* imageCubemapRadianceFilter(
bx::AllocatorI* _allocator
, const ImageContainer& _image
, LightingModel::Enum _lightingModel
, bx::Error* _err
);
} // namespace bimg
#endif // BIMG_ENCODE_H_HEADER_GUARD

View File

@@ -308,7 +308,7 @@ texturev: .build/projects/$(BUILD_PROJECT_DIR) ## Build texturev tool.
$(SILENT) $(MAKE) -C .build/projects/$(BUILD_PROJECT_DIR) texturev config=$(BUILD_TOOLS_CONFIG)
$(SILENT) cp .build/$(BUILD_OUTPUT_DIR)/bin/texturev$(BUILD_TOOLS_SUFFIX)$(EXE) tools/bin/$(OS)/texturev$(EXE)
tools: geometryc shaderc texturec texturev ## Build tools.
tools: texturec ## Build tools.
clean-tools: ## Clean tools projects.
-$(SILENT) rm -r .build/projects/$(BUILD_PROJECT_DIR)

View File

@@ -17,6 +17,7 @@ project "bimg_encode"
files {
path.join(BIMG_DIR, "include/**"),
path.join(BIMG_DIR, "src/image_encode.*"),
path.join(BIMG_DIR, "src/image_cubemap_filter.*"),
path.join(BIMG_DIR, "3rdparty/libsquish/**.cpp"),
path.join(BIMG_DIR, "3rdparty/libsquish/**.h"),
path.join(BIMG_DIR, "3rdparty/edtaa3/**.cpp"),

View File

@@ -43,7 +43,7 @@ namespace bimg
{
if (_hasMips)
{
const uint32_t max = bx::uint32_max(bx::uint32_max(_width, _height), _depth);
const uint32_t max = bx::max(_width, _height, _depth);
const uint32_t num = 1 + uint32_t(bx::log2(float(max) ) );
return uint8_t(num);

View File

@@ -10,7 +10,7 @@ namespace bimg
{
static const ImageBlockInfo s_imageBlockInfo[] =
{
// +-------------------------------------------- bits per pixel
// +--------------------------------------------- bits per pixel
// | +----------------------------------------- block width
// | | +-------------------------------------- block height
// | | | +---------------------------------- block size
@@ -38,15 +38,15 @@ namespace bimg
{ 4, 4, 4, 8, 2, 2, 0, 0, 0, 0, 0, 0, uint8_t(bx::EncodingType::Unorm) }, // PTC14A
{ 2, 8, 4, 8, 2, 2, 0, 0, 0, 0, 0, 0, uint8_t(bx::EncodingType::Unorm) }, // PTC22
{ 4, 4, 4, 8, 2, 2, 0, 0, 0, 0, 0, 0, uint8_t(bx::EncodingType::Unorm) }, // PTC24
{ 4, 4, 4, 8, 1, 1, 0, 0, 0, 0, 0, 0, uint8_t(bx::EncodingType::Unorm) }, // ATC
{ 8, 4, 4, 16, 1, 1, 0, 0, 0, 0, 0, 0, uint8_t(bx::EncodingType::Unorm) }, // ATCE
{ 8, 4, 4, 16, 1, 1, 0, 0, 0, 0, 0, 0, uint8_t(bx::EncodingType::Unorm) }, // ATCI
{ 8, 4, 4, 16, 1, 1, 0, 0, 0, 0, 0, 0, uint8_t(bx::EncodingType::Unorm) }, // ASTC4x4
{ 6, 5, 5, 16, 1, 1, 0, 0, 0, 0, 0, 0, uint8_t(bx::EncodingType::Unorm) }, // ASTC5x5
{ 4, 6, 6, 16, 1, 1, 0, 0, 0, 0, 0, 0, uint8_t(bx::EncodingType::Unorm) }, // ASTC6x6
{ 4, 8, 5, 16, 1, 1, 0, 0, 0, 0, 0, 0, uint8_t(bx::EncodingType::Unorm) }, // ASTC8x5
{ 3, 8, 6, 16, 1, 1, 0, 0, 0, 0, 0, 0, uint8_t(bx::EncodingType::Unorm) }, // ASTC8x6
{ 3, 10, 5, 16, 1, 1, 0, 0, 0, 0, 0, 0, uint8_t(bx::EncodingType::Unorm) }, // ASTC10x5
{ 4, 4, 4, 8, 1, 1, 0, 0, 0, 0, 0, 0, uint8_t(bx::EncodingType::Unorm) }, // ATC
{ 8, 4, 4, 16, 1, 1, 0, 0, 0, 0, 0, 0, uint8_t(bx::EncodingType::Unorm) }, // ATCE
{ 8, 4, 4, 16, 1, 1, 0, 0, 0, 0, 0, 0, uint8_t(bx::EncodingType::Unorm) }, // ATCI
{ 8, 4, 4, 16, 1, 1, 0, 0, 0, 0, 0, 0, uint8_t(bx::EncodingType::Unorm) }, // ASTC4x4
{ 6, 5, 5, 16, 1, 1, 0, 0, 0, 0, 0, 0, uint8_t(bx::EncodingType::Unorm) }, // ASTC5x5
{ 4, 6, 6, 16, 1, 1, 0, 0, 0, 0, 0, 0, uint8_t(bx::EncodingType::Unorm) }, // ASTC6x6
{ 4, 8, 5, 16, 1, 1, 0, 0, 0, 0, 0, 0, uint8_t(bx::EncodingType::Unorm) }, // ASTC8x5
{ 3, 8, 6, 16, 1, 1, 0, 0, 0, 0, 0, 0, uint8_t(bx::EncodingType::Unorm) }, // ASTC8x6
{ 3, 10, 5, 16, 1, 1, 0, 0, 0, 0, 0, 0, uint8_t(bx::EncodingType::Unorm) }, // ASTC10x5
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, uint8_t(bx::EncodingType::Count) }, // Unknown
{ 1, 8, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, uint8_t(bx::EncodingType::Unorm) }, // R1
{ 8, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 8, uint8_t(bx::EncodingType::Unorm) }, // A8
@@ -128,15 +128,15 @@ namespace bimg
"PTC14A", // PTC14A
"PTC22", // PTC22
"PTC24", // PTC24
"ATC", // ATC
"ATCE", // ATCE
"ATCI", // ATCI
"ASTC4x4", // ASTC4x4
"ASTC5x5", // ASTC5x5
"ASTC6x6", // ASTC6x6
"ASTC8x5", // ASTC8x5
"ASTC8x6", // ASTC8x6
"ASTC10x5", // ASTC10x5
"ATC", // ATC
"ATCE", // ATCE
"ATCI", // ATCI
"ASTC4x4", // ASTC4x4
"ASTC5x5", // ASTC5x5
"ASTC6x6", // ASTC6x6
"ASTC8x5", // ASTC8x5
"ASTC8x6", // ASTC8x6
"ASTC10x5", // ASTC10x5
"<unknown>", // Unknown
"R1", // R1
"A8", // A8
@@ -276,9 +276,9 @@ namespace bimg
const uint16_t minBlockX = blockInfo.minBlockX;
const uint16_t minBlockY = blockInfo.minBlockY;
_width = bx::uint16_max(blockWidth * minBlockX, ( (_width + blockWidth - 1) / blockWidth )*blockWidth);
_height = bx::uint16_max(blockHeight * minBlockY, ( (_height + blockHeight - 1) / blockHeight)*blockHeight);
_depth = bx::uint16_max(1, _depth);
_width = bx::max<uint16_t>(blockWidth * minBlockX, ( (_width + blockWidth - 1) / blockWidth )*blockWidth);
_height = bx::max<uint16_t>(blockHeight * minBlockY, ( (_height + blockHeight - 1) / blockHeight)*blockHeight);
_depth = bx::max<uint16_t>(1, _depth);
uint8_t numMips = calcNumMips(true, _width, _height, _depth);
@@ -289,12 +289,15 @@ namespace bimg
{
const ImageBlockInfo& blockInfo = getBlockInfo(_format);
const uint8_t bpp = blockInfo.bitsPerPixel;
const uint16_t blockSize = blockInfo.blockSize;
const uint16_t blockWidth = blockInfo.blockWidth;
const uint16_t blockHeight = blockInfo.blockHeight;
const uint16_t minBlockX = blockInfo.minBlockX;
const uint16_t minBlockY = blockInfo.minBlockY;
const uint8_t blockSize = blockInfo.blockSize;
_width = bx::max<uint16_t>(blockWidth * minBlockX, ( (_width + blockWidth - 1) / blockWidth)*blockWidth);
_height = bx::max<uint16_t>(blockHeight * minBlockY, ( (_height + blockHeight - 1) / blockHeight)*blockHeight);
_depth = bx::max<uint16_t>(1, _depth);
const uint8_t numMips = calcNumMips(_hasMips, _width, _height, _depth);
const uint32_t sides = _cubeMap ? 6 : 1;
@@ -303,22 +306,18 @@ namespace bimg
uint32_t depth = _depth;
uint32_t size = 0;
if (_format != TextureFormat::Unknown)
{
for (uint32_t lod = 0; lod < numMips; ++lod)
{
depth = bx::uint32_max(1, depth);
for (uint32_t lod = 0; lod < numMips; ++lod)
{
width = bx::max<uint32_t>(blockWidth * minBlockX, ( (width + blockWidth - 1) / blockWidth )*blockWidth);
height = bx::max<uint32_t>(blockHeight * minBlockY, ( (height + blockHeight - 1) / blockHeight)*blockHeight);
depth = bx::max<uint32_t>(1, depth);
uint16_t blocksX = bx::uint32_max(minBlockX, ((width + blockWidth - 1) / blockWidth ));
uint16_t blocksY = bx::uint32_max(minBlockY, ((height + blockHeight - 1) / blockHeight));
size += uint32_t(uint64_t(width/blockWidth * height/blockHeight * depth)*blockSize * sides);
size += blocksX * blocksY * blockSize * depth * sides;
width >>= 1;
height >>= 1;
depth >>= 1;
}
}
width >>= 1;
height >>= 1;
depth >>= 1;
}
size *= _numLayers;
@@ -338,7 +337,7 @@ namespace bimg
return size;
}
void imageSolid(void* _dst, uint32_t _width, uint32_t _height, uint32_t _solid)
void imageSolid(void* _dst, uint32_t _width, uint32_t _height, uint32_t _solid)
{
uint32_t* dst = (uint32_t*)_dst;
for (uint32_t ii = 0, num = _width*_height; ii < num; ++ii)
@@ -711,6 +710,136 @@ namespace bimg
imageRgba32fLinearDownsample2x2Ref(_dst, _width, _height, _depth, _srcPitch, _src);
}
void imageRgba32fDownsample2x2Ref(void* _dst, uint32_t _width, uint32_t _height, uint32_t _depth, uint32_t _srcPitch, const void* _src)
{
const uint32_t dstWidth = _width/2;
const uint32_t dstHeight = _height/2;
const uint32_t dstDepth = _depth/2;
if (0 == dstWidth
|| 0 == dstHeight)
{
return;
}
const uint8_t* src = (const uint8_t*)_src;
uint8_t* dst = (uint8_t*)_dst;
if (0 == dstDepth)
{
for (uint32_t yy = 0, ystep = _srcPitch*2; yy < dstHeight; ++yy, src += ystep)
{
const float* rgba0 = (const float*)&src[0];
const float* rgba1 = (const float*)&src[_srcPitch];
for (uint32_t xx = 0; xx < dstWidth; ++xx, rgba0 += 8, rgba1 += 8, dst += 16)
{
float xyz[4];
xyz[0] = bx::toLinear(rgba0[0]);
xyz[1] = bx::toLinear(rgba0[1]);
xyz[2] = bx::toLinear(rgba0[2]);
xyz[3] = rgba0[3];
xyz[0] += bx::toLinear(rgba0[4]);
xyz[1] += bx::toLinear(rgba0[5]);
xyz[2] += bx::toLinear(rgba0[6]);
xyz[3] += rgba0[7];
xyz[0] += bx::toLinear(rgba1[0]);
xyz[1] += bx::toLinear(rgba1[1]);
xyz[2] += bx::toLinear(rgba1[2]);
xyz[3] += rgba1[3];
xyz[0] += bx::toLinear(rgba1[4]);
xyz[1] += bx::toLinear(rgba1[5]);
xyz[2] += bx::toLinear(rgba1[6]);
xyz[3] += rgba1[7];
xyz[0] = bx::toGamma(xyz[0]/4.0f);
xyz[1] = bx::toGamma(xyz[1]/4.0f);
xyz[2] = bx::toGamma(xyz[2]/4.0f);
xyz[3] = xyz[3]/4.0f;
bx::packRgba32F(dst, xyz);
}
}
}
else
{
const uint32_t slicePitch = _srcPitch*_height;
for (uint32_t zz = 0; zz < dstDepth; ++zz, src += slicePitch)
{
for (uint32_t yy = 0, ystep = _srcPitch*2; yy < dstHeight; ++yy, src += ystep)
{
const float* rgba0 = (const float*)&src[0];
const float* rgba1 = (const float*)&src[_srcPitch];
const float* rgba2 = (const float*)&src[slicePitch];
const float* rgba3 = (const float*)&src[slicePitch+_srcPitch];
for (uint32_t xx = 0
; xx < dstWidth
; ++xx, rgba0 += 8, rgba1 += 8, rgba2 += 8, rgba3 += 8, dst += 16
)
{
float xyz[4];
xyz[0] = bx::toLinear(rgba0[0]);
xyz[1] = bx::toLinear(rgba0[1]);
xyz[2] = bx::toLinear(rgba0[2]);
xyz[3] = rgba0[3];
xyz[0] += bx::toLinear(rgba0[4]);
xyz[1] += bx::toLinear(rgba0[5]);
xyz[2] += bx::toLinear(rgba0[6]);
xyz[3] += rgba0[7];
xyz[0] += bx::toLinear(rgba1[0]);
xyz[1] += bx::toLinear(rgba1[1]);
xyz[2] += bx::toLinear(rgba1[2]);
xyz[3] += rgba1[3];
xyz[0] += bx::toLinear(rgba1[4]);
xyz[1] += bx::toLinear(rgba1[5]);
xyz[2] += bx::toLinear(rgba1[6]);
xyz[3] += rgba1[7];
xyz[0] += bx::toLinear(rgba2[0]);
xyz[1] += bx::toLinear(rgba2[1]);
xyz[2] += bx::toLinear(rgba2[2]);
xyz[3] += rgba2[3];
xyz[0] += bx::toLinear(rgba2[4]);
xyz[1] += bx::toLinear(rgba2[5]);
xyz[2] += bx::toLinear(rgba2[6]);
xyz[3] += rgba2[7];
xyz[0] += bx::toLinear(rgba3[0]);
xyz[1] += bx::toLinear(rgba3[1]);
xyz[2] += bx::toLinear(rgba3[2]);
xyz[3] += rgba3[3];
xyz[0] += bx::toLinear(rgba3[4]);
xyz[1] += bx::toLinear(rgba3[5]);
xyz[2] += bx::toLinear(rgba3[6]);
xyz[3] += rgba3[7];
xyz[0] = bx::toGamma(xyz[0]/8.0f);
xyz[1] = bx::toGamma(xyz[1]/8.0f);
xyz[2] = bx::toGamma(xyz[2]/8.0f);
xyz[3] = xyz[3]/8.0f;
bx::packRgba32F(dst, xyz);
}
}
}
}
}
void imageRgba32fDownsample2x2(void* _dst, uint32_t _width, uint32_t _height, uint32_t _depth, uint32_t _srcPitch, const void* _src)
{
imageRgba32fDownsample2x2Ref(_dst, _width, _height, _depth, _srcPitch, _src);
}
void imageRgba32fDownsample2x2NormalMapRef(void* _dst, uint32_t _width, uint32_t _height, uint32_t _srcPitch, uint32_t _dstPitch, const void* _src)
{
const uint32_t dstWidth = _width/2;
@@ -872,15 +1001,15 @@ namespace bimg
{ NULL, NULL }, // PTC14A
{ NULL, NULL }, // PTC22
{ NULL, NULL }, // PTC24
{ NULL, NULL }, // ATC
{ NULL, NULL }, // ATCE
{ NULL, NULL }, // ATCI
{ NULL, NULL }, // ASTC4x4
{ NULL, NULL }, // ASTC5x5
{ NULL, NULL }, // ASTC6x6
{ NULL, NULL }, // ASTC8x5
{ NULL, NULL }, // ASTC8x6
{ NULL, NULL }, // ASTC10x5
{ NULL, NULL }, // ATC
{ NULL, NULL }, // ATCE
{ NULL, NULL }, // ATCI
{ NULL, NULL }, // ASTC4x4
{ NULL, NULL }, // ASTC5x5
{ NULL, NULL }, // ASTC6x6
{ NULL, NULL }, // ASTC8x5
{ NULL, NULL }, // ASTC8x6
{ NULL, NULL }, // ASTC10x5
{ NULL, NULL }, // Unknown
{ NULL, NULL }, // R1
{ bx::packR8, bx::unpackR8 }, // A8
@@ -1039,7 +1168,7 @@ namespace bimg
if (_dstFormat == _srcFormat)
{
bx::memCopy(_dst, _src, _width*_height*_depth*srcBpp/8);
bx::memCopy(_dst, _src, _width*_height*_depth*(srcBpp/8) );
return true;
}
@@ -2267,61 +2396,61 @@ namespace bimg
}
}
// BC6H, BC7
// ATC
//
void decodeBlockATC(uint8_t _dst[16*4], const uint8_t _src[8])
{
uint8_t colors[4*4]; // You can see from comparison with decodeBlockDXT just how little sense the ATI patent-avoiding(?) modification makes
void decodeBlockATC(uint8_t _dst[16*4], const uint8_t _src[8])
{
uint8_t colors[4*4];
uint32_t c0 = _src[0] | (_src[1] << 8);
uint32_t c1 = _src[2] | (_src[3] << 8);
uint32_t c0 = _src[0] | (_src[1] << 8);
uint32_t c1 = _src[2] | (_src[3] << 8);
if ((c0 & 0x8000) == 0)
{
colors[0] = bitRangeConvert( (c0>> 0)&0x1f, 5, 8);
colors[1] = bitRangeConvert( (c0>> 5)&0x1f, 5, 8);
colors[2] = bitRangeConvert( (c0>>10)&0x1f, 5, 8);
if (0 == (c0 & 0x8000) )
{
colors[ 0] = bitRangeConvert( (c0>> 0)&0x1f, 5, 8);
colors[ 1] = bitRangeConvert( (c0>> 5)&0x1f, 5, 8);
colors[ 2] = bitRangeConvert( (c0>>10)&0x1f, 5, 8);
colors[12] = bitRangeConvert( (c1>> 0)&0x1f, 5, 8);
colors[13] = bitRangeConvert( (c1>> 5)&0x3f, 6, 8);
colors[14] = bitRangeConvert( (c1>>11)&0x1f, 5, 8);
colors[12] = bitRangeConvert( (c1>> 0)&0x1f, 5, 8);
colors[13] = bitRangeConvert( (c1>> 5)&0x3f, 6, 8);
colors[14] = bitRangeConvert( (c1>>11)&0x1f, 5, 8);
colors[ 4] = (2 * colors[0] + colors[12]) / 3;
colors[ 5] = (2 * colors[1] + colors[13]) / 3;
colors[ 6] = (2 * colors[2] + colors[14]) / 3;
colors[ 4] = (2 * colors[0] + colors[12]) / 3;
colors[ 5] = (2 * colors[1] + colors[13]) / 3;
colors[ 6] = (2 * colors[2] + colors[14]) / 3;
colors[ 8] = (colors[0] + 2 * colors[12]) / 3;
colors[ 9] = (colors[1] + 2 * colors[13]) / 3;
colors[10] = (colors[2] + 2 * colors[14]) / 3;
}
else
{
colors[ 0] = 0;
colors[ 1] = 0;
colors[ 2] = 0;
colors[ 8] = (colors[0] + 2 * colors[12]) / 3;
colors[ 9] = (colors[1] + 2 * colors[13]) / 3;
colors[10] = (colors[2] + 2 * colors[14]) / 3;
}
else
{
colors[ 0] = 0;
colors[ 1] = 0;
colors[ 2] = 0;
colors[ 8] = bitRangeConvert( (c0>> 0)&0x1f, 5, 8);
colors[ 9] = bitRangeConvert( (c0>> 5)&0x1f, 5, 8);
colors[10] = bitRangeConvert( (c0>>10)&0x1f, 5, 8);
colors[ 8] = bitRangeConvert( (c0>> 0)&0x1f, 5, 8);
colors[ 9] = bitRangeConvert( (c0>> 5)&0x1f, 5, 8);
colors[10] = bitRangeConvert( (c0>>10)&0x1f, 5, 8);
colors[12] = bitRangeConvert( (c1>> 0)&0x1f, 5, 8);
colors[13] = bitRangeConvert( (c1>> 5)&0x3f, 6, 8);
colors[14] = bitRangeConvert( (c1>>11)&0x1f, 5, 8);
colors[12] = bitRangeConvert( (c1>> 0)&0x1f, 5, 8);
colors[13] = bitRangeConvert( (c1>> 5)&0x3f, 6, 8);
colors[14] = bitRangeConvert( (c1>>11)&0x1f, 5, 8);
colors[ 4] = colors[ 8] - colors[12] / 4;
colors[ 5] = colors[ 9] - colors[13] / 4;
colors[ 6] = colors[10] - colors[14] / 4;
}
colors[ 4] = colors[ 8] - colors[12] / 4;
colors[ 5] = colors[ 9] - colors[13] / 4;
colors[ 6] = colors[10] - colors[14] / 4;
}
for (uint32_t ii = 0, next = 8*4; ii < 16*4; ii += 4, next += 2)
{
int idx = ( (_src[next>>3] >> (next & 7) ) & 3) * 4;
_dst[ii+0] = colors[idx+0];
_dst[ii+1] = colors[idx+1];
_dst[ii+2] = colors[idx+2];
_dst[ii+3] = colors[idx+3];
}
}
for (uint32_t ii = 0, next = 8*4; ii < 16*4; ii += 4, next += 2)
{
int32_t idx = ( (_src[next>>3] >> (next & 7) ) & 3) * 4;
_dst[ii+0] = colors[idx+0];
_dst[ii+1] = colors[idx+1];
_dst[ii+2] = colors[idx+2];
_dst[ii+3] = colors[idx+3];
}
}
static const int32_t s_etc1Mod[8][4] =
{
@@ -2968,10 +3097,10 @@ namespace bimg
const uint16_t minBlockX = blockInfo.minBlockX;
const uint16_t minBlockY = blockInfo.minBlockY;
_width = bx::uint16_max(blockWidth * minBlockX, ( (_width + blockWidth - 1) / blockWidth)*blockWidth);
_height = bx::uint16_max(blockHeight * minBlockY, ( (_height + blockHeight - 1) / blockHeight)*blockHeight);
_depth = bx::uint16_max(1, _depth);
_numLayers = bx::uint16_max(1, _numLayers);
_width = bx::max<uint16_t>(blockWidth * minBlockX, ( (_width + blockWidth - 1) / blockWidth)*blockWidth);
_height = bx::max<uint16_t>(blockHeight * minBlockY, ( (_height + blockHeight - 1) / blockHeight)*blockHeight);
_depth = bx::max<uint16_t>(1, _depth);
_numLayers = bx::max<uint16_t>(1, _numLayers);
const uint8_t numMips = _hasMips ? imageGetNumMips(_format, _width, _height, _depth) : 1;
uint32_t size = imageGetSize(NULL, _width, _height, _depth, _cubeMap, _hasMips, _numLayers, _format);
@@ -3617,15 +3746,15 @@ namespace bimg
{ KTX_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, KTX_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT, KTX_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, KTX_ZERO, }, // PTC14A
{ KTX_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG, KTX_ZERO, KTX_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG, KTX_ZERO, }, // PTC22
{ KTX_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG, KTX_ZERO, KTX_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG, KTX_ZERO, }, // PTC24
{ KTX_ATC_RGB_AMD, KTX_ZERO, KTX_ATC_RGB_AMD, KTX_ZERO, }, // ATC
{ KTX_ATC_RGBA_EXPLICIT_ALPHA_AMD, KTX_ZERO, KTX_ATC_RGBA_EXPLICIT_ALPHA_AMD, KTX_ZERO, }, // ATCE
{ KTX_ATC_RGBA_INTERPOLATED_ALPHA_AMD, KTX_ZERO, KTX_ATC_RGBA_INTERPOLATED_ALPHA_AMD, KTX_ZERO, }, // ATCI
{ KTX_COMPRESSED_RGBA_ASTC_4x4_KHR, KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR, KTX_COMPRESSED_RGBA_ASTC_4x4_KHR, KTX_ZERO, }, // ASTC4x4
{ KTX_COMPRESSED_RGBA_ASTC_5x5_KHR, KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR, KTX_COMPRESSED_RGBA_ASTC_5x5_KHR, KTX_ZERO, }, // ASTC5x5
{ KTX_COMPRESSED_RGBA_ASTC_6x6_KHR, KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR, KTX_COMPRESSED_RGBA_ASTC_6x6_KHR, KTX_ZERO, }, // ASTC6x6
{ KTX_COMPRESSED_RGBA_ASTC_8x5_KHR, KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR, KTX_COMPRESSED_RGBA_ASTC_8x5_KHR, KTX_ZERO, }, // ASTC8x5
{ KTX_COMPRESSED_RGBA_ASTC_8x6_KHR, KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR, KTX_COMPRESSED_RGBA_ASTC_8x6_KHR, KTX_ZERO, }, // ASTC8x6
{ KTX_COMPRESSED_RGBA_ASTC_10x5_KHR, KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR, KTX_COMPRESSED_RGBA_ASTC_10x5_KHR, KTX_ZERO, }, // ASTC10x5
{ KTX_ATC_RGB_AMD, KTX_ZERO, KTX_ATC_RGB_AMD, KTX_ZERO, }, // ATC
{ KTX_ATC_RGBA_EXPLICIT_ALPHA_AMD, KTX_ZERO, KTX_ATC_RGBA_EXPLICIT_ALPHA_AMD, KTX_ZERO, }, // ATCE
{ KTX_ATC_RGBA_INTERPOLATED_ALPHA_AMD, KTX_ZERO, KTX_ATC_RGBA_INTERPOLATED_ALPHA_AMD, KTX_ZERO, }, // ATCI
{ KTX_COMPRESSED_RGBA_ASTC_4x4_KHR, KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR, KTX_COMPRESSED_RGBA_ASTC_4x4_KHR, KTX_ZERO, }, // ASTC4x4
{ KTX_COMPRESSED_RGBA_ASTC_5x5_KHR, KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR, KTX_COMPRESSED_RGBA_ASTC_5x5_KHR, KTX_ZERO, }, // ASTC5x5
{ KTX_COMPRESSED_RGBA_ASTC_6x6_KHR, KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR, KTX_COMPRESSED_RGBA_ASTC_6x6_KHR, KTX_ZERO, }, // ASTC6x6
{ KTX_COMPRESSED_RGBA_ASTC_8x5_KHR, KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR, KTX_COMPRESSED_RGBA_ASTC_8x5_KHR, KTX_ZERO, }, // ASTC8x5
{ KTX_COMPRESSED_RGBA_ASTC_8x6_KHR, KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR, KTX_COMPRESSED_RGBA_ASTC_8x6_KHR, KTX_ZERO, }, // ASTC8x6
{ KTX_COMPRESSED_RGBA_ASTC_10x5_KHR, KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR, KTX_COMPRESSED_RGBA_ASTC_10x5_KHR, KTX_ZERO, }, // ASTC10x5
{ KTX_ZERO, KTX_ZERO, KTX_ZERO, KTX_ZERO, }, // Unknown
{ KTX_ZERO, KTX_ZERO, KTX_ZERO, KTX_ZERO, }, // R1
{ KTX_ALPHA, KTX_ZERO, KTX_ALPHA, KTX_UNSIGNED_BYTE, }, // A8
@@ -3784,8 +3913,8 @@ namespace bimg
_imageContainer.m_depth = depth;
_imageContainer.m_format = format;
_imageContainer.m_orientation = Orientation::R0;
_imageContainer.m_numLayers = uint16_t(bx::uint32_max(numberOfArrayElements, 1) );
_imageContainer.m_numMips = uint8_t(bx::uint32_max(numMips, 1) );
_imageContainer.m_numLayers = uint16_t(bx::max<uint32_t>(numberOfArrayElements, 1) );
_imageContainer.m_numMips = uint8_t(bx::max<uint32_t>(numMips, 1) );
_imageContainer.m_hasAlpha = hasAlpha;
_imageContainer.m_cubeMap = numFaces > 1;
_imageContainer.m_ktx = true;
@@ -3950,7 +4079,7 @@ namespace bimg
_imageContainer.m_format = format;
_imageContainer.m_orientation = Orientation::R0;
_imageContainer.m_numLayers = 1;
_imageContainer.m_numMips = uint8_t(bx::uint32_max(numMips, 1) );
_imageContainer.m_numMips = uint8_t(bx::max<uint32_t>(numMips, 1) );
_imageContainer.m_hasAlpha = hasAlpha;
_imageContainer.m_cubeMap = numFaces > 1;
_imageContainer.m_ktx = false;
@@ -4605,28 +4734,35 @@ namespace bimg
for (uint8_t lod = 0, num = _imageContainer.m_numMips; lod < num; ++lod)
{
uint32_t sourceSize = bx::toHostEndian(*(const uint32_t*)&data[offset], _imageContainer.m_ktxLE);
width = bx::max<uint32_t>(blockWidth * minBlockX, ( (width + blockWidth - 1) / blockWidth )*blockWidth);
height = bx::max<uint32_t>(blockHeight * minBlockY, ( (height + blockHeight - 1) / blockHeight)*blockHeight);
depth = bx::max<uint32_t>(1, depth);
const uint32_t mipSize = width/blockWidth * height/blockHeight * depth * blockSize;
if (mipSize != width*height*depth*bpp/8)
{
BX_TRACE("x");
}
const uint32_t size = mipSize*numSides;
uint32_t imageSize = bx::toHostEndian(*(const uint32_t*)&data[offset], _imageContainer.m_ktxLE);
BX_CHECK(size == imageSize, "KTX: Image size mismatch %d (expected %d).", size, imageSize);
BX_UNUSED(size, imageSize);
offset += sizeof(uint32_t);
depth = bx::uint32_max(1, depth);
uint32_t blocksX = bx::uint32_max(minBlockX, ((width + blockWidth - 1) / blockWidth ));
uint32_t blocksY = bx::uint32_max(minBlockY, ((height + blockHeight - 1) / blockHeight));
uint32_t destSize = blocksX * blocksY * blockSize * depth;
BX_CHECK(sourceSize == destSize, "KTX: Image size mismatch %d (expected %d).", sourceSize, destSize);
for (uint16_t side = 0; side < numSides; ++side)
{
BX_CHECK(offset <= _size, "Reading past size of data buffer! (offset %d, size %d)", offset, _size);
if (side == _side
&& lod == _lod)
{
_mip.m_width = blocksX * blockWidth;
_mip.m_height = blocksY * blockHeight;
_mip.m_width = width;
_mip.m_height = height;
_mip.m_depth = depth;
_mip.m_blockSize = blockSize;
_mip.m_size = destSize;
_mip.m_size = mipSize;
_mip.m_data = &data[offset];
_mip.m_bpp = bpp;
_mip.m_format = format;
@@ -4634,9 +4770,8 @@ namespace bimg
return true;
}
offset += sourceSize;
offset += mipSize;
BX_CHECK(offset <= _size, "Reading past size of data buffer! (offset %d, size %d)", offset, _size);
BX_UNUSED(_size);
}
@@ -4655,21 +4790,22 @@ namespace bimg
for (uint8_t lod = 0, num = _imageContainer.m_numMips; lod < num; ++lod)
{
depth = bx::uint32_max(1, depth);
BX_CHECK(offset <= _size, "Reading past size of data buffer! (offset %d, size %d)", offset, _size);
uint32_t blocksX = bx::uint32_max(minBlockX, ((width + blockWidth - 1) / blockWidth ));
uint32_t blocksY = bx::uint32_max(minBlockY, ((height + blockHeight - 1) / blockHeight));
width = bx::max<uint32_t>(blockWidth * minBlockX, ( (width + blockWidth - 1) / blockWidth )*blockWidth);
height = bx::max<uint32_t>(blockHeight * minBlockY, ( (height + blockHeight - 1) / blockHeight)*blockHeight);
depth = bx::max<uint32_t>(1, depth);
uint32_t size = blocksX * blocksY * blockSize * depth;
uint32_t mipSize = width/blockWidth * height/blockHeight * depth * blockSize;
if (side == _side
&& lod == _lod)
{
_mip.m_width = blocksX * blockWidth;
_mip.m_height = blocksY * blockHeight;
_mip.m_width = width;
_mip.m_height = height;
_mip.m_depth = depth;
_mip.m_blockSize = blockSize;
_mip.m_size = size;
_mip.m_size = mipSize;
_mip.m_data = &data[offset];
_mip.m_bpp = bpp;
_mip.m_format = format;
@@ -4677,9 +4813,8 @@ namespace bimg
return true;
}
offset += size;
offset += mipSize;
BX_CHECK(offset <= _size, "Reading past size of data buffer! (offset %d, size %d)", offset, _size);
BX_UNUSED(_size);
width >>= 1;
@@ -4891,13 +5026,15 @@ namespace bimg
total += bx::writeLE(_writer, uint32_t(18*4+1), _err);
const uint8_t cdata[] = { 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 };
total += bx::write(_writer, 'R', _err);
total += bx::write(_writer, cdata, BX_COUNTOF(cdata), _err);
total += bx::write(_writer, 'G', _err);
// Order is always ABGR order because Photoshop and GIMP ignore these fields and
// assume it's in ABGR order.
total += bx::write(_writer, 'A', _err);
total += bx::write(_writer, cdata, BX_COUNTOF(cdata), _err);
total += bx::write(_writer, 'B', _err);
total += bx::write(_writer, cdata, BX_COUNTOF(cdata), _err);
total += bx::write(_writer, 'A', _err);
total += bx::write(_writer, 'G', _err);
total += bx::write(_writer, cdata, BX_COUNTOF(cdata), _err);
total += bx::write(_writer, 'R', _err);
total += bx::write(_writer, cdata, BX_COUNTOF(cdata), _err);
total += bx::write(_writer, '\0', _err);
@@ -4973,12 +5110,7 @@ namespace bimg
for (uint32_t xx = 0; xx < _width && _err->isOk(); ++xx)
{
total += bx::write(_writer, &data[xx*bpp/8+0*bytesPerChannel], bytesPerChannel, _err);
}
for (uint32_t xx = 0; xx < _width && _err->isOk(); ++xx)
{
total += bx::write(_writer, &data[xx*bpp/8+1*bytesPerChannel], bytesPerChannel, _err);
total += bx::write(_writer, &data[xx*bpp/8+3*bytesPerChannel], bytesPerChannel, _err);
}
for (uint32_t xx = 0; xx < _width && _err->isOk(); ++xx)
@@ -4988,7 +5120,53 @@ namespace bimg
for (uint32_t xx = 0; xx < _width && _err->isOk(); ++xx)
{
total += bx::write(_writer, &data[xx*bpp/8+3*bytesPerChannel], bytesPerChannel, _err);
total += bx::write(_writer, &data[xx*bpp/8+1*bytesPerChannel], bytesPerChannel, _err);
}
for (uint32_t xx = 0; xx < _width && _err->isOk(); ++xx)
{
total += bx::write(_writer, &data[xx*bpp/8+0*bytesPerChannel], bytesPerChannel, _err);
}
data += _srcPitch;
}
return total;
}
int32_t imageWriteHdr(bx::WriterI* _writer, uint32_t _width, uint32_t _height, uint32_t _srcPitch, const void* _src, TextureFormat::Enum _format, bool _yflip, bx::Error* _err)
{
BX_ERROR_SCOPE(_err);
int32_t total = 0;
total += bx::write(_writer, "#?RADIANCE\n" , _err);
total += bx::write(_writer, "FORMAT=32-bit_rle_rgbe\n" , _err);
total += bx::write(_writer, '\n' , _err);
total += bx::writePrintf(_writer, "%cY %d +X %d\n", _yflip ? '+' : '-', _height, _width);
UnpackFn unpack = getUnpack(_format);
const uint32_t bpp = getBitsPerPixel(_format);
const uint8_t* data = (const uint8_t*)_src;
for (uint32_t yy = 0; yy < _height && _err->isOk(); ++yy)
{
for (uint32_t xx = 0; xx < _width && _err->isOk(); ++xx)
{
float rgba[4];
unpack(rgba, &data[xx*bpp/8]);
const float maxVal = bx::max(rgba[0], rgba[1], rgba[2]);
const float exp = bx::ceil(bx::log2(maxVal) );
const float toRgb8 = 255.0f * 1.0f/bx::ldexp(1.0f, int(exp) );
uint8_t rgbe[4];
rgbe[0] = uint8_t(rgba[0] * toRgb8);
rgbe[1] = uint8_t(rgba[1] * toRgb8);
rgbe[2] = uint8_t(rgba[2] * toRgb8);
rgbe[3] = uint8_t(exp+128.0f);
total += bx::write(_writer, rgbe, 4, _err);
}
data += _srcPitch;
@@ -5191,15 +5369,15 @@ namespace bimg
}
const ImageBlockInfo& blockInfo = s_imageBlockInfo[_format];
const uint8_t bpp = blockInfo.bitsPerPixel;
const uint32_t blockWidth = blockInfo.blockWidth;
const uint32_t blockHeight = blockInfo.blockHeight;
const uint32_t minBlockX = blockInfo.minBlockX;
const uint32_t minBlockY = blockInfo.minBlockY;
const uint8_t blockSize = blockInfo.blockSize;
const uint8_t* src = (const uint8_t*)_src;
const uint32_t numLayers = bx::uint32_max(_numLayers, 1);
const uint32_t numLayers = bx::max<uint32_t>(_numLayers, 1);
const uint32_t numSides = _cubeMap ? 6 : 1;
uint32_t width = _width;
@@ -5208,12 +5386,12 @@ namespace bimg
for (uint8_t lod = 0; lod < _numMips && _err->isOk(); ++lod)
{
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);
width = bx::max<uint32_t>(blockWidth * minBlockX, ( (width + blockWidth - 1) / blockWidth )*blockWidth);
height = bx::max<uint32_t>(blockHeight * minBlockY, ( (height + blockHeight - 1) / blockHeight)*blockHeight);
depth = bx::max<uint32_t>(1, depth);
const uint32_t mipSize = width*height*depth*bpp/8;
const uint32_t size = mipSize*numLayers*numSides;
const uint32_t mipSize = width/blockWidth * height/blockHeight * depth * blockSize;
const uint32_t size = mipSize * numLayers * numSides;
total += bx::write(_writer, size, _err);
for (uint32_t layer = 0; layer < numLayers && _err->isOk(); ++layer)
@@ -5255,7 +5433,7 @@ namespace bimg
}
const uint32_t numMips = _imageContainer.m_numMips;
const uint32_t numLayers = bx::uint32_max(_imageContainer.m_numLayers, 1);
const uint32_t numLayers = bx::max<uint32_t>(_imageContainer.m_numLayers, 1);
const uint32_t numSides = _imageContainer.m_cubeMap ? 6 : 1;
for (uint8_t lod = 0; lod < numMips && _err->isOk(); ++lod)
@@ -5281,185 +5459,4 @@ namespace bimg
return total;
}
// +----------+
// |-z 2|
// | ^ +y |
// | | |
// | +---->+x |
// +----------+----------+----------+----------+
// |+y 1|+y 4|+y 0|+y 5|
// | ^ -x | ^ +z | ^ +x | ^ -z |
// | | | | | | | | |
// | +---->+z | +---->+x | +---->-z | +---->-x |
// +----------+----------+----------+----------+
// |+z 3|
// | ^ -y |
// | | |
// | +---->+x |
// +----------+
//
struct CubeMapFace
{
float uv[3][3];
};
static const CubeMapFace s_cubeMapFace[] =
{
{{ // +x face
{ 0.0f, 0.0f, -1.0f }, // u -> -z
{ 0.0f, -1.0f, 0.0f }, // v -> -y
{ 1.0f, 0.0f, 0.0f }, // +x face
}},
{{ // -x face
{ 0.0f, 0.0f, 1.0f }, // u -> +z
{ 0.0f, -1.0f, 0.0f }, // v -> -y
{ -1.0f, 0.0f, 0.0f }, // -x face
}},
{{ // +y face
{ 1.0f, 0.0f, 0.0f }, // u -> +x
{ 0.0f, 0.0f, 1.0f }, // v -> +z
{ 0.0f, 1.0f, 0.0f }, // +y face
}},
{{ // -y face
{ 1.0f, 0.0f, 0.0f }, // u -> +x
{ 0.0f, 0.0f, -1.0f }, // v -> -z
{ 0.0f, -1.0f, 0.0f }, // -y face
}},
{{ // +z face
{ 1.0f, 0.0f, 0.0f }, // u -> +x
{ 0.0f, -1.0f, 0.0f }, // v -> -y
{ 0.0f, 0.0f, 1.0f }, // +z face
}},
{{ // -z face
{ -1.0f, 0.0f, 0.0f }, // u -> -x
{ 0.0f, -1.0f, 0.0f }, // v -> -y
{ 0.0f, 0.0f, -1.0f }, // -z face
}},
};
/// _u and _v should be center addressing and in [-1.0+invSize..1.0-invSize] range.
void texelUvToDir(float* _result, uint8_t _side, float _u, float _v)
{
const CubeMapFace& face = s_cubeMapFace[_side];
float tmp[3];
tmp[0] = face.uv[0][0] * _u + face.uv[1][0] * _v + face.uv[2][0];
tmp[1] = face.uv[0][1] * _u + face.uv[1][1] * _v + face.uv[2][1];
tmp[2] = face.uv[0][2] * _u + face.uv[1][2] * _v + face.uv[2][2];
bx::vec3Norm(_result, tmp);
}
ImageContainer* imageCubemapFromLatLongRgba32F(bx::AllocatorI* _allocator, const ImageContainer& _input, bool _useBilinearInterpolation, bx::Error* _err)
{
BX_ERROR_SCOPE(_err);
if (_input.m_depth != 1
&& _input.m_numLayers != 1
&& _input.m_format != TextureFormat::RGBA32F
&& _input.m_width/2 != _input.m_height)
{
BX_ERROR_SET(_err, BIMG_ERROR, "Input image format is not equirectangular projection.");
return NULL;
}
const uint32_t srcWidthMinusOne = _input.m_width-1;
const uint32_t srcHeightMinusOne = _input.m_height-1;
const uint32_t srcPitch = _input.m_width*16;
const uint32_t dstWidth = _input.m_height/2;
const uint32_t dstPitch = dstWidth*16;
const float invDstWidth = 1.0f / float(dstWidth);
ImageContainer* output = imageAlloc(_allocator
, _input.m_format
, uint16_t(dstWidth)
, uint16_t(dstWidth)
, uint16_t(1)
, 1
, true
, false
);
const uint8_t* srcData = (const uint8_t*)_input.m_data;
for (uint8_t side = 0; side < 6 && _err->isOk(); ++side)
{
ImageMip mip;
imageGetRawData(*output, side, 0, output->m_data, output->m_size, mip);
for (uint32_t yy = 0; yy < dstWidth; ++yy)
{
for (uint32_t xx = 0; xx < dstWidth; ++xx)
{
float* dstData = (float*)&mip.m_data[yy*dstPitch+xx*16];
const float uu = 2.0f*xx*invDstWidth - 1.0f;
const float vv = 2.0f*yy*invDstWidth - 1.0f;
float dir[3];
texelUvToDir(dir, side, uu, vv);
float srcU, srcV;
bx::vec3ToLatLong(&srcU, &srcV, dir);
srcU *= srcWidthMinusOne;
srcV *= srcHeightMinusOne;
if (_useBilinearInterpolation)
{
const uint32_t x0 = uint32_t(srcU);
const uint32_t y0 = uint32_t(srcV);
const uint32_t x1 = bx::min(x0 + 1, srcWidthMinusOne);
const uint32_t y1 = bx::min(y0 + 1, srcHeightMinusOne);
const float* src0 = (const float*)&srcData[y0*srcPitch + x0*16];
const float* src1 = (const float*)&srcData[y0*srcPitch + x1*16];
const float* src2 = (const float*)&srcData[y1*srcPitch + x0*16];
const float* src3 = (const float*)&srcData[y1*srcPitch + x1*16];
const float tx = srcU - float(int32_t(x0) );
const float ty = srcV - float(int32_t(y0) );
const float omtx = 1.0f - tx;
const float omty = 1.0f - ty;
float p0[4];
bx::vec4Mul(p0, src0, omtx*omty);
float p1[4];
bx::vec4Mul(p1, src1, tx*omty);
float p2[4];
bx::vec4Mul(p2, src2, omtx*ty);
float p3[4];
bx::vec4Mul(p3, src3, tx*ty);
const float rr = p0[0] + p1[0] + p2[0] + p3[0];
const float gg = p0[1] + p1[1] + p2[1] + p3[1];
const float bb = p0[2] + p1[2] + p2[2] + p3[2];
const float aa = p0[3] + p1[3] + p2[3] + p3[3];
dstData[0] = rr;
dstData[1] = gg;
dstData[2] = bb;
dstData[3] = aa;
}
else
{
const uint32_t x0 = uint32_t(srcU);
const uint32_t y0 = uint32_t(srcV);
const float* src0 = (const float*)&srcData[y0*srcPitch + x0*16];
dstData[0] = src0[0];
dstData[1] = src0[1];
dstData[2] = src0[2];
dstData[3] = src0[3];
}
}
}
}
return output;
}
} // namespace bimg

1207
src/image_cubemap_filter.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -228,7 +228,10 @@ namespace bimg
break;
default:
BX_ERROR_SET(_err, BIMG_ERROR, "Unable to convert between input/output formats!");
if (!imageConvert(_allocator, _dst, _dstFormat, _src, _srcFormat, _width, _height, 1) )
{
BX_ERROR_SET(_err, BIMG_ERROR, "Unable to convert between input/output formats!");
}
break;
}
}
@@ -260,17 +263,18 @@ namespace bimg
imageGetRawData(*output, side, lod, output->m_data, output->m_size, dstMip);
uint8_t* dstData = const_cast<uint8_t*>(dstMip.m_data);
imageEncode(_allocator
, dstData
, mip.m_data
, mip.m_format
, mip.m_width
, mip.m_height
, mip.m_depth
, _dstFormat
, _quality
, &err
);
imageEncode(
_allocator
, dstData
, mip.m_data
, mip.m_format
, mip.m_width
, mip.m_height
, mip.m_depth
, _dstFormat
, _quality
, &err
);
}
}
}

View File

@@ -26,25 +26,12 @@
#include <string>
#define BIMG_TEXTUREC_VERSION_MAJOR 1
#define BIMG_TEXTUREC_VERSION_MINOR 15
#define BIMG_TEXTUREC_VERSION_MINOR 17
BX_ERROR_RESULT(TEXTRUREC_ERROR, BX_MAKEFOURCC('t', 'c', 0, 0) );
struct Options
{
Options()
: maxSize(UINT32_MAX)
, edge(0.0f)
, format(bimg::TextureFormat::Count)
, quality(bimg::Quality::Default)
, mips(false)
, normalMap(false)
, equirect(false)
, iqa(false)
, pma(false)
, sdf(false)
, alphaTest(false)
{
}
void dump()
{
DBG("Options:\n"
@@ -56,6 +43,9 @@ struct Options
"\t iqa: %s\n"
"\t pma: %s\n"
"\t sdf: %s\n"
"\t radiance: %s\n"
"\t equirect: %s\n"
"\t strip: %s\n"
, maxSize
, edge
, bimg::getName(format)
@@ -64,20 +54,25 @@ struct Options
, iqa ? "true" : "false"
, pma ? "true" : "false"
, sdf ? "true" : "false"
, radiance ? "true" : "false"
, equirect ? "true" : "false"
, strip ? "true" : "false"
);
}
uint32_t maxSize;
float edge;
bimg::TextureFormat::Enum format;
bimg::Quality::Enum quality;
bool mips;
bool normalMap;
bool equirect;
bool iqa;
bool pma;
bool sdf;
bool alphaTest;
uint32_t maxSize = UINT32_MAX;
float edge = 0.0f;
bimg::TextureFormat::Enum format = bimg::TextureFormat::Count;
bimg::Quality::Enum quality = bimg::Quality::Default;
bimg::LightingModel::Enum radiance = bimg::LightingModel::Count;
bool mips = false;
bool normalMap = false;
bool equirect = false;
bool strip = false;
bool iqa = false;
bool pma = false;
bool sdf = false;
bool alphaTest = false;
};
void imageRgba32fNormalize(void* _dst, uint32_t _width, uint32_t _height, uint32_t _srcPitch, const void* _src)
@@ -168,9 +163,47 @@ bimg::ImageContainer* convert(bx::AllocatorI* _allocator, const void* _inputData
uint32_t outputHeight = bx::uint32_max(blockHeight * minBlockY, ( (input->m_height + blockHeight - 1) / blockHeight)*blockHeight);
uint32_t outputDepth = input->m_depth;
if (outputWidth > _options.maxSize
|| outputHeight > _options.maxSize
|| outputDepth > _options.maxSize)
if (_options.equirect)
{
if (outputDepth == 1
&& outputWidth/2 == outputHeight)
{
if (outputWidth/2 > _options.maxSize)
{
outputWidth = _options.maxSize*4;
outputHeight = _options.maxSize*2;
}
}
else
{
bimg::imageFree(input);
BX_ERROR_SET(_err, TEXTRUREC_ERROR, "Input image format is not equirectangular projection.");
return NULL;
}
}
else if (_options.strip)
{
if (outputDepth == 1
&& outputWidth/6 == outputHeight)
{
if (outputWidth/6 > _options.maxSize)
{
outputWidth = _options.maxSize*6;
outputHeight = _options.maxSize;
}
}
else
{
bimg::imageFree(input);
BX_ERROR_SET(_err, TEXTRUREC_ERROR, "Input image format is not horizontal strip.");
return NULL;
}
}
else if (outputWidth > _options.maxSize
|| outputHeight > _options.maxSize
|| outputDepth > _options.maxSize)
{
if (outputDepth > outputWidth
&& outputDepth > outputHeight)
@@ -204,9 +237,10 @@ bimg::ImageContainer* convert(bx::AllocatorI* _allocator, const void* _inputData
&& !_options.sdf
&& !_options.alphaTest
&& !_options.normalMap
&& !_options.equirect
&& !(_options.equirect || _options.strip)
&& !_options.iqa
&& !_options.pma
&& (bimg::LightingModel::Count == _options.radiance)
;
if (needResize)
@@ -261,13 +295,24 @@ bimg::ImageContainer* convert(bx::AllocatorI* _allocator, const void* _inputData
return output;
}
if (_options.equirect)
if (_options.equirect
|| _options.strip)
{
bimg::ImageContainer* src = bimg::imageConvert(_allocator, bimg::TextureFormat::RGBA32F, *input);
bimg::imageFree(input);
bimg::ImageContainer* dst = bimg::imageCubemapFromLatLongRgba32F(_allocator, *src, true, _err);
bimg::imageFree(src);
bimg::ImageContainer* dst;
if (outputWidth/2 == outputHeight)
{
dst = bimg::imageCubemapFromLatLongRgba32F(_allocator, *src, true, _err);
bimg::imageFree(src);
}
else
{
dst = bimg::imageCubemapFromStripRgba32F(_allocator, *src, _err);
bimg::imageFree(src);
}
if (!_err->isOk() )
{
@@ -278,6 +323,27 @@ bimg::ImageContainer* convert(bx::AllocatorI* _allocator, const void* _inputData
bimg::imageFree(dst);
}
if (bimg::LightingModel::Count != _options.radiance)
{
output = bimg::imageCubemapRadianceFilter(_allocator, *input, _options.radiance, _err);
if (!_err->isOk() )
{
return NULL;
}
if (bimg::TextureFormat::RGBA32F != outputFormat)
{
bimg::ImageContainer* temp = bimg::imageEncode(_allocator, outputFormat, _options.quality, *output);
bimg::imageFree(output);
output = temp;
}
bimg::imageFree(input);
return output;
}
output = bimg::imageAlloc(
_allocator
, outputFormat
@@ -749,7 +815,7 @@ void help(const char* _error = NULL, bool _showHelp = true)
" *.exr (input, output) OpenEXR.\n"
" *.gif (input) Graphics Interchange Format.\n"
" *.jpg (input) JPEG Interchange Format.\n"
" *.hdr (input) Radiance RGBE.\n"
" *.hdr (input, output) Radiance RGBE.\n"
" *.ktx (input, output) Khronos Texture.\n"
" *.png (input, output) Portable Network Graphics.\n"
" *.psd (input) Photoshop Document.\n"
@@ -766,13 +832,15 @@ void help(const char* _error = NULL, bool _showHelp = true)
" -q <quality> Encoding quality (default, fastest, highest).\n"
" -m, --mips Generate mip-maps.\n"
" -n, --normalmap Input texture is normal map.\n"
" --equirect Input texture equirectangular projection of cubemap.\n"
" --equirect Input texture is equirectangular projection of cubemap.\n"
" --strip Input texture is horizontal strip of cubemap.\n"
" --sdf <edge> Compute SDF texture.\n"
" --ref <alpha> Alpha reference value.\n"
" --iqa Image Quality Assessment\n"
" --pma Premultiply alpha into RGB channel.\n"
" --max <max size> Maximum width/height (image will be scaled down and\n"
" aspect ratio will be preserved.\n"
" --radiance <model> Radiance cubemap filter. (Lighting model: Phong, PhongBrdf, Blinn, BlinnBrdf, GGX)\n"
" --as <extension> Save as.\n"
" --validate *DEBUG* Validate that output image produced matches after loading.\n"
@@ -860,6 +928,7 @@ int main(int _argc, const char* _argv[])
saveAs = NULL == saveAs ? bx::strFindI(outputFileName, ".dds") : saveAs;
saveAs = NULL == saveAs ? bx::strFindI(outputFileName, ".png") : saveAs;
saveAs = NULL == saveAs ? bx::strFindI(outputFileName, ".exr") : saveAs;
saveAs = NULL == saveAs ? bx::strFindI(outputFileName, ".hdr") : saveAs;
if (NULL == saveAs)
{
help("Output file format must be specified.");
@@ -890,16 +959,28 @@ int main(int _argc, const char* _argv[])
}
}
options.mips = cmdLine.hasArg('m', "mips");
options.normalMap = cmdLine.hasArg('n', "normalmap");
options.mips = cmdLine.hasArg('m', "mips");
options.normalMap = cmdLine.hasArg('n', "normalmap");
options.equirect = cmdLine.hasArg("equirect");
options.strip = cmdLine.hasArg("strip");
options.iqa = cmdLine.hasArg("iqa");
options.pma = cmdLine.hasArg("pma");
if (options.equirect
&& options.strip)
{
help("Image can't be equirect and strip at the same time.");
return bx::kExitFailure;
}
const char* maxSize = cmdLine.findOption("max");
if (NULL != maxSize)
{
options.maxSize = atoi(maxSize);
if (!bx::fromString(&options.maxSize, maxSize) )
{
help("Parsing max size failed.");
return bx::kExitFailure;
}
}
options.format = bimg::TextureFormat::Count;
@@ -954,6 +1035,21 @@ int main(int _argc, const char* _argv[])
}
}
const char* radiance = cmdLine.findOption("radiance");
if (NULL != radiance)
{
if (0 == bx::strCmpI(radiance, "phong" ) ) { options.radiance = bimg::LightingModel::Phong; }
else if (0 == bx::strCmpI(radiance, "phongbrdf") ) { options.radiance = bimg::LightingModel::PhongBrdf; }
else if (0 == bx::strCmpI(radiance, "blinn" ) ) { options.radiance = bimg::LightingModel::Blinn; }
else if (0 == bx::strCmpI(radiance, "blinnbrdf") ) { options.radiance = bimg::LightingModel::BlinnBrdf; }
else if (0 == bx::strCmpI(radiance, "ggx" ) ) { options.radiance = bimg::LightingModel::Ggx; }
else
{
help("Invalid radiance lighting model specified.");
return bx::kExitFailure;
}
}
const bool validate = cmdLine.hasArg("validate");
bx::Error err;
@@ -1019,7 +1115,8 @@ int main(int _argc, const char* _argv[])
, mip.m_data
, output->m_format
, false
, &err);
, &err
);
}
else if (NULL != bx::strFindI(saveAs, "exr") )
{
@@ -1032,7 +1129,22 @@ int main(int _argc, const char* _argv[])
, mip.m_data
, output->m_format
, false
, &err);
, &err
);
}
else if (NULL != bx::strFindI(saveAs, "hdr") )
{
bimg::ImageMip mip;
bimg::imageGetRawData(*output, 0, 0, output->m_data, output->m_size, mip);
bimg::imageWriteHdr(&writer
, mip.m_width
, mip.m_height
, mip.m_width*getBitsPerPixel(mip.m_format)/8
, mip.m_data
, output->m_format
, false
, &err
);
}
bx::close(&writer);