diff --git a/tools/texturec/texturec.cpp b/tools/texturec/texturec.cpp index 9a12b62..983f036 100644 --- a/tools/texturec/texturec.cpp +++ b/tools/texturec/texturec.cpp @@ -39,6 +39,7 @@ struct Options , normalMap(false) , equirect(false) , iqa(false) + , pma(false) , sdf(false) , alphaTest(false) { @@ -53,6 +54,7 @@ struct Options "\t mips: %s\n" "\tnormalMap: %s\n" "\t iqa: %s\n" + "\t pma: %s\n" "\t sdf: %s\n" , maxSize , edge @@ -60,6 +62,7 @@ struct Options , mips ? "true" : "false" , normalMap ? "true" : "false" , iqa ? "true" : "false" + , pma ? "true" : "false" , sdf ? "true" : "false" ); } @@ -72,6 +75,7 @@ struct Options bool normalMap; bool equirect; bool iqa; + bool pma; bool sdf; bool alphaTest; }; @@ -88,14 +92,42 @@ void imageRgba32fNormalize(void* _dst, uint32_t _width, uint32_t _height, uint32 { float xyz[3]; - xyz[0] = rgba[0]; - xyz[1] = rgba[1]; - xyz[2] = rgba[2]; + xyz[0] = rgba[0]; + xyz[1] = rgba[1]; + xyz[2] = rgba[2]; bx::vec3Norm( (float*)dst, xyz); } } } +void imagePremultiplyAlpha(void* _inOut, uint32_t _width, uint32_t _height, uint32_t _depth, bimg::TextureFormat::Enum _format) +{ + uint8_t* inOut = (uint8_t*)_inOut; + uint32_t bpp = bimg::getBitsPerPixel(_format); + uint32_t pitch = _width*bpp/8; + + bimg::PackFn pack = bimg::getPack(_format); + bimg::UnpackFn unpack = bimg::getUnpack(_format); + + for (uint32_t zz = 0; zz < _depth; ++zz) + { + for (uint32_t yy = 0; yy < _height; ++yy) + { + for (uint32_t xx = 0; xx < _width; ++xx) + { + const uint32_t offset = yy*pitch + xx*bpp/8; + + float rgba[4]; + unpack(rgba, &inOut[offset]); + rgba[0] *= rgba[3]; + rgba[1] *= rgba[3]; + rgba[2] *= rgba[3]; + pack(&inOut[offset], rgba); + } + } + } +} + bimg::ImageContainer* convert(bx::AllocatorI* _allocator, const void* _inputData, uint32_t _inputSize, const Options& _options, bx::Error* _err) { BX_ERROR_SCOPE(_err); @@ -173,6 +205,7 @@ bimg::ImageContainer* convert(bx::AllocatorI* _allocator, const void* _inputData && !_options.normalMap && !_options.equirect && !_options.iqa + && !_options.pma ; if (needResize) @@ -257,6 +290,7 @@ bimg::ImageContainer* convert(bx::AllocatorI* _allocator, const void* _inputData void* temp = NULL; + // Normal map. if (_options.normalMap) { uint32_t size = bimg::imageGetSize( @@ -360,6 +394,7 @@ bimg::ImageContainer* convert(bx::AllocatorI* _allocator, const void* _inputData BX_FREE(_allocator, rgbaDst); } + // HDR else if ( (!bimg::isCompressed(input->m_format) && 8 != inputBlockInfo.rBits) || outputFormat == bimg::TextureFormat::BC6H || outputFormat == bimg::TextureFormat::BC7 @@ -389,6 +424,17 @@ bimg::ImageContainer* convert(bx::AllocatorI* _allocator, const void* _inputData , mip.m_format ); + if (_options.pma) + { + imagePremultiplyAlpha( + rgba32f + , dstMip.m_width + , dstMip.m_height + , dstMip.m_depth + , bimg::TextureFormat::RGBA32F + ); + } + bimg::imageEncodeFromRgba32f(_allocator , dstData , rgba32f @@ -421,6 +467,17 @@ bimg::ImageContainer* convert(bx::AllocatorI* _allocator, const void* _inputData , rgba32f ); + if (_options.pma) + { + imagePremultiplyAlpha( + rgba32f + , dstMip.m_width + , dstMip.m_height + , dstMip.m_depth + , bimg::TextureFormat::RGBA32F + ); + } + bimg::imageGetRawData(*output, side, lod, output->m_data, output->m_size, dstMip); dstData = const_cast(dstMip.m_data); @@ -447,6 +504,7 @@ bimg::ImageContainer* convert(bx::AllocatorI* _allocator, const void* _inputData BX_FREE(_allocator, rgbaDst); } + // SDF else if (_options.sdf) { uint32_t size = bimg::imageGetSize( @@ -484,6 +542,7 @@ bimg::ImageContainer* convert(bx::AllocatorI* _allocator, const void* _inputData , rgba ); } + // RGBA8 else { uint32_t size = bimg::imageGetSize( @@ -526,8 +585,20 @@ bimg::ImageContainer* convert(bx::AllocatorI* _allocator, const void* _inputData bx::memCopy(ref, rgba, size); } + if (_options.pma) + { + imagePremultiplyAlpha( + rgba + , dstMip.m_width + , dstMip.m_height + , dstMip.m_depth + , bimg::TextureFormat::RGBA8 + ); + } + bimg::imageGetRawData(*output, side, 0, output->m_data, output->m_size, dstMip); dstData = const_cast(dstMip.m_data); + bimg::imageEncodeFromRgba8(dstData , rgba , dstMip.m_width @@ -561,6 +632,17 @@ bimg::ImageContainer* convert(bx::AllocatorI* _allocator, const void* _inputData ); } + if (_options.pma) + { + imagePremultiplyAlpha( + rgba + , dstMip.m_width + , dstMip.m_height + , dstMip.m_depth + , bimg::TextureFormat::RGBA8 + ); + } + bimg::imageGetRawData(*output, side, lod, output->m_data, output->m_size, dstMip); dstData = const_cast(dstMip.m_data); @@ -667,6 +749,7 @@ void help(const char* _error = NULL, bool _showHelp = true) " --sdf Compute SDF texture.\n" " --ref Alpha reference value.\n" " --iqa Image Quality Assessment\n" + " --pma Premultiply alpha into RGB channel.\n" " --max Maximum width/height (image will be scaled down and\n" " aspect ratio will be preserved.\n" " --as Save as.\n" @@ -765,6 +848,7 @@ int main(int _argc, const char* _argv[]) options.normalMap = cmdLine.hasArg('n', "normalmap"); options.equirect = cmdLine.hasArg("equirect"); options.iqa = cmdLine.hasArg("iqa"); + options.pma = cmdLine.hasArg("pma"); const char* maxSize = cmdLine.findOption("max"); if (NULL != maxSize)