@@ -135,15 +135,15 @@ astcEncoderMode(const char* mode) {
135135// so the table below has to be laboriously done in html.
136136//! [scApp options]
137137 <dl>
138- <dt>--encode <astc| etc1s| uastc></dt>
138+ <dt>--encode <astc | etc1s | uastc></dt>
139139 <dd>Compress the image data to ASTC, transcodable ETC1S / BasisLZ or
140140 high-quality transcodable UASTC format. Implies @b --t2.
141141 With each encoding option the following encoder specific options
142142 become valid, otherwise they are ignored.</dd>
143143 <dl>
144144 <dt>astc:</dt>
145145 <dd>Create a texture in high-quality ASTC format.</dd>
146- <dt>--astc_blk_d <XxY| XxYxZ></dt>
146+ <dt>--astc_blk_d <XxY | XxYxZ></dt>
147147 <dd>Specify which block dimension to use for compressing the textures.
148148 e.g. @b --astc_blk_d 6x5 for 2D or @b --astc_blk_d 6x6x6 for 3D.
149149 6x6 is default for 2D.
@@ -175,7 +175,7 @@ astcEncoderMode(const char* mode) {
175175 <tr><td>6x6x5</td> <td>0.71 bpp</td></tr>
176176 <tr><td>6x6x6</td> <td>0.59 bpp</td></tr>
177177 </table></dd>
178- <dt>--astc_mode <ldr| hdr></dt>
178+ <dt>--astc_mode <ldr | hdr></dt>
179179 <dd>Specify which encoding mode to use. LDR is the default unless the input.
180180 image is 16-bit in which case the default is HDR.</dd>
181181 <dt>--astc_quality <level></dt>
@@ -302,20 +302,32 @@ astcEncoderMode(const char* mode) {
302302 deterministic).</dd>
303303 </dl>
304304 <dt>--normal_mode</dt>
305- <dd>For ASTC encoder '@b --encode astc' assumes the input texture is
306- a three component linear LDR normal map storing unit length
307- normals as (R=X, G=Y, B=Z). The output will be a two component
308- X+Y normal map stored as (RGB=X, A=Y), optimized for angular
309- error instead of simple PSNR. The Z component can be recovered
310- programmatically in shader code by using the equation:
305+ <dd>Only valid for linear textures with two or more components.
306+ If the input texture has three or four linear components it is assumed to
307+ be a three component linear normal map storing unit length
308+ normals as (R=X, G=Y, B=Z). A fourth component will be ignored. The map will be
309+ converted to a two component X+Y normal map stored as (RGB=X, A=Y) prior to
310+ encoding. If unsure that your normals are unit length, use @b --normalize.
311+ If the input has 2 linear components it is assumed to be an X+Y map of unit normals.
312+
313+ The Z component can be recovered programmatically in shader
314+ code by using the equations:
311315 <pre>
312316 nml.xy = texture(...).ga; // Load in [0,1]
313317 nml.xy = nml.xy * 2.0 - 1.0; // Unpack to [-1,1]
314318 nml.z = sqrt(1 - dot(nml.xy, nml.xy)); // Compute Z
315319 </pre>
316- For ETC1S encoder '@b --encode etc1s' tunes codec parameters for
317- better quality on normal maps (no selector RDO, no endpoint RDO).
318- Only valid for linear textures.</dd>
320+ Encoding is optimized for normal maps. For ASTC encoding,
321+ '--encode astc', the encoder is directed to optimize for angular
322+ error instead of simple PSNR. For ETC1S encoding, '@b --encode etc1s',
323+ RDO is disabled (no selector RDO, no endpoint RDO) to provide
324+ better quality.</dd>
325+ <dt>--normalize</dt>
326+ <dd>Normalize input normals to have a unit length. Only valid for
327+ linear textures with 2 or more components. For 2-component inputs 2D
328+ unit normals are calculated. Do not use this to generate X+Y normals
329+ for --normal_mode. For 4-component inputs a 3D unit normal is calculated.
330+ 1.0 is used for the value of the 4th component.</dd>
319331 <dt>--no_sse</dt>
320332 <dd>Forbid use of the SSE instruction set. Ignored if CPU does not
321333 support SSE. Only the Basis Universal compressor uses SSE.</dd>
@@ -433,13 +445,15 @@ class scApp : public ktxApp {
433445 mode.clear ();
434446 qualityLevel.clear ();
435447 normalMap = false ;
448+ for (int i = 0 ; i < 4 ; i++) inputSwizzle[i] = 0 ;
436449 }
437450 };
438451 int ktx2;
439452 int etc1s;
440453 int zcmp;
441454 int astc;
442455 ktx_bool_t normalMode;
456+ ktx_bool_t normalize;
443457 clamped<ktx_uint32_t > zcmpLevel;
444458 clamped<ktx_uint32_t > threadCount;
445459 struct basisOptions bopts;
@@ -454,6 +468,7 @@ class scApp : public ktxApp {
454468 zcmp = false ;
455469 astc = false ;
456470 normalMode = false ;
471+ normalize = false ;
457472 }
458473 };
459474
@@ -486,14 +501,14 @@ class scApp : public ktxApp {
486501 void usage ()
487502 {
488503 cerr <<
489- " --encode <astc| etc1s| uastc>\n "
504+ " --encode <astc | etc1s | uastc>\n "
490505 " Compress the image data to ASTC, transcodable ETC1S / BasisLZ or\n "
491506 " high-quality transcodable UASTC format. Implies --t2.\n "
492507 " With each encoding option the following encoder specific options\n "
493508 " become valid, otherwise they are ignored.\n\n "
494509 " astc:\n "
495510 " Create a texture in high-quality ASTC format.\n "
496- " --astc_blk_d <XxY| XxYxZ>\n "
511+ " --astc_blk_d <XxY | XxYxZ>\n "
497512 " Specify which block dimension to use for compressing the textures.\n "
498513 " e.g. --astc_blk_d 6x5 for 2D or --astc_blk_d 6x6x6 for 3D.\n "
499514 " 6x6 is default for 2D.\n\n "
@@ -511,7 +526,7 @@ class scApp : public ktxApp {
511526 " 4x4x3: 2.67 bpp 6x5x5: 0.85 bpp\n "
512527 " 4x4x4: 2.00 bpp 6x6x5: 0.71 bpp\n "
513528 " 5x4x4: 1.60 bpp 6x6x6: 0.59 bpp\n "
514- " --astc_mode <ldr| hdr>\n "
529+ " --astc_mode <ldr | hdr>\n "
515530 " Specify which encoding mode to use. LDR is the default unless the input.\n "
516531 " image is 16-bit in which case the default is HDR.\n "
517532 " --astc_quality <level>\n "
@@ -630,18 +645,29 @@ class scApp : public ktxApp {
630645 " Disable RDO multithreading (slightly higher compression,\n "
631646 " deterministic).\n\n "
632647 " --normal_mode\n "
633- " For ASTC encoder '--encode astc' assumes the input texture is\n "
634- " a three component linear LDR normal map storing unit length\n "
635- " normals as (R=X, G=Y, B=Z). The output will be a two component\n "
636- " X+Y normal map stored as (RGB=X, A=Y), optimized for angular\n "
637- " error instead of simple PSNR. The Z component can be recovered\n "
638- " programmatically in shader code by using the equation:\n\n "
648+ " Only valid for linear textures with two or more components.\n "
649+ " If the input texture has three or four linear components it is assumed to\n "
650+ " be a three component linear normal map storing unit length\n "
651+ " normals as (R=X, G=Y, B=Z). A fourth component will be ignored. The map will be\n "
652+ " converted to a two component X+Y normal map stored as (RGB=X, A=Y) prior to\n "
653+ " encoding. If unsure that your normals are unit length, use @b --normalize.\n "
654+ " If the input has 2 linear components it is assumed to be an X+Y map of unit normals.\n\n "
655+ " The Z component can be recovered programmatically in shader\n "
656+ " code by using the equations:\n\n "
639657 " nml.xy = texture(...).ga; // Load in [0,1]\n "
640658 " nml.xy = nml.xy * 2.0 - 1.0; // Unpack to [-1,1]\n "
641659 " nml.z = sqrt(1 - dot(nml.xy, nml.xy)); // Compute Z\n\n "
642- " For ETC1S encoder '--encode etc1s' tunes codec parameters for \n "
643- " better quality on normal maps (no selector RDO, no endpoint RDO).\n "
644- " Only valid for linear textures.\n "
660+ " Encoding is optimized for normal maps. For ASTC encoding,\n "
661+ " '--encode astc', the encoder is directed to optimize for angular\n "
662+ " error instead of simple PSNR. For ETC1S encoding, '--encode etc1s',\n "
663+ " RDO is disabled (no selector RDO, no endpoint RDO) to provide \n "
664+ " better quality.\n\n "
665+ " --normalize\n "
666+ " Normalize input normals to have a unit length. Only valid for\n "
667+ " linear textures with 2 or more components. For 2-component inputs 2D\n "
668+ " unit normals are calculated. Do not use this to generate X+Y normals \n "
669+ " for --normal_mode. For 4-component inputs a 3D unit normal is calculated.\n "
670+ " 1.0 is used for the value of the 4th component."
645671 " --no_sse\n "
646672 " Forbid use of the SSE instruction set. Ignored if CPU does not\n "
647673 " support SSE. Only the Basis Universal compressor uses SSE.\n "
@@ -707,9 +733,10 @@ scApp::scApp(string& version, string& defaultVersion,
707733 { " astc_mode" , argparser::option::required_argument, NULL , 1013 },
708734 { " astc_quality" , argparser::option::required_argument, NULL , 1014 },
709735 { " encode" , argparser::option::required_argument, NULL , 1015 },
736+ { " normalize" , argparser::option::no_argument, NULL , 1016 },
710737 // Deprecated options
711738 { " bcmp" , argparser::option::no_argument, NULL , ' b' },
712- { " uastc" , argparser::option::optional_argument, NULL , 1016 }
739+ { " uastc" , argparser::option::optional_argument, NULL , 1017 }
713740 };
714741 const int lastOptionIndex = sizeof (my_option_list)
715742 / sizeof (argparser::option);
@@ -757,7 +784,7 @@ scApp::processOption(argparser& parser, int opt)
757784 switch (opt) {
758785 case ' z' :
759786 if (options.etc1s ) {
760- cerr << " Only one of '--encode etc1s| --bcmp' and --zcmp can be specified."
787+ cerr << " Only one of '--encode etc1s | --bcmp' and --zcmp can be specified."
761788 << endl;
762789 usage ();
763790 exit (1 );
@@ -881,7 +908,7 @@ scApp::processOption(argparser& parser, int opt)
881908 exit (1 );
882909 }
883910 if (options.bopts .uastc ) {
884- cerr << " Only one of --bcmp and '--encode etc1s| --uastc' can be specified.\n "
911+ cerr << " Only one of --bcmp and '--encode etc1s | --uastc' can be specified.\n "
885912 << " --bcmp is deprecated, use '--encode etc1s' instead."
886913 << endl;
887914 usage ();
@@ -893,10 +920,14 @@ scApp::processOption(argparser& parser, int opt)
893920 case 1015 :
894921 setEncoder (parser.optarg );
895922 options.ktx2 = 1 ;
923+ hasArg = true ;
896924 break ;
897925 case 1016 :
926+ options.normalize = true ;
927+ break ;
928+ case 1017 :
898929 if (options.etc1s ) {
899- cerr << " Only one of `--encode etc1s| --bcmp` and `--uastc [<level>]` can be specified."
930+ cerr << " Only one of `--encode etc1s | --bcmp` and `--uastc [<level>]` can be specified."
900931 << endl;
901932 usage ();
902933 exit (1 );
0 commit comments