Browse Source

texturev: Added support for loading .exr images.

Branimir Karadžić 9 years ago
parent
commit
af9122b209
4 changed files with 569 additions and 229 deletions
  1. 425 220
      3rdparty/tinyexr/tinyexr.h
  2. 142 8
      examples/common/bgfx_utils.cpp
  3. 1 1
      src/glcontext_egl.cpp
  4. 1 0
      tools/texturev/texturev.cpp

File diff suppressed because it is too large
+ 425 - 220
3rdparty/tinyexr/tinyexr.h


+ 142 - 8
examples/common/bgfx_utils.cpp

@@ -21,6 +21,12 @@ namespace stl = tinystl;
 #include "entry/entry.h"
 #include <ib-compress/indexbufferdecompression.h>
 
+BX_PRAGMA_DIAGNOSTIC_PUSH()
+BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC("-Wtype-limits")
+#define TINYEXR_IMPLEMENTATION
+#include <tinyexr/tinyexr.h>
+BX_PRAGMA_DIAGNOSTIC_POP()
+
 #define LODEPNG_NO_COMPILE_ENCODER
 #define LODEPNG_NO_COMPILE_DISK
 #define LODEPNG_NO_COMPILE_ANCILLARY_CHUNKS
@@ -161,6 +167,11 @@ extern "C" stbi_uc* stbi_load_from_memory(stbi_uc const* _buffer, int _len, int*
 extern "C" void stbi_image_free(void* _ptr);
 extern void lodepng_free(void* _ptr);
 
+static void exrRelease(void* _ptr)
+{
+	BX_FREE(entry::getAllocator(), _ptr);
+}
+
 bgfx::TextureHandle loadTexture(bx::FileReaderI* _reader, const char* _filePath, uint32_t _flags, uint8_t _skip, bgfx::TextureInfo* _info)
 {
 	if (NULL != bx::stristr(_filePath, ".dds")
@@ -196,6 +207,7 @@ bgfx::TextureHandle loadTexture(bx::FileReaderI* _reader, const char* _filePath,
 
 		uint8_t* out = NULL;
 		static uint8_t pngMagic[] = { 0x89, 0x50, 0x4E, 0x47, 0x0d, 0x0a };
+
 		if (0 == memcmp(data, pngMagic, sizeof(pngMagic) ) )
 		{
 			release = lodepng_free;
@@ -292,24 +304,146 @@ bgfx::TextureHandle loadTexture(bx::FileReaderI* _reader, const char* _filePath,
 		}
 		else
 		{
-			int comp = 0;
-			out = stbi_load_from_memory( (uint8_t*)data, size, (int*)&width, (int*)&height, &comp, 4);
+			EXRVersion exrVersion;
+			int result = ParseEXRVersionFromMemory(&exrVersion, (uint8_t*)data, size);
+			if (TINYEXR_SUCCESS == result)
+			{
+				const char* err = NULL;
+				EXRHeader exrHeader;
+				result = ParseEXRHeaderFromMemory(&exrHeader, &exrVersion, (uint8_t*)data, size, &err);
+				if (TINYEXR_SUCCESS == result)
+				{
+					EXRImage exrImage;
+					InitEXRImage(&exrImage);
+
+					result = LoadEXRImageFromMemory(&exrImage, &exrHeader, (uint8_t*)data, size, &err);
+					if (TINYEXR_SUCCESS == result)
+					{
+						uint8_t idxR = UINT8_MAX;
+						uint8_t idxG = UINT8_MAX;
+						uint8_t idxB = UINT8_MAX;
+						uint8_t idxA = UINT8_MAX;
+						for (uint8_t ii = 0, num = uint8_t(exrHeader.num_channels); ii < num; ++ii)
+						{
+							const EXRChannelInfo& channel = exrHeader.channels[ii];
+							if (UINT8_MAX == idxR
+							&&  0 == strcmp(channel.name, "R") )
+							{
+								idxR = ii;
+							}
+							else if (UINT8_MAX == idxG
+								 &&  0 == strcmp(channel.name, "G") )
+							{
+								idxG = ii;
+							}
+							else if (UINT8_MAX == idxB
+								 &&  0 == strcmp(channel.name, "B") )
+							{
+								idxB = ii;
+							}
+							else if (UINT8_MAX == idxA
+								 &&  0 == strcmp(channel.name, "A") )
+							{
+								idxA = ii;
+							}
+						}
+
+						if (UINT8_MAX != idxR)
+						{
+							const bool asFloat = exrHeader.pixel_types[idxR] == TINYEXR_PIXELTYPE_FLOAT;
+
+							uint32_t srcBpp = 32;
+							uint32_t dstBpp = asFloat ? 32 : 16;
+							format = asFloat ? bgfx::TextureFormat::R32F : bgfx::TextureFormat::R16F;
+							uint32_t stepR = 1;
+							uint32_t stepG = 0;
+							uint32_t stepB = 0;
+							uint32_t stepA = 0;
+
+							if (UINT8_MAX != idxG)
+							{
+								srcBpp += 32;
+								dstBpp = asFloat ? 64 : 32;
+								format = asFloat ? bgfx::TextureFormat::RG32F : bgfx::TextureFormat::RG16F;
+								stepG  = 1;
+							}
+
+							if (UINT8_MAX != idxB)
+							{
+								srcBpp += 32;
+								dstBpp = asFloat ? 128 : 64;
+								format = asFloat ? bgfx::TextureFormat::RGBA32F : bgfx::TextureFormat::RGBA16F;
+								stepB  = 1;
+							}
+
+							if (UINT8_MAX != idxA)
+							{
+								srcBpp += 32;
+								dstBpp = asFloat ? 128 : 64;
+								format = asFloat ? bgfx::TextureFormat::RGBA32F : bgfx::TextureFormat::RGBA16F;
+								stepA  = 1;
+							}
+
+							release = exrRelease;
+							out = (uint8_t*)BX_ALLOC(allocator, exrImage.width * exrImage.height * dstBpp/8);
+
+							const float zero = 0.0f;
+							const float* srcR = UINT8_MAX == idxR ? &zero : (const float*)(exrImage.images)[idxR];
+							const float* srcG = UINT8_MAX == idxG ? &zero : (const float*)(exrImage.images)[idxG];
+							const float* srcB = UINT8_MAX == idxB ? &zero : (const float*)(exrImage.images)[idxB];
+							const float* srcA = UINT8_MAX == idxA ? &zero : (const float*)(exrImage.images)[idxA];
+
+							const uint32_t bytesPerPixel = dstBpp/8;
+							for (uint32_t ii = 0, num = exrImage.width * exrImage.height; ii < num; ++ii)
+							{
+								float rgba[4] =
+								{
+									*srcR,
+									*srcG,
+									*srcB,
+									*srcA,
+								};
+								memcpy(&out[ii * bytesPerPixel], rgba, bytesPerPixel);
+
+								srcR += stepR;
+								srcG += stepG;
+								srcB += stepB;
+								srcA += stepA;
+							}
+						}
+
+						FreeEXRImage(&exrImage);
+					}
+
+					FreeEXRHeader(&exrHeader);
+				}
+			}
+			else
+			{
+				int comp = 0;
+				out = stbi_load_from_memory( (uint8_t*)data, size, (int*)&width, (int*)&height, &comp, 4);
+			}
 		}
 
 		BX_FREE(allocator, data);
 
 		if (NULL != out)
 		{
-			handle = bgfx::createTexture2D(uint16_t(width), uint16_t(height), false, 1
-											, format
-											, _flags
-											, bgfx::copy(out, width*height*bpp/8)
-											);
+			handle = bgfx::createTexture2D(
+				  uint16_t(width)
+				, uint16_t(height)
+				, false
+				, 1
+				, format
+				, _flags
+				, bgfx::copy(out, width*height*bpp/8)
+				);
 			release(out);
 
 			if (NULL != _info)
 			{
-				bgfx::calcTextureSize(*_info
+				bgfx::calcTextureSize(
+					  *_info
 					, uint16_t(width)
 					, uint16_t(height)
 					, 0

+ 1 - 1
src/glcontext_egl.cpp

@@ -262,7 +262,7 @@ EGL_IMPORT
 
 #	if BX_PLATFORM_RPI
 				BX_UNUSED(hasEglKhrCreateContext, hasEglKhrNoError);
-#else
+#	else
 				if (hasEglKhrCreateContext)
 				{
 					bx::write(&writer, EGLint(EGL_CONTEXT_MAJOR_VERSION_KHR) );

+ 1 - 0
tools/texturev/texturev.cpp

@@ -49,6 +49,7 @@ static const char* s_supportedExt[] =
 {
 	"bmp",
 	"dds",
+	"exr",
 	"jpg",
 	"jpeg",
 	"hdr",

Some files were not shown because too many files changed in this diff