2
0
Эх сурвалжийг харах

Update to bimg rev 0e68019.

woollybah 6 жил өмнө
parent
commit
7efa4c02f5

+ 4 - 4
bimg.mod/bimg.bmx

@@ -27,18 +27,18 @@ SuperStrict
 Module gfx.bimg
 
 ?linuxx86
-ModuleInfo "CC_OPTS: -mfpmath=sse -msse2 -std=c++0x"
+ModuleInfo "CC_OPTS: -mfpmath=sse -msse2 -std=c++14"
 ?linuxx64
-ModuleInfo "CC_OPTS: -mfpmath=sse -msse2 -std=c++0x"
+ModuleInfo "CC_OPTS: -mfpmath=sse -msse2 -std=c++14"
 ?macos
 ModuleInfo "CC_OPTS: -msse2"
 ?win32
-ModuleInfo "CC_OPTS: -mfpmath=sse -msse2 -std=c++0x"
+ModuleInfo "CC_OPTS: -mfpmath=sse -msse2 -std=c++14"
 
 ModuleInfo "CC_OPTS: -D__STDC_LIMIT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_CONSTANT_MACROS"
 
 ?raspberrypi
-ModuleInfo "CC_OPTS: -std=c++0x"
+ModuleInfo "CC_OPTS: -std=c++14"
 ?
 
 Import "common.bmx"

+ 0 - 1
bimg.mod/bimg/.appveyor.yml

@@ -5,7 +5,6 @@ os:
 
 environment:
   matrix:
-  - TOOLSET: vs2015
   - TOOLSET: vs2017
 
 configuration:

+ 1 - 1
bimg.mod/bimg/3rdparty/nvtt/nvcore/debug.h

@@ -165,7 +165,7 @@ NVCORE_API void NV_CDECL nvDebugPrint( const char *msg, ... ) __attribute__((for
 namespace nv
 {
     inline bool isValidPtr(const void * ptr) {
-    #if NV_CPU_X86_64
+    #if NV_CPU_X86_64 || NV_CPU_AARCH64
         if (ptr == NULL) return true;
         if (reinterpret_cast<uint64>(ptr) < 0x10000ULL) return false;
         if (reinterpret_cast<uint64>(ptr) >= 0x000007FFFFFEFFFFULL) return false;

+ 3 - 3
bimg.mod/bimg/3rdparty/nvtt/nvtt.cpp

@@ -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) ) ) );
 					}
 				}
 

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 351 - 165
bimg.mod/bimg/3rdparty/tinyexr/tinyexr.h


+ 38 - 9
bimg.mod/bimg/include/bimg/bimg.h

@@ -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
 {
@@ -65,6 +65,15 @@ namespace bimg
 			PTC14A,       //!< PVRTC1 RGBA 4BPP
 			PTC22,        //!< PVRTC2 RGBA 2BPP
 			PTC24,        //!< PVRTC2 RGBA 4BPP
+			ATC,          //!< ATC RGB 4BPP
+			ATCE,         //!< ATCE RGBA 8 BPP explicit alpha
+			ATCI,         //!< ATCI RGBA 8 BPP interpolated alpha
+			ASTC4x4,      //!< ASTC 4x4 8.0 BPP
+			ASTC5x5,      //!< ASTC 5x5 5.12 BPP
+			ASTC6x6,      //!< ASTC 6x6 3.56 BPP
+			ASTC8x5,      //!< ASTC 8x5 3.20 BPP
+			ASTC8x6,      //!< ASTC 8x6 2.67 BPP
+			ASTC10x5,     //!< ASTC 10x5 2.56 BPP
 
 			Unknown,      // Compressed formats above.
 
@@ -305,6 +314,9 @@ namespace bimg
 		, const void* _src
 		);
 
+	///
+	void imageRgba32fToLinear(ImageContainer* _imageContainer);
+
 	///
 	void imageRgba32fToGamma(
 		  void* _dst
@@ -315,6 +327,9 @@ namespace bimg
 		, const void* _src
 		);
 
+	///
+	void imageRgba32fToGamma(ImageContainer* _imageContainer);
+
 	///
 	void imageRgba32fLinearDownsample2x2(
 		  void* _dst
@@ -325,6 +340,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
@@ -484,6 +509,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
@@ -619,14 +656,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

+ 45 - 1
bimg.mod/bimg/include/bimg/encode.h

@@ -87,7 +87,6 @@ namespace bimg
 		, uint32_t _width
 		, uint32_t _height
 		, uint32_t _srcPitch
-		, float _edge
 		, const void* _src
 		);
 
@@ -114,6 +113,7 @@ namespace bimg
 		, const void* _src
 		, float _alphaRef
 		, float _scale = 1.0f
+		, uint32_t _upscale = 1
 		);
 
 	///
@@ -125,6 +125,50 @@ namespace bimg
 		, void* _src
 		, float _coverage
 		, float _alphaRef
+		, uint32_t _upscale = 1
+		);
+
+	///
+	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

+ 3 - 42
bimg.mod/bimg/makefile

@@ -39,15 +39,12 @@ clean: ## Clean all intermediate files.
 	@mkdir .build
 
 projgen: ## Generate project files for all configurations.
-	$(GENIE) --with-tools                     vs2012
-	$(GENIE) --with-tools                     vs2013
-	$(GENIE) --with-tools                     vs2015
 	$(GENIE) --with-tools                     vs2017
 	$(GENIE) --with-tools --gcc=mingw-gcc     gmake
 	$(GENIE) --with-tools --gcc=linux-gcc     gmake
 	$(GENIE) --with-tools --gcc=osx           gmake
-	$(GENIE) --with-tools --xcode=osx         xcode4
-	$(GENIE) --with-tools --xcode=ios         xcode4
+	$(GENIE) --with-tools --xcode=osx         xcode8
+	$(GENIE) --with-tools --xcode=ios         xcode8
 	$(GENIE)              --gcc=freebsd       gmake
 	$(GENIE)                                --gcc=android-arm     gmake
 	$(GENIE)                                --gcc=android-mips    gmake
@@ -135,42 +132,6 @@ mingw-clang-release64: .build/projects/gmake-mingw-clang ## Build - MinGW Clang
 	$(MAKE) -R -C .build/projects/gmake-mingw-clang config=release64
 mingw-clang: mingw-clang-debug32 mingw-clang-release32 mingw-clang-debug64 mingw-clang-release64 ## Build - MinGW Clang x86/x64 Debug and Release
 
-.build/projects/vs2012:
-	$(GENIE) --with-tools vs2012
-vs2012-debug32: .build/projects/vs2012 ## Build - VS2012 x86 Debug
-	devenv .build/projects/vs2012/bimg.sln /Build "Debug|Win32"
-vs2012-release32: .build/projects/vs2012 ## Build - VS2012 x86 Release
-	devenv .build/projects/vs2012/bimg.sln /Build "Release|Win32"
-vs2012-debug64: .build/projects/vs2012 ## Build - VS2012 x64 Debug
-	devenv .build/projects/vs2012/bimg.sln /Build "Debug|x64"
-vs2012-release64: .build/projects/vs2012 ## Build - VS2012 x64 Release
-	devenv .build/projects/vs2012/bimg.sln /Build "Release|x64"
-vs2012: vs2012-debug32 vs2012-release32 vs2012-debug64 vs2012-release64 ## Build - VS2012 x86/x64 Debug and Release
-
-.build/projects/vs2013:
-	$(GENIE) --with-tools vs2013
-vs2013-debug32: .build/projects/vs2013 ## Build - VS2013 x86 Debug
-	devenv .build/projects/vs2013/bimg.sln /Build "Debug|Win32"
-vs2013-release32: .build/projects/vs2013 ## Build - VS2013 x86 Release
-	devenv .build/projects/vs2013/bimg.sln /Build "Release|Win32"
-vs2013-debug64: .build/projects/vs2013 ## Build - VS2013 x64 Debug
-	devenv .build/projects/vs2013/bimg.sln /Build "Debug|x64"
-vs2013-release64: .build/projects/vs2013 ## Build - VS2013 x64 Release
-	devenv .build/projects/vs2013/bimg.sln /Build "Release|x64"
-vs2013: vs2013-debug32 vs2013-release32 vs2013-debug64 vs2013-release64 ## Build - VS2013 x86/x64 Debug and Release
-
-.build/projects/vs2015:
-	$(GENIE) --with-tools vs2015
-vs2015-debug32: .build/projects/vs2015 ## Build - VS2015 x86 Debug
-	devenv .build/projects/vs2015/bimg.sln /Build "Debug|Win32"
-vs2015-release32: .build/projects/vs2015 ## Build - VS2015 x86 Release
-	devenv .build/projects/vs2015/bimg.sln /Build "Release|Win32"
-vs2015-debug64: .build/projects/vs2015 ## Build - VS2015 x64 Debug
-	devenv .build/projects/vs2015/bimg.sln /Build "Debug|x64"
-vs2015-release64: .build/projects/vs2015 ## Build - VS2015 x64 Release
-	devenv .build/projects/vs2015/bimg.sln /Build "Release|x64"
-vs2015: vs2015-debug32 vs2015-release32 vs2015-debug64 vs2015-release64 ## Build - VS2015 x86/x64 Debug and Release
-
 .build/projects/vs2017:
 	$(GENIE) --with-tools vs2017
 vs2017-debug32: .build/projects/vs2017 ## Build - vs2017 x86 Debug
@@ -308,7 +269,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)

+ 3 - 0
bimg.mod/bimg/scripts/bimg_encode.lua

@@ -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"),
@@ -29,6 +30,8 @@ project "bimg_encode"
 		path.join(BIMG_DIR, "3rdparty/nvtt/**.h"),
 		path.join(BIMG_DIR, "3rdparty/pvrtc/**.cpp"),
 		path.join(BIMG_DIR, "3rdparty/pvrtc/**.h"),
+		path.join(BIMG_DIR, "3rdparty/astc/**.cpp"),
+		path.join(BIMG_DIR, "3rdparty/astc/**.h"),
 		path.join(BIMG_DIR, "3rdparty/tinyexr/**.h"),
 		path.join(BIMG_DIR, "3rdparty/iqa/include/**.h"),
 		path.join(BIMG_DIR, "3rdparty/iqa/source/**.c"),

+ 0 - 18
bimg.mod/bimg/scripts/texturec.lua

@@ -9,27 +9,9 @@ project "texturec"
 	includedirs {
 		path.join(BX_DIR,   "include"),
 		path.join(BIMG_DIR, "include"),
-		path.join(BIMG_DIR, "3rdparty"),
-		path.join(BIMG_DIR, "3rdparty/nvtt"),
-		path.join(BIMG_DIR, "3rdparty/iqa/include"),
 	}
 
 	files {
-		path.join(BIMG_DIR, "3rdparty/libsquish/**.cpp"),
-		path.join(BIMG_DIR, "3rdparty/libsquish/**.h"),
-		path.join(BIMG_DIR, "3rdparty/edtaa3/**.cpp"),
-		path.join(BIMG_DIR, "3rdparty/edtaa3/**.h"),
-		path.join(BIMG_DIR, "3rdparty/etc1/**.cpp"),
-		path.join(BIMG_DIR, "3rdparty/etc1/**.h"),
-		path.join(BIMG_DIR, "3rdparty/etc2/**.cpp"),
-		path.join(BIMG_DIR, "3rdparty/etc2/**.hpp"),
-		path.join(BIMG_DIR, "3rdparty/nvtt/**.cpp"),
-		path.join(BIMG_DIR, "3rdparty/nvtt/**.h"),
-		path.join(BIMG_DIR, "3rdparty/pvrtc/**.cpp"),
-		path.join(BIMG_DIR, "3rdparty/pvrtc/**.h"),
-		path.join(BIMG_DIR, "3rdparty/tinyexr/**.h"),
-		path.join(BIMG_DIR, "3rdparty/iqa/include/**.h"),
-		path.join(BIMG_DIR, "3rdparty/iqa/source/**.c"),
 		path.join(BIMG_DIR, "tools/texturec/**.cpp"),
 		path.join(BIMG_DIR, "tools/texturec/**.h"),
 	}

+ 5 - 1
bimg.mod/bimg/src/bimg_p.h

@@ -19,6 +19,10 @@
 
 BX_ERROR_RESULT(BIMG_ERROR, BX_MAKEFOURCC('b', 'i', 'm', 'g') );
 
+#ifndef BIMG_CONFIG_ASTC_DECODE
+#	define BIMG_CONFIG_ASTC_DECODE 0
+#endif // BIMG_CONFIG_ASTC_DECODE
+
 namespace bimg
 {
 	struct Memory
@@ -43,7 +47,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);

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 609 - 163
bimg.mod/bimg/src/image.cpp


+ 16 - 1
bimg.mod/bimg/src/image_decode.cpp

@@ -473,7 +473,22 @@ namespace bimg
 			}
 			else
 			{
-				BX_ERROR_SET(_err, BIMG_ERROR, "EXR: Failed to parse image.");
+				switch (result)
+				{
+				case TINYEXR_ERROR_INVALID_MAGIC_NUMBER: BX_ERROR_SET(_err, BIMG_ERROR, "EXR: Failed to parse image. Invalid magic number."); break;
+				case TINYEXR_ERROR_INVALID_EXR_VERSION:	 BX_ERROR_SET(_err, BIMG_ERROR, "EXR: Failed to parse image. Invalid EXR version.");  break;
+				case TINYEXR_ERROR_INVALID_ARGUMENT:     BX_ERROR_SET(_err, BIMG_ERROR, "EXR: Failed to parse image. Invalid argument.");     break;
+				case TINYEXR_ERROR_INVALID_DATA:         BX_ERROR_SET(_err, BIMG_ERROR, "EXR: Failed to parse image. Invalid data.");         break;
+				case TINYEXR_ERROR_INVALID_FILE:         BX_ERROR_SET(_err, BIMG_ERROR, "EXR: Failed to parse image. Invalid file.");         break;
+//				case TINYEXR_ERROR_INVALID_PARAMETER:    BX_ERROR_SET(_err, BIMG_ERROR, "EXR: Failed to parse image. Invalid parameter.");    break;
+				case TINYEXR_ERROR_CANT_OPEN_FILE:       BX_ERROR_SET(_err, BIMG_ERROR, "EXR: Failed to parse image. Can't open file.");      break;
+				case TINYEXR_ERROR_UNSUPPORTED_FORMAT:   BX_ERROR_SET(_err, BIMG_ERROR, "EXR: Failed to parse image. Unsupported format.");   break;
+				case TINYEXR_ERROR_INVALID_HEADER:       BX_ERROR_SET(_err, BIMG_ERROR, "EXR: Failed to parse image. Invalid header.");       break;
+				case TINYEXR_ERROR_UNSUPPORTED_FEATURE:  BX_ERROR_SET(_err, BIMG_ERROR, "EXR: Failed to parse image. Unsupported feature.");  break;
+				case TINYEXR_ERROR_CANT_WRITE_FILE:      BX_ERROR_SET(_err, BIMG_ERROR, "EXR: Failed to parse image. Can't write file.");     break;
+				case TINYEXR_ERROR_SERIALZATION_FAILED:  BX_ERROR_SET(_err, BIMG_ERROR, "EXR: Failed to parse image. Serialization failed."); break;
+				default:                                 BX_ERROR_SET(_err, BIMG_ERROR, "EXR: Failed to parse image.");                       break;
+				}
 			}
 
 			FreeEXRHeader(&exrHeader);

+ 68 - 34
bimg.mod/bimg/src/image_encode.cpp

@@ -12,6 +12,7 @@
 #include <nvtt/nvtt.h>
 #include <pvrtc/PvrTcEncoder.h>
 #include <edtaa3/edtaa3func.h>
+#include <astc/astc_lib.h>
 
 BX_PRAGMA_DIAGNOSTIC_PUSH();
 BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC(4100) // warning C4100: 'alloc_context': unreferenced formal parameter
@@ -35,6 +36,14 @@ namespace bimg
 	};
 	BX_STATIC_ASSERT(Quality::Count == BX_COUNTOF(s_squishQuality) );
 
+    static const ASTC_COMPRESS_MODE s_astcQuality[] =
+    {
+        ASTC_COMPRESS_MEDIUM,       // Default
+        ASTC_COMPRESS_THOROUGH,     // Highest
+        ASTC_COMPRESS_FAST,         // Fastest
+    };
+    BX_STATIC_ASSERT(Quality::Count == BX_COUNTOF(s_astcQuality));
+
 	void imageEncodeFromRgba8(bx::AllocatorI* _allocator, void* _dst, const void* _src, uint32_t _width, uint32_t _height, uint32_t _depth, TextureFormat::Enum _format, Quality::Enum _quality, bx::Error* _err)
 	{
 		const uint8_t* src = (const uint8_t*)_src;
@@ -89,7 +98,7 @@ namespace bimg
 							for (uint32_t ii = 0; ii < 16; ++ii)
 							{ // BGRx
 								bx::memCopy(&block[ii*4], &ptr[(ii%4)*srcPitch + (ii&~3)], 4);
-								bx::xchg(block[ii*4+0], block[ii*4+2]);
+								bx::swap(block[ii*4+0], block[ii*4+2]);
 							}
 
 							*dstBlock++ = ProcessRGB_ETC2(block);
@@ -122,6 +131,22 @@ namespace bimg
 				}
 				break;
 
+			case TextureFormat::ASTC4x4:
+			case TextureFormat::ASTC5x5:
+			case TextureFormat::ASTC6x6:
+			case TextureFormat::ASTC8x5:
+			case TextureFormat::ASTC8x6:
+			case TextureFormat::ASTC10x5:
+				{
+                    const bimg::ImageBlockInfo& astcBlockInfo = bimg::getBlockInfo(_format);
+
+                    ASTC_COMPRESS_MODE  compress_mode = s_astcQuality[_quality];
+					ASTC_DECODE_MODE    decode_mode   = ASTC_DECODE_LDR_LINEAR;
+
+                    astc_compress(_width, _height, src, ASTC_RGBA, srcPitch, astcBlockInfo.blockWidth, astcBlockInfo.blockHeight, compress_mode, decode_mode, dst);
+				}
+				break;
+
 			case TextureFormat::BGRA8:
 				imageSwizzleBgra8(dst, dstPitch, _width, _height, src, srcPitch);
 				break;
@@ -200,15 +225,21 @@ namespace bimg
 	{
 		switch (_dstFormat)
 		{
-			case bimg::TextureFormat::BC1:
-			case bimg::TextureFormat::BC2:
-			case bimg::TextureFormat::BC3:
-			case bimg::TextureFormat::BC4:
-			case bimg::TextureFormat::BC5:
-			case bimg::TextureFormat::ETC1:
-			case bimg::TextureFormat::ETC2:
-			case bimg::TextureFormat::PTC14:
-			case bimg::TextureFormat::PTC14A:
+			case TextureFormat::BC1:
+			case TextureFormat::BC2:
+			case TextureFormat::BC3:
+			case TextureFormat::BC4:
+			case TextureFormat::BC5:
+			case TextureFormat::ETC1:
+			case TextureFormat::ETC2:
+			case TextureFormat::PTC14:
+			case TextureFormat::PTC14A:
+			case TextureFormat::ASTC4x4:
+			case TextureFormat::ASTC5x5:
+			case TextureFormat::ASTC6x6:
+			case TextureFormat::ASTC8x5:
+			case TextureFormat::ASTC8x6:
+			case TextureFormat::ASTC10x5:
 				{
 					uint8_t* temp = (uint8_t*)BX_ALLOC(_allocator, _width*_height*_depth*4);
 					imageDecodeToRgba8(_allocator, temp, _src, _width, _height, _width*4, _srcFormat);
@@ -228,7 +259,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 +294,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
+						);
 				}
 			}
 		}
@@ -333,7 +368,7 @@ namespace bimg
 		BX_FREE(_allocator, gy);
 	}
 
-	void imageMakeDist(bx::AllocatorI* _allocator, void* _dst, uint32_t _width, uint32_t _height, uint32_t _srcPitch, float _edge, const void* _src)
+	void imageMakeDist(bx::AllocatorI* _allocator, void* _dst, uint32_t _width, uint32_t _height, uint32_t _srcPitch, const void* _src)
 	{
 		const uint32_t numPixels = _width*_height;
 
@@ -364,12 +399,9 @@ namespace bimg
 
 		uint8_t* dst = (uint8_t*)_dst;
 
-		double edgeOffset = _edge*0.5;
-		double invEdge = 1.0/_edge;
-
 		for (uint32_t ii = 0; ii < numPixels; ++ii)
 		{
-			double dist = bx::clamp( ( (outside[ii] - inside[ii])+edgeOffset) * invEdge, 0.0, 1.0);
+			double dist = bx::clamp( (outside[ii] - inside[ii]) * 1.0/16.0 + 0.5, 0.0, 1.0);
 			dst[ii] = 255-uint8_t(dist * 255.0);
 		}
 
@@ -435,7 +467,7 @@ namespace bimg
 					, 4, 3
 					, STBIR_FLAG_ALPHA_PREMULTIPLIED
 					, STBIR_EDGE_CLAMP
-					, STBIR_FILTER_CUBICBSPLINE
+					, STBIR_FILTER_BOX
 					, STBIR_COLORSPACE_LINEAR
 					, NULL
 					);
@@ -458,7 +490,7 @@ namespace bimg
 		return rgba[3];
 	}
 
-	float imageAlphaTestCoverage(TextureFormat::Enum _format, uint32_t _width, uint32_t _height, uint32_t _srcPitch, const void* _src, float _alphaRef, float _scale)
+	float imageAlphaTestCoverage(TextureFormat::Enum _format, uint32_t _width, uint32_t _height, uint32_t _srcPitch, const void* _src, float _alphaRef, float _scale, uint32_t _upscale)
 	{
 		UnpackFn unpack = getUnpack(_format);
 		if (NULL == unpack)
@@ -469,7 +501,8 @@ namespace bimg
 		float coverage = 0.0f;
 		const uint8_t* src = (const uint8_t*)_src;
 		const uint32_t xstep = getBitsPerPixel(_format) / 8;
-		const float numSamples = 8.0f;
+		const uint32_t numSamples = _upscale;
+		const float sampleStep = 1.0f / numSamples;
 
 		for (uint32_t yy = 0, ystep = _srcPitch; yy < _height-1; ++yy, src += ystep)
 		{
@@ -481,9 +514,9 @@ namespace bimg
 				float alpha01 = _scale * getAlpha(unpack, data+ystep);
 				float alpha11 = _scale * getAlpha(unpack, data+ystep+xstep);
 
-				for (float fy = 0.5f/numSamples; fy < 1.0f; fy += 1.0f)
+				for (float fy = 0.0f; fy < 1.0f; fy += sampleStep)
 				{
-					for (float fx = 0.5f/numSamples; fx < 1.0f; fx += 1.0f)
+					for (float fx = 0.0f; fx < 1.0f; fx += sampleStep)
 					{
 						float alpha = 0.0f
 							+ alpha00 * (1.0f - fx) * (1.0f - fy)
@@ -504,7 +537,7 @@ namespace bimg
 		return coverage / float(_width*_height*numSamples*numSamples);
 	}
 
-	void imageScaleAlphaToCoverage(TextureFormat::Enum _format, uint32_t _width, uint32_t _height, uint32_t _srcPitch, void* _src, float _desiredCoverage, float _alphaRef)
+	void imageScaleAlphaToCoverage(TextureFormat::Enum _format, uint32_t _width, uint32_t _height, uint32_t _srcPitch, void* _src, float _desiredCoverage, float _alphaRef, uint32_t _upscale)
 	{
 		PackFn   pack   = getPack(_format);
 		UnpackFn unpack = getUnpack(_format);
@@ -518,7 +551,7 @@ namespace bimg
 		float max   = 4.0f;
 		float scale = 1.0f;
 
-		for (uint32_t ii = 0; ii < 8; ++ii)
+		for (uint32_t ii = 0; ii < 10; ++ii)
 		{
 			float coverage = imageAlphaTestCoverage(
 				  _format
@@ -528,6 +561,7 @@ namespace bimg
 				, _src
 				, _alphaRef
 				, scale
+				, _upscale
 				);
 
 			if (coverage < _desiredCoverage)

+ 323 - 91
bimg.mod/bimg/tools/texturec/texturec.cpp

@@ -21,34 +21,21 @@
 #include <bx/bx.h>
 #include <bx/commandline.h>
 #include <bx/file.h>
-#include <bx/uint32_t.h>
 
 #include <string>
 
 #define BIMG_TEXTUREC_VERSION_MAJOR 1
-#define BIMG_TEXTUREC_VERSION_MINOR 15
+#define BIMG_TEXTUREC_VERSION_MINOR 18
+
+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"
 			"\t  maxSize: %d\n"
+			"\t  mipSkip: %d\n"
 			"\t     edge: %f\n"
 			"\t   format: %s\n"
 			"\t     mips: %s\n"
@@ -56,7 +43,12 @@ 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"
+			"\t   linear: %s\n"
 			, maxSize
+			, mipSkip
 			, edge
 			, bimg::getName(format)
 			, mips      ? "true" : "false"
@@ -64,20 +56,28 @@ struct Options
 			, iqa       ? "true" : "false"
 			, pma       ? "true" : "false"
 			, sdf       ? "true" : "false"
+			, radiance  ? "true" : "false"
+			, equirect  ? "true" : "false"
+			, strip     ? "true" : "false"
+			, linear    ? "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;
+	uint32_t mipSkip = 0;
+	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;
+	bool linear    = false;
 };
 
 void imageRgba32fNormalize(void* _dst, uint32_t _width, uint32_t _height, uint32_t _srcPitch, const void* _src)
@@ -90,12 +90,8 @@ void imageRgba32fNormalize(void* _dst, uint32_t _width, uint32_t _height, uint32
 		const float* rgba = (const float*)&src[0];
 		for (uint32_t xx = 0; xx < _width; ++xx, rgba += 4, dst += 16)
 		{
-			float xyz[3];
-
-			xyz[0] = rgba[0];
-			xyz[1] = rgba[1];
-			xyz[2] = rgba[2];
-			bx::vec3Norm( (float*)dst, xyz);
+			const bx::Vec3 xyz = bx::load(rgba);
+			bx::store(dst, bx::normalize(xyz) );
 		}
 	}
 }
@@ -161,16 +157,65 @@ bimg::ImageContainer* convert(bx::AllocatorI* _allocator, const void* _inputData
 		const bimg::ImageBlockInfo&  inputBlockInfo  = bimg::getBlockInfo(inputFormat);
 		const bimg::ImageBlockInfo&  outputBlockInfo = bimg::getBlockInfo(outputFormat);
 		const uint32_t blockWidth  = outputBlockInfo.blockWidth;
-		const uint32_t blockHeight = outputBlockInfo.blockHeight;
-		const uint32_t minBlockX   = outputBlockInfo.minBlockX;
-		const uint32_t minBlockY   = outputBlockInfo.minBlockY;
-		uint32_t outputWidth  = bx::uint32_max(blockWidth  * minBlockX, ( (input->m_width  + blockWidth  - 1) / blockWidth )*blockWidth);
-		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)
+        const uint32_t blockHeight = outputBlockInfo.blockHeight;
+        const uint32_t minBlockX   = outputBlockInfo.minBlockX;
+        const uint32_t minBlockY   = outputBlockInfo.minBlockY;
+        uint32_t outputWidth  = bx::max(blockWidth  * minBlockX, ( (input->m_width  + blockWidth  - 1) / blockWidth )*blockWidth);
+        uint32_t outputHeight = bx::max(blockHeight * minBlockY, ( (input->m_height + blockHeight - 1) / blockHeight)*blockHeight);
+        uint32_t outputDepth  = input->m_depth;
+
+		if (_options.mips
+		&&  _options.mipSkip != 0)
+		{
+			for (uint32_t ii = 0; ii < _options.mipSkip; ++ii)
+			{
+				outputWidth  = bx::max(blockWidth  * minBlockX, ( ( (outputWidth>>1)  + blockWidth  - 1) / blockWidth )*blockWidth);
+				outputHeight = bx::max(blockHeight * minBlockY, ( ( (outputHeight>>1) + blockHeight - 1) / blockHeight)*blockHeight);
+				outputDepth  = bx::max(outputDepth>>1, 1u);
+			}
+		}
+
+		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,12 +249,14 @@ 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)
+		if (!_options.sdf
+		&&  needResize)
 		{
 			bimg::ImageContainer* src = bimg::imageConvert(_allocator, bimg::TextureFormat::RGBA32F, *input, false);
 
@@ -224,8 +271,18 @@ bimg::ImageContainer* convert(bx::AllocatorI* _allocator, const void* _inputData
 				, false
 				);
 
+			if (!_options.linear)
+			{
+				bimg::imageRgba32fToLinear(src);
+			}
+
 			bimg::imageResizeRgba32fLinear(dst, src);
 
+			if (!_options.linear)
+			{
+				bimg::imageRgba32fToGamma(dst);
+			}
+
 			bimg::imageFree(src);
 			bimg::imageFree(input);
 
@@ -261,13 +318,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 +346,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
@@ -531,10 +620,10 @@ bimg::ImageContainer* convert(bx::AllocatorI* _allocator, const void* _inputData
 						, bimg::TextureFormat::R8
 						);
 					temp = BX_ALLOC(_allocator, size);
-					uint8_t* rgba = (uint8_t*)temp;
+					uint8_t* r8 = (uint8_t*)temp;
 
 					bimg::imageDecodeToR8(_allocator
-						, rgba
+						, r8
 						, mip.m_data
 						, mip.m_width
 						, mip.m_height
@@ -551,9 +640,85 @@ bimg::ImageContainer* convert(bx::AllocatorI* _allocator, const void* _inputData
 						, mip.m_width
 						, mip.m_height
 						, mip.m_width
-						, _options.edge
-						, rgba
+						, r8
 						);
+
+					if (_options.mips) {
+						const float alphaRef = 0.5f;
+						float coverage = bimg::imageAlphaTestCoverage(bimg::TextureFormat::A8
+							, mip.m_width
+							, mip.m_height
+							, mip.m_width
+							, r8
+							, alphaRef
+						);
+
+						size = bimg::imageGetSize(
+							NULL
+							, uint16_t(dstMip.m_width)
+							, uint16_t(dstMip.m_height)
+							, uint16_t(dstMip.m_depth)
+							, false
+							, false
+							, 1
+							, bimg::TextureFormat::RGBA8
+						);
+						void* rgbaTemp = BX_ALLOC(_allocator, size);
+						uint8_t* rgba = (uint8_t*)rgbaTemp;
+
+						bimg::imageDecodeToRgba8(
+							_allocator
+							, rgba
+							, dstMip.m_data
+							, dstMip.m_width
+							, dstMip.m_height
+							, dstMip.m_width * 4
+							, bimg::TextureFormat::A8
+						);
+
+						for (uint8_t lod = 1; lod < numMips && _err->isOk(); ++lod) {
+							bimg::imageRgba8Downsample2x2(rgba
+								, dstMip.m_width
+								, dstMip.m_height
+								, dstMip.m_depth
+								, dstMip.m_width * 4
+								, bx::strideAlign(dstMip.m_width / 2, blockWidth) * 4
+								, rgba
+							);
+
+							// For each mip, upscale to original size,
+							// scale image alpha to get same coverage as mip0
+							uint32_t upsample   = 1 << lod;
+							uint32_t destWidth  = dstMip.m_width / 2;
+							uint32_t destHeight = dstMip.m_height / 2;
+							bimg::imageScaleAlphaToCoverage(bimg::TextureFormat::RGBA8
+								, destWidth
+								, destHeight
+								, destWidth * 4
+								, rgba
+								, coverage
+								, alphaRef
+								, upsample
+							);
+
+							bimg::imageGetRawData(*output, side, lod, output->m_data, output->m_size, dstMip);
+							dstData = const_cast<uint8_t*>(dstMip.m_data);
+
+							bimg::imageEncodeFromRgba8(
+								_allocator
+								, dstData
+								, rgba
+								, dstMip.m_width
+								, dstMip.m_height
+								, dstMip.m_depth
+								, bimg::TextureFormat::A8
+								, _options.quality
+								, _err
+							);
+						}
+
+						BX_FREE(_allocator, rgbaTemp);
+					}
 				}
 				// RGBA8
 				else
@@ -749,7 +914,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"
@@ -765,19 +930,24 @@ void help(const char* _error = NULL, bool _showHelp = true)
 		  "  -t <format>              Output format type (BC1/2/3/4/5, ETC1, PVR14, etc.).\n"
 		  "  -q <quality>             Encoding quality (default, fastest, highest).\n"
 		  "  -m, --mips               Generate mip-maps.\n"
+		  "      --mipskip <N>        Skip <N> number of mips.\n"
 		  "  -n, --normalmap          Input texture is normal map.\n"
-		  "      --equirect           Input texture equirectangular projection of cubemap.\n"
-		  "      --sdf <edge>         Compute SDF texture.\n"
+		  "      --equirect           Input texture is equirectangular projection of cubemap.\n"
+		  "      --strip              Input texture is horizontal strip of cubemap.\n"
+		  "      --sdf                Compute SDF texture.\n"
 		  "      --ref <alpha>        Alpha reference value.\n"
 		  "      --iqa                Image Quality Assessment\n"
 		  "      --pma                Premultiply alpha into RGB channel.\n"
+		  "      --linear             Input and output texture is linear color space (gamma correction won't be applied).\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"
+          "      --formats            List all supported formats.\n"
 		  "      --validate           *DEBUG* Validate that output image produced matches after loading.\n"
 
 		  "\n"
-		  "For additional information, see https://github.com/bkaradzic/bgfx\n"
+		  "For additional information, see https://github.com/bkaradzic/bimg\n"
 		);
 }
 
@@ -841,6 +1011,24 @@ int main(int _argc, const char* _argv[])
 		return bx::kExitFailure;
 	}
 
+    if (cmdLine.hasArg("formats"))
+    {
+        printf("Uncompressed formats:\n");
+
+        for (int format = bimg::TextureFormat::Unknown + 1; format < bimg::TextureFormat::UnknownDepth; format++)
+            printf("  %s\n", bimg::getName((bimg::TextureFormat::Enum) format));
+
+        for (int format = bimg::TextureFormat::UnknownDepth + 1; format < bimg::TextureFormat::Count; format++)
+            printf("  %s\n", bimg::getName((bimg::TextureFormat::Enum) format));
+
+        printf("Compressed formats:\n");
+
+        for (int format = 0; format < bimg::TextureFormat::Unknown; format++)
+            printf("  %s\n", bimg::getName((bimg::TextureFormat::Enum) format));
+
+        return bx::kExitSuccess;
+    }
+
 	const char* inputFileName = cmdLine.findOption('f');
 	if (NULL == inputFileName)
 	{
@@ -855,12 +1043,13 @@ int main(int _argc, const char* _argv[])
 		return bx::kExitFailure;
 	}
 
-	const char* saveAs = cmdLine.findOption("as");
-	saveAs = NULL == saveAs ? bx::strFindI(outputFileName, ".ktx") : saveAs;
-	saveAs = NULL == saveAs ? bx::strFindI(outputFileName, ".dds") : saveAs;
-	saveAs = NULL == saveAs ? bx::strFindI(outputFileName, ".png") : saveAs;
-	saveAs = NULL == saveAs ? bx::strFindI(outputFileName, ".exr") : saveAs;
-	if (NULL == saveAs)
+	bx::StringView saveAs = cmdLine.findOption("as");
+	saveAs = saveAs.isEmpty() ? bx::strFindI(outputFileName, ".ktx") : saveAs;
+	saveAs = saveAs.isEmpty() ? bx::strFindI(outputFileName, ".dds") : saveAs;
+	saveAs = saveAs.isEmpty() ? bx::strFindI(outputFileName, ".png") : saveAs;
+	saveAs = saveAs.isEmpty() ? bx::strFindI(outputFileName, ".exr") : saveAs;
+	saveAs = saveAs.isEmpty() ? bx::strFindI(outputFileName, ".hdr") : saveAs;
+	if (saveAs.isEmpty() )
 	{
 		help("Output file format must be specified.");
 		return bx::kExitFailure;
@@ -868,38 +1057,50 @@ int main(int _argc, const char* _argv[])
 
 	Options options;
 
-	const char* edgeOpt = cmdLine.findOption("sdf");
-	if (NULL != edgeOpt)
+	const char* alphaRef = cmdLine.findOption("ref");
+	if (NULL != alphaRef)
 	{
-		options.sdf  = true;
-		if (!bx::fromString(&options.edge, edgeOpt) )
+		options.alphaTest = true;
+		if (!bx::fromString(&options.edge, alphaRef))
 		{
-			options.edge = 255.0f;
-		}
-	}
-	else
-	{
-		const char* alphaRef = cmdLine.findOption("ref");
-		if (NULL != alphaRef)
-		{
-			options.alphaTest = true;
-			if (!bx::fromString(&options.edge, alphaRef))
-			{
-				options.edge = 0.5f;
-			}
+			options.edge = 0.5f;
 		}
 	}
 
-	options.mips      = cmdLine.hasArg('m',  "mips");
-	options.normalMap = cmdLine.hasArg('n',  "normalmap");
+	options.sdf       = cmdLine.hasArg("sdf");
+	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");
+	options.linear    = cmdLine.hasArg("linear");
+
+	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` failed.");
+			return bx::kExitFailure;
+		}
+	}
+
+	const char* mipSkip = cmdLine.findOption("mipskip");
+	if (NULL != mipSkip)
+	{
+		if (!bx::fromString(&options.mipSkip, mipSkip) )
+		{
+			help("Parsing `--mipskip` failed.");
+			return bx::kExitFailure;
+		}
 	}
 
 	options.format = bimg::TextureFormat::Count;
@@ -915,7 +1116,7 @@ int main(int _argc, const char* _argv[])
 		}
 	}
 
-	if (NULL != bx::strFindI(saveAs, "png") )
+	if (!bx::strFindI(saveAs, "png").isEmpty() )
 	{
 		if (options.format == bimg::TextureFormat::Count)
 		{
@@ -927,7 +1128,7 @@ int main(int _argc, const char* _argv[])
 			return bx::kExitFailure;
 		}
 	}
-	else if (NULL != bx::strFindI(saveAs, "exr") )
+	else if (!bx::strFindI(saveAs, "exr").isEmpty() )
 	{
 		if (options.format == bimg::TextureFormat::Count)
 		{
@@ -954,6 +1155,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;
@@ -994,15 +1210,15 @@ int main(int _argc, const char* _argv[])
 		bx::FileWriter writer;
 		if (bx::open(&writer, outputFileName, false, &err) )
 		{
-			if (NULL != bx::strFindI(saveAs, "ktx") )
+			if (!bx::strFindI(saveAs, "ktx").isEmpty() )
 			{
 				bimg::imageWriteKtx(&writer, *output, output->m_data, output->m_size, &err);
 			}
-			else if (NULL != bx::strFindI(saveAs, "dds") )
+			else if (!bx::strFindI(saveAs, "dds").isEmpty() )
 			{
 				bimg::imageWriteDds(&writer, *output, output->m_data, output->m_size, &err);
 			}
-			else if (NULL != bx::strFindI(saveAs, "png") )
+			else if (!bx::strFindI(saveAs, "png").isEmpty() )
 			{
 				if (output->m_format != bimg::TextureFormat::RGBA8)
 				{
@@ -1019,9 +1235,10 @@ int main(int _argc, const char* _argv[])
 					, mip.m_data
 					, output->m_format
 					, false
-					, &err);
+					, &err
+					);
 			}
-			else if (NULL != bx::strFindI(saveAs, "exr") )
+			else if (!bx::strFindI(saveAs, "exr").isEmpty() )
 			{
 				bimg::ImageMip mip;
 				bimg::imageGetRawData(*output, 0, 0, output->m_data, output->m_size, mip);
@@ -1032,7 +1249,22 @@ int main(int _argc, const char* _argv[])
 					, mip.m_data
 					, output->m_format
 					, false
-					, &err);
+					, &err
+					);
+			}
+			else if (!bx::strFindI(saveAs, "hdr").isEmpty() )
+			{
+				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);

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно