From 6c25d5655129825e3835d92f314b39c91ad35c49 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= <branimirkaradzic@gmail.com>
Date: Wed, 6 Jan 2016 18:15:05 -0800
Subject: [PATCH] texturec: Added basic normalmap mipmap filter.

---
 src/image.cpp               | 82 +++++++++++++++++++------------------
 tools/texturec/texturec.cpp | 45 +++++++++++++-------
 2 files changed, 74 insertions(+), 53 deletions(-)

diff --git a/src/image.cpp b/src/image.cpp
index fc1b1273..499b54f7 100644
--- a/src/image.cpp
+++ b/src/image.cpp
@@ -469,28 +469,29 @@ namespace bgfx
 			return;
 		}
 
-		float* dst = (float*)_dst;
-		const float* src = (const float*)_src;
+		const uint8_t* src = (const uint8_t*)_src;
+		uint8_t* dst = (uint8_t*)_dst;
 
 		for (uint32_t yy = 0, ystep = _pitch*2; yy < dstheight; ++yy, src += ystep)
 		{
-			const float* rgba = src;
-			for (uint32_t xx = 0; xx < dstwidth; ++xx, rgba += 8, dst += 4)
+			const float* rgba0 = (const float*)&src[0];
+			const float* rgba1 = (const float*)&src[_pitch];
+			for (uint32_t xx = 0; xx < dstwidth; ++xx, rgba0 += 8, rgba1 += 8, dst += 16)
 			{
 				float xyz[3];
-				xyz[0]  = rgba[       0];
-				xyz[1]  = rgba[       1];
-				xyz[2]  = rgba[       2];
-				xyz[0] += rgba[       4];
-				xyz[1] += rgba[       5];
-				xyz[2] += rgba[       6];
-				xyz[0] += rgba[_pitch+0];
-				xyz[1] += rgba[_pitch+1];
-				xyz[2] += rgba[_pitch+2];
-				xyz[0] += rgba[_pitch+4];
-				xyz[1] += rgba[_pitch+5];
-				xyz[2] += rgba[_pitch+6];
-				bx::vec3Norm(dst, xyz);
+				xyz[0]  = rgba0[0];
+				xyz[1]  = rgba0[1];
+				xyz[2]  = rgba0[2];
+				xyz[0] += rgba0[4];
+				xyz[1] += rgba0[5];
+				xyz[2] += rgba0[6];
+				xyz[0] += rgba1[0];
+				xyz[1] += rgba1[1];
+				xyz[2] += rgba1[2];
+				xyz[0] += rgba1[4];
+				xyz[1] += rgba1[5];
+				xyz[2] += rgba1[6];
+				bx::vec3Norm( (float*)dst, xyz);
 			}
 		}
 	}
@@ -2496,36 +2497,39 @@ namespace bgfx
 	void imageDecodeToRgba32f(bx::AllocatorI* _allocator, void* _dst, const void* _src, uint32_t _width, uint32_t _height, uint32_t _pitch, TextureFormat::Enum _format)
 	{
 		const uint8_t* src = (const uint8_t*)_src;
-		float* dst = (float*)_dst;
-
-		uint32_t width  = _width/4;
-		uint32_t height = _height/4;
+		uint8_t* dst = (uint8_t*)_dst;
 
 		switch (_format)
 		{
 		case TextureFormat::BC5:
-			for (uint32_t yy = 0; yy < height; ++yy)
 			{
-				for (uint32_t xx = 0; xx < width; ++xx)
+				uint32_t width  = _width/4;
+				uint32_t height = _height/4;
+
+				for (uint32_t yy = 0; yy < height; ++yy)
 				{
-					uint8_t temp[16*4];
-
-					decodeBlockDxt45A(temp+1, src);
-					src += 8;
-					decodeBlockDxt45A(temp+2, src);
-					src += 8;
-
-					for (uint32_t ii = 0; ii < 16; ++ii)
+					for (uint32_t xx = 0; xx < width; ++xx)
 					{
-						float nx = temp[ii*4+2]*2.0f/255.0f - 1.0f;
-						float ny = temp[ii*4+1]*2.0f/255.0f - 1.0f;
-						float nz = sqrtf(1.0f - nx*nx - ny*ny);
+						uint8_t temp[16*4];
 
-						float* block = &dst[( (yy + ii/4)*_pitch+xx*4+ii%4)*16];
-						block[0] = nx;
-						block[1] = ny;
-						block[2] = nz;
-						block[3] = 0.0f;
+						decodeBlockDxt45A(temp+1, src);
+						src += 8;
+						decodeBlockDxt45A(temp+2, src);
+						src += 8;
+
+						for (uint32_t ii = 0; ii < 16; ++ii)
+						{
+							float nx = temp[ii*4+2]*2.0f/255.0f - 1.0f;
+							float ny = temp[ii*4+1]*2.0f/255.0f - 1.0f;
+							float nz = sqrtf(1.0f - nx*nx - ny*ny);
+
+							const uint32_t offset = (yy + ii/4)*_pitch + (xx*4 + ii%4)*16;
+							float* block = (float*)&dst[offset];
+							block[0] = nx;
+							block[1] = ny;
+							block[2] = nz;
+							block[3] = 0.0f;
+						}
 					}
 				}
 			}
diff --git a/tools/texturec/texturec.cpp b/tools/texturec/texturec.cpp
index 25207f5f..3bee4fe7 100644
--- a/tools/texturec/texturec.cpp
+++ b/tools/texturec/texturec.cpp
@@ -331,6 +331,19 @@ int main(int _argc, const char* _argv[])
 						, mip.m_format
 						);
 
+					for (uint32_t yy = 0; yy < mip.m_height; ++yy)
+					{
+						for (uint32_t xx = 0; xx < mip.m_width; ++xx)
+						{
+							const uint32_t offset = (yy*mip.m_width + xx) * 4;
+							float* inout = &rgba[offset];
+							inout[0] = inout[0] * 2.0f/255.0f - 1.0f;
+							inout[1] = inout[1] * 2.0f/255.0f - 1.0f;
+							inout[2] = inout[2] * 2.0f/255.0f - 1.0f;
+							inout[3] = inout[3] * 2.0f/255.0f - 1.0f;
+						}
+					}
+
 					imageContainer.m_numMips = numMips;
 					imageContainer.m_size    = imageGetSize(format, mip.m_width, mip.m_height, 0, false, numMips);
 					imageContainer.m_format  = format;
@@ -340,14 +353,12 @@ int main(int _argc, const char* _argv[])
 
 					for (uint8_t lod = 1; lod < numMips; ++lod)
 					{
-						ImageMip mip1;
-						imageGetRawData(imageContainer, 0, lod, output->data, output->size, mip1);
-						uint8_t* data = const_cast<uint8_t*>(mip1.m_data);
+						imageRgba32fDownsample2x2NormalMap(mip.m_width, mip.m_height, mip.m_width*16, rgba, rgba);
 
-						uint32_t width  = bx::uint32_max(1, mip.m_width >>lod);
-						uint32_t height = bx::uint32_max(1, mip.m_height>>lod);
-						imageRgba32fDownsample2x2NormalMap(width, height, width*16, rgba, rgba);
-						imageEncodeFromRgba32f(data, rgba, width, height, format);
+						ImageMip dstMip;
+						imageGetRawData(imageContainer, 0, lod, output->data, output->size, dstMip);
+						uint8_t* data = const_cast<uint8_t*>(dstMip.m_data);
+						imageEncodeFromRgba32f(data, rgba, dstMip.m_width, dstMip.m_height, format);
 					}
 				}
 				else
@@ -356,6 +367,14 @@ int main(int _argc, const char* _argv[])
 					temp = BX_ALLOC(&allocator, size);
 					uint8_t* rgba = (uint8_t*)temp;
 
+					imageDecodeToRgba8(rgba
+						, mip.m_data
+						, mip.m_width
+						, mip.m_height
+						, mip.m_width*mip.m_bpp/8
+						, mip.m_format
+						);
+
 					imageContainer.m_numMips = numMips;
 					imageContainer.m_size    = imageGetSize(format, mip.m_width, mip.m_height, 0, false, numMips);
 					imageContainer.m_format  = format;
@@ -365,14 +384,12 @@ int main(int _argc, const char* _argv[])
 
 					for (uint8_t lod = 1; lod < numMips; ++lod)
 					{
-						ImageMip mip1;
-						imageGetRawData(imageContainer, 0, lod, output->data, output->size, mip1);
-						uint8_t* data = const_cast<uint8_t*>(mip1.m_data);
+						imageRgba8Downsample2x2(mip.m_width, mip.m_height, mip.m_width*4, rgba, rgba);
 
-						uint32_t width  = bx::uint32_max(1, mip.m_width >>lod);
-						uint32_t height = bx::uint32_max(1, mip.m_height>>lod);
-						imageRgba8Downsample2x2(width, height, width*4, rgba, rgba);
-						imageEncodeFromRgba8(data, rgba, width, height, format);
+						ImageMip dstMip;
+						imageGetRawData(imageContainer, 0, lod, output->data, output->size, dstMip);
+						uint8_t* data = const_cast<uint8_t*>(dstMip.m_data);
+						imageEncodeFromRgba8(data, rgba, dstMip.m_width, dstMip.m_height, format);
 					}
 				}