diff --git a/src/nvtt/CompressorDX9.cpp b/src/nvtt/CompressorDX9.cpp index e9bf91c..53f979c 100644 --- a/src/nvtt/CompressorDX9.cpp +++ b/src/nvtt/CompressorDX9.cpp @@ -111,8 +111,8 @@ void FastCompressorDXT5n::compressBlock(ColorBlock & rgba, nvtt::AlphaMode alpha QuickCompress::compressDXT5(rgba, block); } -#if 0 -void NormalCompressorDXT1::compressBlock(ColorSet & set, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output) +#if 1 +void CompressorDXT1::compressBlock(ColorSet & set, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output) { set.setUniformWeights(); set.createMinimalSet(false); @@ -146,7 +146,7 @@ void NormalCompressorDXT1::compressBlock(ColorSet & set, nvtt::AlphaMode alphaMo } } #else -void NormalCompressorDXT1::compressBlock(ColorBlock & rgba, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output) +void CompressorDXT1::compressBlock(ColorBlock & rgba, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output) { nvsquish::WeightedClusterFit fit; fit.SetMetric(compressionOptions.colorWeight.x, compressionOptions.colorWeight.y, compressionOptions.colorWeight.z); @@ -165,7 +165,7 @@ void NormalCompressorDXT1::compressBlock(ColorBlock & rgba, nvtt::AlphaMode alph } #endif -void NormalCompressorDXT1a::compressBlock(ColorBlock & rgba, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output) +void CompressorDXT1a::compressBlock(ColorBlock & rgba, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output) { uint alphaMask = 0; for (uint i = 0; i < 16; i++) @@ -185,18 +185,24 @@ void NormalCompressorDXT1a::compressBlock(ColorBlock & rgba, nvtt::AlphaMode alp nvsquish::WeightedClusterFit fit; fit.SetMetric(compressionOptions.colorWeight.x, compressionOptions.colorWeight.y, compressionOptions.colorWeight.z); - int flags = nvsquish::kDxt1; - if (alphaMode == nvtt::AlphaMode_Transparency) flags |= nvsquish::kWeightColourByAlpha; + int flags = nvsquish::kDxt1; + if (alphaMode == nvtt::AlphaMode_Transparency) flags |= nvsquish::kWeightColourByAlpha; - nvsquish::ColourSet colours((uint8 *)rgba.colors(), flags); - fit.SetColourSet(&colours, nvsquish::kDxt1); + nvsquish::ColourSet colours((uint8 *)rgba.colors(), flags); + fit.SetColourSet(&colours, nvsquish::kDxt1); fit.Compress(output); } } +void CompressorDXT1_Luma::compressBlock(ColorBlock & rgba, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output) +{ + BlockDXT1 * block = new(output) BlockDXT1; + OptimalCompress::compressDXT1_Luma(rgba, block); +} + -void NormalCompressorDXT3::compressBlock(ColorBlock & rgba, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output) +void CompressorDXT3::compressBlock(ColorBlock & rgba, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output) { BlockDXT3 * block = new(output) BlockDXT3; @@ -223,7 +229,7 @@ void NormalCompressorDXT3::compressBlock(ColorBlock & rgba, nvtt::AlphaMode alph } -void NormalCompressorDXT5::compressBlock(ColorBlock & rgba, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output) +void CompressorDXT5::compressBlock(ColorBlock & rgba, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output) { BlockDXT5 * block = new(output) BlockDXT5; @@ -247,17 +253,17 @@ void NormalCompressorDXT5::compressBlock(ColorBlock & rgba, nvtt::AlphaMode alph nvsquish::WeightedClusterFit fit; fit.SetMetric(compressionOptions.colorWeight.x, compressionOptions.colorWeight.y, compressionOptions.colorWeight.z); - int flags = 0; - if (alphaMode == nvtt::AlphaMode_Transparency) flags |= nvsquish::kWeightColourByAlpha; + int flags = 0; + if (alphaMode == nvtt::AlphaMode_Transparency) flags |= nvsquish::kWeightColourByAlpha; - nvsquish::ColourSet colours((uint8 *)rgba.colors(), flags); - fit.SetColourSet(&colours, 0); - fit.Compress(&block->color); + nvsquish::ColourSet colours((uint8 *)rgba.colors(), flags); + fit.SetColourSet(&colours, 0); + fit.Compress(&block->color); } } -void NormalCompressorDXT5n::compressBlock(ColorBlock & rgba, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output) +void CompressorDXT5n::compressBlock(ColorBlock & rgba, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output) { BlockDXT5 * block = new(output) BlockDXT5; diff --git a/src/nvtt/CompressorDX9.h b/src/nvtt/CompressorDX9.h index 9f81e14..8e65ba6 100644 --- a/src/nvtt/CompressorDX9.h +++ b/src/nvtt/CompressorDX9.h @@ -64,39 +64,45 @@ namespace nv // Normal CPU compressors. -#if 0 - struct NormalCompressorDXT1 : public ColorSetCompressor +#if 1 + struct CompressorDXT1 : public ColorSetCompressor { virtual void compressBlock(ColorSet & set, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output); virtual uint blockSize() const { return 8; } }; #else - struct NormalCompressorDXT1 : public FixedBlockCompressor + struct CompressorDXT1 : public FixedBlockCompressor { virtual void compressBlock(ColorBlock & rgba, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output); virtual uint blockSize() const { return 8; } }; #endif - struct NormalCompressorDXT1a : public FixedBlockCompressor + struct CompressorDXT1a : public FixedBlockCompressor { virtual void compressBlock(ColorBlock & rgba, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output); virtual uint blockSize() const { return 8; } }; - struct NormalCompressorDXT3 : public FixedBlockCompressor + struct CompressorDXT1_Luma : public FixedBlockCompressor + { + virtual void compressBlock(ColorBlock & rgba, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output); + virtual uint blockSize() const { return 8; } + }; + + struct CompressorDXT3 : public FixedBlockCompressor { virtual void compressBlock(ColorBlock & rgba, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output); virtual uint blockSize() const { return 16; } }; - struct NormalCompressorDXT5 : public FixedBlockCompressor + struct CompressorDXT5 : public FixedBlockCompressor { virtual void compressBlock(ColorBlock & rgba, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output); virtual uint blockSize() const { return 16; } }; - struct NormalCompressorDXT5n : public FixedBlockCompressor + struct CompressorDXT5n : public FixedBlockCompressor { virtual void compressBlock(ColorBlock & rgba, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output); virtual uint blockSize() const { return 16; } diff --git a/src/nvtt/CompressorDXT.cpp b/src/nvtt/CompressorDXT.cpp index ea8c629..7faeb49 100644 --- a/src/nvtt/CompressorDXT.cpp +++ b/src/nvtt/CompressorDXT.cpp @@ -201,7 +201,7 @@ void ColorSetCompressorTask(void * data, int i) //for (uint x = 0; x < d->bw; x++) { ColorSet set; - set.setColors(d->data, d->w, d->h, x, y); + set.setColors(d->data, d->w, d->h, x * 4, y * 4); uint8 * ptr = d->mem + (y * d->bw + x) * d->bs; d->compressor->compressBlock(set, d->alphaMode, *d->compressionOptions, ptr); diff --git a/src/nvtt/Context.cpp b/src/nvtt/Context.cpp index fb5ec9c..a049ddf 100644 --- a/src/nvtt/Context.cpp +++ b/src/nvtt/Context.cpp @@ -690,7 +690,7 @@ CompressorInterface * Compressor::Private::chooseCpuCompressor(const Compression return new FastCompressorDXT1; } - return new NormalCompressorDXT1; + return new CompressorDXT1; } else if (compressionOptions.format == Format_DXT1a) { @@ -699,7 +699,7 @@ CompressorInterface * Compressor::Private::chooseCpuCompressor(const Compression return new FastCompressorDXT1a; } - return new NormalCompressorDXT1a; + return new CompressorDXT1a; } else if (compressionOptions.format == Format_DXT1n) { @@ -712,7 +712,7 @@ CompressorInterface * Compressor::Private::chooseCpuCompressor(const Compression return new FastCompressorDXT3; } - return new NormalCompressorDXT3; + return new CompressorDXT3; } else if (compressionOptions.format == Format_DXT5) { @@ -726,7 +726,7 @@ CompressorInterface * Compressor::Private::chooseCpuCompressor(const Compression return new FastCompressorDXT5; } - return new NormalCompressorDXT5; + return new CompressorDXT5; } else if (compressionOptions.format == Format_DXT5n) { @@ -735,7 +735,7 @@ CompressorInterface * Compressor::Private::chooseCpuCompressor(const Compression return new FastCompressorDXT5n; } - return new NormalCompressorDXT5n; + return new CompressorDXT5n; } else if (compressionOptions.format == Format_BC4) { diff --git a/src/nvtt/CubeSurface.cpp b/src/nvtt/CubeSurface.cpp index 79cdb55..5e61258 100644 --- a/src/nvtt/CubeSurface.cpp +++ b/src/nvtt/CubeSurface.cpp @@ -28,11 +28,9 @@ #include "nvmath/Vector.inl" -#include "nvcore/Array.h" +#include "nvcore/Array.inl" #include "nvcore/StrLib.h" -#include // FLT_MAX - using namespace nv; using namespace nvtt; @@ -304,7 +302,7 @@ const Surface & CubeSurface::face(int f) const bool CubeSurface::load(const char * fileName, int mipmap) { - if (strcmp(Path::extension(fileName), ".dds") == 0) { + if (strEqual(Path::extension(fileName), ".dds")) { nv::DirectDrawSurface dds(fileName); if (!dds.isValid()/* || !dds.isSupported()*/) { @@ -412,7 +410,7 @@ void CubeSurface::range(int channel, float * minimum_ptr, float * maximum_ptr) c const uint edgeLength = m->edgeLength; m->allocateTexelTable(); - float minimum = FLT_MAX; + float minimum = NV_FLOAT_MAX; float maximum = 0.0f; for (int f = 0; f < 6; f++) { diff --git a/src/nvtt/OptimalCompressDXT.cpp b/src/nvtt/OptimalCompressDXT.cpp index ca7640e..b9eb351 100644 --- a/src/nvtt/OptimalCompressDXT.cpp +++ b/src/nvtt/OptimalCompressDXT.cpp @@ -379,6 +379,108 @@ void OptimalCompress::compressDXT1G(const ColorBlock & rgba, BlockDXT1 * block) block->indices = computeGreenIndices(rgba, palette); } + +/*void OptimalCompress::initLumaTables() { + + // For all possible color pairs: + for (int c0 = 0; c0 < 65536; c0++) { + for (int c1 = 0; c1 < 65536; c1++) { + + // Compute + + } + } + + + for (int r = 0; r < 1<<5; r++) { + for (int g = 0; g < 1<<6; g++) { + for (int b = 0; b < 1<<5; b++) { + + + } + } + } +}*/ + + +// Brute force Luma compressor +void OptimalCompress::compressDXT1_Luma(const ColorBlock & rgba, BlockDXT1 * block) +{ + nvDebugCheck(block != NULL); + + // F_YR = 19595/65536.0f, F_YG = 38470/65536.0f, F_YB = 7471/65536.0f; + // 195841 + //if ( + + + /* + uint8 ming = 63; + uint8 maxg = 0; + + bool isSingleColor = true; + uint8 singleColor = rgba.color(0).g; + + // Get min/max green. + for (uint i = 0; i < 16; i++) + { + uint8 green = (rgba.color(i).g + 1) >> 2; + ming = min(ming, green); + maxg = max(maxg, green); + + if (rgba.color(i).g != singleColor) isSingleColor = false; + } + + if (isSingleColor) + { + compressDXT1G(singleColor, block); + return; + } + + block->col0.r = 31; + block->col1.r = 31; + block->col0.g = maxg; + block->col1.g = ming; + block->col0.b = 0; + block->col1.b = 0; + + int bestError = computeGreenError(rgba, block); + int bestg0 = maxg; + int bestg1 = ming; + + // Expand search space a bit. + const int greenExpand = 4; + ming = (ming <= greenExpand) ? 0 : ming - greenExpand; + maxg = (maxg >= 63-greenExpand) ? 63 : maxg + greenExpand; + + for (int g0 = ming+1; g0 <= maxg; g0++) + { + for (int g1 = ming; g1 < g0; g1++) + { + block->col0.g = g0; + block->col1.g = g1; + int error = computeGreenError(rgba, block, bestError); + + if (error < bestError) + { + bestError = error; + bestg0 = g0; + bestg1 = g1; + } + } + } + + block->col0.g = bestg0; + block->col1.g = bestg1; + + nvDebugCheck(bestg0 == bestg1 || block->isFourColorMode()); + */ + + Color32 palette[4]; + block->evaluatePalette(palette, false); // @@ Use target decoder. + block->indices = computeGreenIndices(rgba, palette); +} + + void OptimalCompress::compressDXT3A(const ColorBlock & rgba, AlphaBlockDXT3 * dxtBlock) { dxtBlock->alpha0 = quantize4(rgba.color(0).a); diff --git a/src/nvtt/OptimalCompressDXT.h b/src/nvtt/OptimalCompressDXT.h index 5fcd0e1..87bbe70 100644 --- a/src/nvtt/OptimalCompressDXT.h +++ b/src/nvtt/OptimalCompressDXT.h @@ -47,6 +47,9 @@ namespace nv void compressDXT1G(const ColorBlock & rgba, BlockDXT1 * block); void compressDXT3A(const ColorBlock & rgba, AlphaBlockDXT3 * dxtBlock); void compressDXT5A(const ColorBlock & rgba, AlphaBlockDXT5 * dxtBlock); + + void compressDXT1_Luma(const ColorBlock & rgba, BlockDXT1 * block); + } } // nv namespace diff --git a/src/nvtt/Surface.cpp b/src/nvtt/Surface.cpp index 86e67d4..a46cc3f 100644 --- a/src/nvtt/Surface.cpp +++ b/src/nvtt/Surface.cpp @@ -38,6 +38,7 @@ #include "nvimage/ErrorMetric.h" #include +#include // memset, memcpy using namespace nv; using namespace nvtt; @@ -451,8 +452,8 @@ static int filter(unsigned int code, struct _EXCEPTION_POINTERS *ep) { #define CATCH __except (filter(GetExceptionCode(), GetExceptionInformation())) #else -#define TRY -#define CATCH +#define TRY if (true) +#define CATCH else #endif @@ -2421,6 +2422,37 @@ void Surface::flipZ() m->image->flipZ(); } +Surface Surface::subImage(int x0, int x1, int y0, int y1, int z0, int z1) const +{ + Surface s; + + if (isNull()) return s; + if (x0 < 0 || x1 > width() || x0 > x1) return s; + if (y0 < 0 || y1 > height() || y0 > y1) return s; + if (z0 < 0 || z1 > depth() || z0 > z1) return s; + if (x1 >= width() || y1 >= height() || z1 >= depth()) return s; + + FloatImage * img = s.m->image = new FloatImage; + + int w = x1 - x0 + 1; + int h = y1 - y0 + 1; + int d = z1 - z0 + 1; + + img->allocate(4, w, h, d); + + for (int c = 0; c < 4; c++) { + for (int z = 0; z < d; z++) { + for (int y = 0; y < h; y++) { + for (int x = 0; x < w; x++) { + img->pixel(c, x, y, z) = m->image->pixel(c, x0+x, y0+y, z0+z); + } + } + } + } + + return s; +} + bool Surface::copyChannel(const Surface & srcImage, int srcChannel) { return copyChannel(srcImage, srcChannel, srcChannel); diff --git a/src/nvtt/nvtt.h b/src/nvtt/nvtt.h index b849b77..ce5cb1f 100644 --- a/src/nvtt/nvtt.h +++ b/src/nvtt/nvtt.h @@ -103,6 +103,8 @@ namespace nvtt Format_BC6, // Not supported yet. Format_BC7, // Not supported yet. + + Format_DXT1_Luma, }; // Pixel types. These basically indicate how the output should be interpreted, but do not have any influence over the input. They are only relevant in RGBA mode. @@ -532,6 +534,7 @@ namespace nvtt NVTT_API void flipX(); NVTT_API void flipY(); NVTT_API void flipZ(); + NVTT_API Surface subImage(int x0, int x1, int y0, int y1, int z0, int z1) const; // Copy image data. NVTT_API bool copyChannel(const Surface & srcImage, int srcChannel); diff --git a/src/nvtt/tools/assemble.cpp b/src/nvtt/tools/assemble.cpp index c3086e2..27e56e5 100644 --- a/src/nvtt/tools/assemble.cpp +++ b/src/nvtt/tools/assemble.cpp @@ -21,16 +21,17 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. -#include -#include +#include "cmdline.h" -#include +#include "nvimage/Image.h" +#include "nvimage/ImageIO.h" +#include "nvimage/DirectDrawSurface.h" -#include -#include -#include +#include "nvmath/Color.h" -#include "cmdline.h" +#include "nvcore/Array.inl" +#include "nvcore/StrLib.h" +#include "nvcore/StdStream.h" // @@ Add decent error messages. // @@ Add option to resize images. diff --git a/src/nvtt/tools/imgdiff.cpp b/src/nvtt/tools/imgdiff.cpp index 3f3aeb3..3964fab 100644 --- a/src/nvtt/tools/imgdiff.cpp +++ b/src/nvtt/tools/imgdiff.cpp @@ -92,6 +92,7 @@ struct Error { printf(" Mean absolute error: %f\n", mabse); printf(" Max absolute error: %f\n", maxabse); + printf(" Mean squared error: %f\n", mse); printf(" Root mean squared error: %f\n", rmse); printf(" Peak signal to noise ratio in dB: %f\n", psnr); } @@ -153,6 +154,13 @@ struct NormalError float psnr; }; +static float luma(const nv::Color32 & c) { + return 0.299f * float(c.r) + 0.587f * float(c.g) + 0.114f * float(c.b); + //return 0.25f * float(c.r) + 0.5f * float(c.g) + 0.25f * float(c.b); + //return 0.333f * float(c.r) + 0.334f * float(c.g) + 0.333f * float(c.b); + //return 0.1f * float(c.r) + 0.8f * float(c.g) + 0.1f * float(c.g); +} + int main(int argc, char *argv[]) { @@ -220,6 +228,7 @@ int main(int argc, char *argv[]) Error error_g; Error error_b; Error error_a; + Error error_luma; Error error_total; NormalError error_normal; @@ -234,15 +243,16 @@ int main(int argc, char *argv[]) double g = float(c0.g - c1.g); double b = float(c0.b - c1.b); double a = float(c0.a - c1.a); - + error_r.addSample(r); error_g.addSample(g); error_b.addSample(b); error_a.addSample(a); - - if (compareNormal) { - error_normal.addSample(c0, c1); - } + + double l0 = luma(c0); + double l1 = luma(c1); + + error_luma.addSample(l0 - l1); double d = sqrt(r*r + g*g + b*b); @@ -251,6 +261,10 @@ int main(int argc, char *argv[]) } error_total.addSample(d); + + if (compareNormal) { + error_normal.addSample(c0, c1); + } } } @@ -258,6 +272,7 @@ int main(int argc, char *argv[]) error_g.done(); error_b.done(); error_a.done(); + error_luma.done(); error_total.done(); error_normal.done(); @@ -271,6 +286,9 @@ int main(int argc, char *argv[]) printf("Color:\n"); error_total.print(); + printf("Luma:\n"); + error_luma.print(); + if (compareNormal) { printf("Normal:\n");