Explorar el Código

ASTC normal map support

- Update astc to 57af6af from https://github.com/andrewwillmott/astc-encoder
- Expand bimg::Quality to include source-as-normal-map
  modes, intended as a hint to the encoder.
- Hook this up for ASTC, and in texturec
Andrew Willmott hace 6 años
padre
commit
73fa013ec0

+ 0 - 1
3rdparty/astc/astc_codec_internals.h

@@ -19,7 +19,6 @@
 
 #include <stdint.h>
 #include <stdlib.h>
-#include <math.h>
 #include "mathlib.h"
 
 #ifndef MIN

+ 53 - 170
3rdparty/astc/astc_lib.cpp

@@ -52,6 +52,8 @@ namespace
     {
         { 0, 1, 2, 3 }, // ASTC_RGBA
         { 2, 1, 0, 3 }, // ASTC_BGRA
+        { 0, 0, 0, 1 }, // ASTC_ENC_NORMAL_RA
+        { 0, 3, 6, 5 }, // ASTC_DEC_RA_NORMAL
     };
 
     void alloc_temp_buffers(compress_symbolic_block_buffers* temp_buffers)
@@ -272,197 +274,64 @@ namespace
 
     void setup_ewp(ASTC_COMPRESS_MODE mode, int ydim, int xdim, error_weighting_params& ewp)
     {
-        float oplimit_autoset    = 0.0;
-        float dblimit_autoset_2d = 0.0;
-        float bmc_autoset        = 0.0;
-        float mincorrel_autoset  = 0.0;
+        float oplimit    = 0.0;
+        float dblimit_2d = 0.0;
+        float bmc        = 0.0;
+        float mincorrel  = 0.0;
 
-        int plimit_autoset       = -1;
-        int maxiters_autoset     = 0;
-        int pcdiv                = 1;
+        int plimit       = -1;
+        int maxiters     = 0;
 
         float log10_texels_2d = log((float)(xdim * ydim)) / log(10.0f);
 
         if (mode == ASTC_COMPRESS_VERY_FAST)
         {
-            plimit_autoset = 2;
-            oplimit_autoset = 1.0;
-            dblimit_autoset_2d = MAX(70 - 35 * log10_texels_2d, 53 - 19 * log10_texels_2d);
-            bmc_autoset = 25;
-            mincorrel_autoset = 0.5;
-            maxiters_autoset = 1;
-
-            switch (ydim)
-            {
-            case 4:
-                pcdiv = 240;
-                break;
-            case 5:
-                pcdiv = 56;
-                break;
-            case 6:
-                pcdiv = 64;
-                break;
-            case 8:
-                pcdiv = 47;
-                break;
-            case 10:
-                pcdiv = 36;
-                break;
-            case 12:
-                pcdiv = 30;
-                break;
-            default:
-                pcdiv = 30;
-                break;
-            }
+            plimit = 2;
+            oplimit = 1.0;
+            dblimit_2d = MAX(70 - 35 * log10_texels_2d, 53 - 19 * log10_texels_2d);
+            bmc = 25;
+            mincorrel = 0.5;
+            maxiters = 1;
         }
         else if (mode == ASTC_COMPRESS_FAST)
         {
-            plimit_autoset = 4;
-            oplimit_autoset = 1.0;
-            mincorrel_autoset = 0.5;
-            dblimit_autoset_2d = MAX(85 - 35 * log10_texels_2d, 63 - 19 * log10_texels_2d);
-            bmc_autoset = 50;
-            maxiters_autoset = 1;
-
-            switch (ydim)
-            {
-            case 4:
-                pcdiv = 60;
-                break;
-            case 5:
-                pcdiv = 27;
-                break;
-            case 6:
-                pcdiv = 30;
-                break;
-            case 8:
-                pcdiv = 24;
-                break;
-            case 10:
-                pcdiv = 16;
-                break;
-            case 12:
-                pcdiv = 20;
-                break;
-            default:
-                pcdiv = 20;
-                break;
-            };
+            plimit = 4;
+            oplimit = 1.0;
+            mincorrel = 0.5;
+            dblimit_2d = MAX(85 - 35 * log10_texels_2d, 63 - 19 * log10_texels_2d);
+            bmc = 50;
+            maxiters = 1;
         }
         else if (mode == ASTC_COMPRESS_MEDIUM)
         {
-            plimit_autoset = 25;
-            oplimit_autoset = 1.2f;
-            mincorrel_autoset = 0.75f;
-            dblimit_autoset_2d = MAX(95 - 35 * log10_texels_2d, 70 - 19 * log10_texels_2d);
-            bmc_autoset = 75;
-            maxiters_autoset = 2;
-
-            switch (ydim)
-            {
-            case 4:
-                pcdiv = 25;
-                break;
-            case 5:
-                pcdiv = 15;
-                break;
-            case 6:
-                pcdiv = 15;
-                break;
-            case 8:
-                pcdiv = 10;
-                break;
-            case 10:
-                pcdiv = 8;
-                break;
-            case 12:
-                pcdiv = 6;
-                break;
-            default:
-                pcdiv = 6;
-                break;
-            };
+            plimit = 25;
+            oplimit = 1.2f;
+            mincorrel = 0.75f;
+            dblimit_2d = MAX(95 - 35 * log10_texels_2d, 70 - 19 * log10_texels_2d);
+            bmc = 75;
+            maxiters = 2;
         }
         else if (mode == ASTC_COMPRESS_THOROUGH)
         {
-            plimit_autoset = 100;
-            oplimit_autoset = 2.5f;
-            mincorrel_autoset = 0.95f;
-            dblimit_autoset_2d = MAX(105 - 35 * log10_texels_2d, 77 - 19 * log10_texels_2d);
-            bmc_autoset = 95;
-            maxiters_autoset = 4;
-
-            switch (ydim)
-            {
-            case 4:
-                pcdiv = 12;
-                break;
-            case 5:
-                pcdiv = 7;
-                break;
-            case 6:
-                pcdiv = 7;
-                break;
-            case 8:
-                pcdiv = 5;
-                break;
-            case 10:
-                pcdiv = 4;
-                break;
-            case 12:
-                pcdiv = 3;
-                break;
-            default:
-                pcdiv = 3;
-                break;
-            };
+            plimit = 100;
+            oplimit = 2.5f;
+            mincorrel = 0.95f;
+            dblimit_2d = MAX(105 - 35 * log10_texels_2d, 77 - 19 * log10_texels_2d);
+            bmc = 95;
+            maxiters = 4;
         }
         else if (mode == ASTC_COMPRESS_EXHAUSTIVE)
         {
-            plimit_autoset = PARTITION_COUNT;
-            oplimit_autoset = 1000.0f;
-            mincorrel_autoset = 0.99f;
-            dblimit_autoset_2d = 999.0f;
-            bmc_autoset = 100;
-            maxiters_autoset = 4;
-
-            switch (ydim)
-            {
-            case 4:
-                pcdiv = 3;
-                break;
-            case 5:
-                pcdiv = 1;
-                break;
-            case 6:
-                pcdiv = 1;
-                break;
-            case 8:
-                pcdiv = 1;
-                break;
-            case 10:
-                pcdiv = 1;
-                break;
-            case 12:
-                pcdiv = 1;
-                break;
-            default:
-                pcdiv = 1;
-                break;
-            }
+            plimit = PARTITION_COUNT;
+            oplimit = 1000.0f;
+            mincorrel = 0.99f;
+            dblimit_2d = 999.0f;
+            bmc = 100;
+            maxiters = 4;
         }
 
-        int partitions_to_test = plimit_autoset;
-        float dblimit_2d = dblimit_autoset_2d;
-        float oplimit = oplimit_autoset;
-        float mincorrel = mincorrel_autoset;
-
-        int maxiters = maxiters_autoset;
         ewp.max_refinement_iters = maxiters;
-
-        ewp.block_mode_cutoff = bmc_autoset / 100.0f;
+        ewp.block_mode_cutoff = bmc / 100.0f;
 
         float texel_avg_error_limit_2d;
 
@@ -477,6 +346,7 @@ namespace
         ewp.partition_1_to_2_limit = oplimit;
         ewp.lowest_correlation_cutoff = mincorrel;
 
+        int partitions_to_test = plimit;
         if (partitions_to_test < 1)
             partitions_to_test = 1;
         else if (partitions_to_test > PARTITION_COUNT)
@@ -487,6 +357,18 @@ namespace
 
         expand_block_artifact_suppression(xdim, ydim, 1, &ewp);
     }
+
+    void setup_ewp(ASTC_CHANNELS channels, error_weighting_params& ewp)
+    {
+        if (channels == ASTC_ENC_NORMAL_RA)
+        {
+            ewp.rgba_weights[0] = 1.0f;
+            ewp.rgba_weights[1] = 0.01f;
+            ewp.rgba_weights[2] = 0.01f;
+            ewp.rgba_weights[3] = 1.0f;
+            ewp.ra_normal_angular_scale = 1;
+        }
+    }
 }
 
 size_t astc_compressed_size(int w, int h, int bw, int bh)
@@ -517,6 +399,7 @@ void astc_compress
     error_weighting_params ewp;
     init_ewp(ewp);
     setup_ewp(compress_mode, block_width, block_height, ewp);
+    setup_ewp(src_channels, ewp);   // For special-case encoding of some channel types such as normals
 
     if (src_stride == 0)
         src_stride = src_width * 4;

+ 4 - 2
3rdparty/astc/astc_lib.h

@@ -30,8 +30,10 @@ enum ASTC_DECODE_MODE
 
 enum ASTC_CHANNELS
 {
-    ASTC_RGBA,
-    ASTC_BGRA
+    ASTC_RGBA,               // Encode/decode into RGBA
+    ASTC_BGRA,               // Encode/decode into BGRA
+    ASTC_ENC_NORMAL_RA,      // Encode normal XYZ as XY in RA with reconstructed Z
+    ASTC_DEC_RA_NORMAL,      // Decode RA into XY and reconstructed Z
 };
 
 

+ 1 - 1
3rdparty/astc/mathlib.cpp

@@ -61,7 +61,7 @@ float nan(int p)
 	return v.q;
 }
 
-#if !defined(_MSC_VER) && (__cplusplus < 201103L)
+#if !_MSC_VER && !__clang__ && (__cplusplus < 201103L)
 float fmax(float p, float q)
 {
 	if (p != p)

+ 1 - 1
3rdparty/astc/mathlib.h

@@ -27,7 +27,7 @@ float cospi(float p);
 
 float nan(int p);
 
-#if !defined(_MSC_VER) && (__cplusplus < 201103L)
+#if !_MSC_VER && !__clang__ && (__cplusplus < 201103L)
 float fmax(float p, float q);
 float fmin(float p, float q);
 #endif  // C++11

+ 4 - 0
include/bimg/encode.h

@@ -18,6 +18,10 @@ namespace bimg
 			Highest,
 			Fastest,
 
+			NormalMap_Default,  // Treat the source as a normal map
+			NormalMap_Highest,
+			NormalMap_Fastest,
+
 			Count
 		};
 	};

+ 14 - 1
src/image_encode.cpp

@@ -30,6 +30,11 @@ namespace bimg
 {
 	static uint32_t s_squishQuality[] =
 	{
+		// Standard
+		squish::kColourClusterFit,          // Default
+		squish::kColourIterativeClusterFit, // Highest
+		squish::kColourRangeFit,            // Fastest
+		// Normal map
 		squish::kColourClusterFit,          // Default
 		squish::kColourIterativeClusterFit, // Highest
 		squish::kColourRangeFit,            // Fastest
@@ -38,6 +43,11 @@ namespace bimg
 
 	static const ASTC_COMPRESS_MODE s_astcQuality[] =
 	{
+		// Standard
+		ASTC_COMPRESS_MEDIUM,       // Default
+		ASTC_COMPRESS_THOROUGH,     // Highest
+		ASTC_COMPRESS_FAST,         // Fastest
+		// Normal map
 		ASTC_COMPRESS_MEDIUM,       // Default
 		ASTC_COMPRESS_THOROUGH,     // Highest
 		ASTC_COMPRESS_FAST,         // Fastest
@@ -143,7 +153,10 @@ namespace bimg
 					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);
+                    if (Quality::NormalMap_Default <= _quality)
+                        astc_compress(_width, _height, src, ASTC_ENC_NORMAL_RA, srcPitch, astcBlockInfo.blockWidth, astcBlockInfo.blockHeight, compress_mode, decode_mode, dst);
+                    else
+                        astc_compress(_width, _height, src, ASTC_RGBA, srcPitch, astcBlockInfo.blockWidth, astcBlockInfo.blockHeight, compress_mode, decode_mode, dst);
 				}
 				break;
 

+ 4 - 3
tools/texturec/texturec.cpp

@@ -450,6 +450,7 @@ bimg::ImageContainer* convert(bx::AllocatorI* _allocator, const void* _inputData
 						, rgba
 						);
 
+                    bimg::Quality::Enum nmapQuality = bimg::Quality::Enum(_options.quality + bimg::Quality::NormalMap_Default);
 					bimg::imageEncodeFromRgba32f(_allocator
 						, dstData
 						, rgbaDst
@@ -457,7 +458,7 @@ bimg::ImageContainer* convert(bx::AllocatorI* _allocator, const void* _inputData
 						, dstMip.m_height
 						, dstMip.m_depth
 						, outputFormat
-						, _options.quality
+						, nmapQuality
 						, _err
 						);
 
@@ -489,7 +490,7 @@ bimg::ImageContainer* convert(bx::AllocatorI* _allocator, const void* _inputData
 							, dstMip.m_height
 							, dstMip.m_depth
 							, outputFormat
-							, _options.quality
+							, nmapQuality
 							, _err
 							);
 					}
@@ -1362,7 +1363,7 @@ int main(int _argc, const char* _argv[])
 	}
 	else
 	{
-		help(NULL, err);
+		help("Failed to create output", err);
 		return bx::kExitFailure;
 	}