Work in progress.

Merging squish into nvtt. 
Using squish only to find endpoints, do discrete refinement afterwards.
This commit is contained in:
castano
2010-11-09 03:38:03 +00:00
parent c532ffb34e
commit 49482d1441
25 changed files with 1726 additions and 1008 deletions

File diff suppressed because it is too large Load Diff

View File

@ -217,6 +217,33 @@ inline static uint computeIndices3(const ColorBlock & rgba, Vector3::Arg maxColo
return indices;
}
inline static uint computeIndices3(const Vector3 block[16], Vector3::Arg maxColor, Vector3::Arg minColor)
{
Vector3 palette[4];
palette[0] = minColor;
palette[1] = maxColor;
palette[2] = (palette[0] + palette[1]) * 0.5f;
uint indices = 0;
for(int i = 0; i < 16; i++)
{
float d0 = colorDistance(palette[0], block[i]);
float d1 = colorDistance(palette[1], block[i]);
float d2 = colorDistance(palette[2], block[i]);
uint index;
if (d0 < d1 && d0 < d2) index = 0;
else if (d1 < d2) index = 1;
else index = 2;
indices |= index << (2 * i);
}
return indices;
}
static void optimizeEndPoints4(Vector3 block[16], BlockDXT1 * dxtBlock)
{
@ -266,7 +293,7 @@ static void optimizeEndPoints4(Vector3 block[16], BlockDXT1 * dxtBlock)
dxtBlock->indices = computeIndices4(block, a, b);
}
/*static void optimizeEndPoints3(Vector3 block[16], BlockDXT1 * dxtBlock)
static void optimizeEndPoints3(Vector3 block[16], BlockDXT1 * dxtBlock)
{
float alpha2_sum = 0.0f;
float beta2_sum = 0.0f;
@ -278,7 +305,7 @@ static void optimizeEndPoints4(Vector3 block[16], BlockDXT1 * dxtBlock)
{
const uint bits = dxtBlock->indices >> (2 * i);
float beta = (bits & 1);
float beta = float(bits & 1);
if (bits & 2) beta = 0.5f;
float alpha = 1.0f - beta;
@ -312,7 +339,7 @@ static void optimizeEndPoints4(Vector3 block[16], BlockDXT1 * dxtBlock)
dxtBlock->col0 = Color16(color1);
dxtBlock->col1 = Color16(color0);
dxtBlock->indices = computeIndices3(block, a, b);
}*/
}
namespace
{
@ -571,7 +598,7 @@ void QuickCompress::compressDXT1a(const ColorBlock & rgba, BlockDXT1 * dxtBlock)
dxtBlock->col0 = Color16(color1);
dxtBlock->col1 = Color16(color0);
dxtBlock->indices = computeIndices3(rgba, maxColor, minColor);
dxtBlock->indices = computeIndices3(block, maxColor, minColor);
// optimizeEndPoints(block, dxtBlock);
}
@ -634,3 +661,51 @@ void QuickCompress::compressDXT5(const ColorBlock & rgba, BlockDXT5 * dxtBlock,
compressDXT1(rgba, &dxtBlock->color);
compressDXT5A(rgba, &dxtBlock->alpha, iterationCount);
}
void QuickCompress::outputBlock4(const ColorBlock & rgba, const Vector3 & start, const Vector3 & end, BlockDXT1 * dxtBlock)
{
Vector3 block[16];
extractColorBlockRGB(rgba, block);
Vector3 maxColor = start * 255;
Vector3 minColor = end * 255;
uint16 color0 = roundAndExpand(&maxColor);
uint16 color1 = roundAndExpand(&minColor);
if (color0 < color1)
{
swap(maxColor, minColor);
swap(color0, color1);
}
dxtBlock->col0 = Color16(color0);
dxtBlock->col1 = Color16(color1);
dxtBlock->indices = computeIndices4(block, maxColor, minColor);
optimizeEndPoints4(block, dxtBlock);
}
void QuickCompress::outputBlock3(const ColorBlock & rgba, const Vector3 & start, const Vector3 & end, BlockDXT1 * dxtBlock)
{
Vector3 block[16];
extractColorBlockRGB(rgba, block);
Vector3 maxColor = start * 255;
Vector3 minColor = end * 255;
uint16 color0 = roundAndExpand(&maxColor);
uint16 color1 = roundAndExpand(&minColor);
if (color0 > color1)
{
swap(maxColor, minColor);
swap(color0, color1);
}
dxtBlock->col0 = Color16(color0);
dxtBlock->col1 = Color16(color1);
dxtBlock->indices = computeIndices3(block, maxColor, minColor);
optimizeEndPoints3(block, dxtBlock);
}

View File

@ -35,6 +35,7 @@ namespace nv
struct BlockDXT5;
struct AlphaBlockDXT3;
struct AlphaBlockDXT5;
class Vector3;
namespace QuickCompress
{
@ -45,6 +46,9 @@ namespace nv
void compressDXT5A(const ColorBlock & rgba, AlphaBlockDXT5 * dxtBlock, int iterationCount=8);
void compressDXT5(const ColorBlock & rgba, BlockDXT5 * dxtBlock, int iterationCount=8);
void outputBlock4(const ColorBlock & rgba, const Vector3 & start, const Vector3 & end, BlockDXT1 * block);
void outputBlock3(const ColorBlock & rgba, const Vector3 & start, const Vector3 & end, BlockDXT1 * block);
}
} // nv namespace

View File

@ -299,6 +299,46 @@ const float * TexImage::data() const
return m->image->channel(0);
}
void TexImage::histogram(int channel, float rangeMin, float rangeMax, int binCount, int * binPtr) const
{
// We assume it's clear in case we want to accumulate multiple histograms.
//memset(bins, 0, sizeof(int)*count);
if (m->image == NULL) return;
const float * c = m->image->channel(channel);
float scale = float(binCount) / rangeMax;
float bias = - scale * rangeMin;
const uint count = m->image->width() * m->image->height();
for (uint i = 0; i < count; i++) {
float f = c[i] * scale + bias;
int idx = ifloor(f);
if (idx < 0) idx = 0;
if (idx > binCount-1) idx = binCount-1;
binPtr[idx]++;
}
}
void TexImage::range(int channel, float * rangeMin, float * rangeMax)
{
Vector2 range(FLT_MAX, -FLT_MAX);
FloatImage * img = m->image;
float * c = img->channel(channel);
const uint count = img->width() * img->height();
for (uint p = 0; p < count; p++) {
float f = c[p];
if (f < range.x) range.x = f;
if (f > range.y) range.y = f;
}
*rangeMin = range.x;
*rangeMax = range.y;
}
bool TexImage::load(const char * fileName)
{
@ -320,8 +360,6 @@ bool TexImage::load(const char * fileName)
bool TexImage::save(const char * fileName) const
{
#pragma NV_MESSAGE("TODO: Add support for DDS textures in TexImage::save")
if (m->image != NULL)
{
return ImageIO::saveFloat(fileName, m->image, 0, 4);
@ -989,33 +1027,19 @@ void TexImage::scaleAlphaToCoverage(float coverage, float alphaRef/*= 0.5f*/)
m->image->scaleAlphaToCoverage(coverage, alphaRef, 3);
}
bool TexImage::normalizeRange(float * rangeMin, float * rangeMax)
/*bool TexImage::normalizeRange(float * rangeMin, float * rangeMax)
{
if (m->image == NULL) return false;
Vector2 range(FLT_MAX, -FLT_MAX);
range(0, rangeMin, rangeMax);
// Compute range.
FloatImage * img = m->image;
const uint count = img->count();
for (uint p = 0; p < count; p++) {
float c = img->pixel(p);
if (c < range.x) range.x = c;
if (c > range.y) range.y = c;
}
if (range.x == range.y) {
if (*rangeMin == *rangeMax) {
// Single color image.
return false;
}
*rangeMin = range.x;
*rangeMax = range.y;
const float scale = 1.0f / (range.y - range.x);
const float bias = range.x * scale;
const float scale = 1.0f / (*rangeMax - *rangeMin);
const float bias = *rangeMin * scale;
if (range.x == 0.0f && range.y == 1.0f) {
// Already normalized.
@ -1029,7 +1053,7 @@ bool TexImage::normalizeRange(float * rangeMin, float * rangeMax)
//img->clamp(0, 4, 0.0f, 1.0f);
return true;
}
}*/
// Ideally you should compress/quantize the RGB and M portions independently.
// Once you have M quantized, you would compute the corresponding RGB and quantize that.
@ -1054,7 +1078,6 @@ void TexImage::toRGBM(float range/*= 1*/, float threshold/*= 0.25*/)
float B = nv::clamp(b[i] * irange, 0.0f, 1.0f);
float M = max(max(R, G), max(B, 1e-6f)); // Avoid division by zero.
//m = quantizeCeil(m, 8);
r[i] = R / M;
g[i] = G / M;
@ -1233,20 +1256,19 @@ void TexImage::toLUVW(float range/*= 1.0f*/)
float G = nv::clamp(g[i] * irange, 0.0f, 1.0f);
float B = nv::clamp(b[i] * irange, 0.0f, 1.0f);
float L = max(sqrtf(R*R + G*G + B*B), 1e-6f)); // Avoid division by zero.
//m = quantizeCeil(m, 8);
float L = max(sqrtf(R*R + G*G + B*B), 1e-6f); // Avoid division by zero.
r[i] = R / L;
g[i] = G / L;
b[i] = B / L;
a[i] = L;
a[i] = L / sqrtf(3);
}
}
void TexImage::fromLUVW(float range/*= 1.0f*/)
{
// Decompression is the same as in RGBM.
fromRGBM(range);
fromRGBM(range * sqrtf(3));
}
@ -1435,10 +1457,52 @@ float nvtt::rmsAlphaError(const TexImage & reference, const TexImage & image)
return float(sqrt(mse / count));
}
TexImage nvtt::diff(const TexImage & reference, const TexImage & image)
TexImage nvtt::diff(const TexImage & reference, const TexImage & image, float scale)
{
// @@ TODO.
return TexImage();
const FloatImage * ref = reference.m->image;
const FloatImage * img = image.m->image;
if (img == NULL || ref == NULL || img->width() != ref->width() || img->height() != ref->height()) {
return TexImage();
}
nvDebugCheck(img->componentNum() == 4);
nvDebugCheck(ref->componentNum() == 4);
nvtt::TexImage diffImage;
FloatImage * diff = diffImage.m->image = new FloatImage;
diff->allocate(4, img->width(), img->height());
const uint count = img->width() * img->height();
for (uint i = 0; i < count; i++)
{
float r0 = img->pixel(i, 0);
float g0 = img->pixel(i, 1);
float b0 = img->pixel(i, 2);
//float a0 = img->pixel(i, 3);
float r1 = ref->pixel(i, 0);
float g1 = ref->pixel(i, 1);
float b1 = ref->pixel(i, 2);
float a1 = ref->pixel(i, 3);
float dr = r0 - r1;
float dg = g0 - g1;
float db = b0 - b1;
//float da = a0 - a1;
if (reference.alphaMode() == nvtt::AlphaMode_Transparency)
{
dr *= a1;
dg *= a1;
db *= a1;
}
diff->pixel(i, 0) = dr * scale;
diff->pixel(i, 1) = dg * scale;
diff->pixel(i, 2) = db * scale;
diff->pixel(i, 3) = a1;
}
return diffImage;
}

View File

@ -395,6 +395,8 @@ namespace nvtt
NVTT_API float alphaTestCoverage(float alphaRef = 0.5) const;
NVTT_API float average(int channel) const;
NVTT_API const float * data() const;
NVTT_API void histogram(int channel, float rangeMin, float rangeMax, int binCount, int * binPtr) const;
NVTT_API void range(int channel, float * rangeMin, float * rangeMax);
// Texture data.
NVTT_API bool load(const char * fileName);
@ -426,7 +428,7 @@ namespace nvtt
NVTT_API void setBorder(float r, float g, float b, float a);
NVTT_API void fill(float r, float g, float b, float a);
NVTT_API void scaleAlphaToCoverage(float coverage, float alphaRef = 0.5f);
NVTT_API bool normalizeRange(float * rangeMin, float * rangeMax);
//NVTT_API bool normalizeRange(float * rangeMin, float * rangeMax);
NVTT_API void toRGBM(float range = 1.0f, float threshold = 0.0f);
NVTT_API void fromRGBM(float range = 1.0f);
NVTT_API void toYCoCg();
@ -451,9 +453,9 @@ namespace nvtt
NVTT_API bool copyChannel(const TexImage & srcImage, int srcChannel, int dstChannel);
// Error compare.
friend float rmsError(const TexImage & reference, const TexImage & img);
friend float rmsAlphaError(const TexImage & reference, const TexImage & img);
friend TexImage diff(const TexImage & reference, const TexImage & img);
NVTT_API friend float rmsError(const TexImage & reference, const TexImage & img);
NVTT_API friend float rmsAlphaError(const TexImage & reference, const TexImage & img);
NVTT_API friend TexImage diff(const TexImage & reference, const TexImage & img, float scale);
private:
void detach();
@ -471,7 +473,7 @@ namespace nvtt
NVTT_API float rmsError(const TexImage & reference, const TexImage & img);
NVTT_API float rmsAlphaError(const TexImage & reference, const TexImage & img);
NVTT_API TexImage diff(const TexImage & reference, const TexImage & img);
NVTT_API TexImage diff(const TexImage & reference, const TexImage & img, float scale);
} // nvtt namespace

View File

@ -38,21 +38,21 @@ void ColourFit::SetColourSet( ColourSet const* colours, int flags )
m_flags = flags;
}
void ColourFit::Compress( void* block )
void ColourFit::Compress( Vec3 * start, Vec3 * end )
{
bool isDxt1 = ( ( m_flags & kDxt1 ) != 0 );
if( isDxt1 )
{
Compress3( block );
Compress3( start, end );
if( !m_colours->IsTransparent() )
{
Compress4( block );
Compress4( start, end );
}
}
else
{
Compress4( block );
Compress4( start, end );
}
}

View File

@ -40,11 +40,11 @@ public:
void SetColourSet( ColourSet const* colours, int flags );
void Compress( void* block );
void Compress( Vec3 * start, Vec3 * end );
protected:
virtual void Compress3( void* block ) = 0;
virtual void Compress4( void* block ) = 0;
virtual bool Compress3( Vec3 * start, Vec3 * end ) = 0;
virtual bool Compress4( Vec3 * start, Vec3 * end ) = 0;
ColourSet const* m_colours;
int m_flags;

View File

@ -129,7 +129,7 @@ float WeightedClusterFit::GetBestError() const
#if SQUISH_USE_SIMD
void WeightedClusterFit::Compress3( void* block )
bool WeightedClusterFit::Compress3( Vec3 * start, Vec3 * end )
{
int const count = m_colours->GetCount();
Vec4 const one = VEC4_CONST(1.0f);
@ -212,7 +212,7 @@ void WeightedClusterFit::Compress3( void* block )
if( CompareAnyLessThan( besterror, m_besterror ) )
{
// compute indices from cluster sizes.
u8 bestindices[16];
/*u8 bestindices[16];
{
int i = 0;
for(; i < b0; i++) {
@ -233,16 +233,22 @@ void WeightedClusterFit::Compress3( void* block )
m_colours->RemapIndices( ordered, bestindices );
// save the block
WriteColourBlock3( beststart.GetVec3(), bestend.GetVec3(), bestindices, block );
WriteColourBlock3( beststart.GetVec3(), bestend.GetVec3(), bestindices, block );*/
*start = beststart.GetVec3();
*end = bestend.GetVec3();
// save the error
m_besterror = besterror;
return true;
}
return false;
}
void WeightedClusterFit::Compress4( void* block )
bool WeightedClusterFit::Compress4( Vec3 * start, Vec3 * end )
{
int const count = m_colours->GetCount();
Vec4 const one = VEC4_CONST(1.0f);
@ -334,7 +340,7 @@ void WeightedClusterFit::Compress4( void* block )
// save the block if necessary
if( CompareAnyLessThan( besterror, m_besterror ) )
{
// compute indices from cluster sizes.
/*// compute indices from cluster sizes.
u8 bestindices[16];
{
int i = 0;
@ -360,11 +366,18 @@ void WeightedClusterFit::Compress4( void* block )
m_colours->RemapIndices( ordered, bestindices );
// save the block
WriteColourBlock4( beststart.GetVec3(), bestend.GetVec3(), bestindices, block );
WriteColourBlock4( beststart.GetVec3(), bestend.GetVec3(), bestindices, block );*/
*start = beststart.GetVec3();
*end = bestend.GetVec3();
// save the error
m_besterror = besterror;
return true;
}
return false;
}
#else

View File

@ -45,8 +45,8 @@ public:
float GetBestError() const;
// Make them public
virtual void Compress3( void* block );
virtual void Compress4( void* block );
bool Compress3( Vec3 * start, Vec3 * end );
bool Compress4( Vec3 * start, Vec3 * end );
private:

View File

@ -145,6 +145,11 @@ static const char * s_witnessImageSet[] = {
"specRuin-puzzle.tga"
};
static const char * s_witnessLmapImageSet[] = {
"specruin.dds",
};
enum Mode {
Mode_BC1,
Mode_BC1_Alpha,
@ -152,9 +157,12 @@ enum Mode {
Mode_BC3_Alpha,
Mode_BC3_YCoCg,
Mode_BC3_RGBM,
Mode_BC3_LUVW,
Mode_BC1_Normal,
Mode_BC3_Normal,
Mode_BC5_Normal,
Mode_BC3_Lightmap_1,
Mode_BC3_Lightmap_2,
};
static const char * s_modeNames[] = {
"BC1",
@ -167,6 +175,8 @@ static const char * s_modeNames[] = {
"BC1-Normal",
"BC3-Normal",
"BC5-Normal",
"BC3-RGBM",
"BC3-LUVW",
};
struct Test {
@ -175,26 +185,29 @@ struct Test {
Mode modes[4];
};
static Test s_imageTests[] = {
{"DXT Color", 3, {Mode_BC1, Mode_BC3_YCoCg, Mode_BC3_RGBM}},
{"DXT Color", 1, {Mode_BC1, Mode_BC3_YCoCg, Mode_BC3_RGBM, Mode_BC3_LUVW}},
{"DXT Alpha", 3, {Mode_BC1_Alpha, Mode_BC2_Alpha, Mode_BC3_Alpha}},
{"DXT Normal", 3, {Mode_BC1_Normal, Mode_BC3_Normal, Mode_BC5_Normal}},
{"DXT Lightmap", 2, {Mode_BC3_Lightmap_1, Mode_BC3_Lightmap_2}},
};
const int s_testCount = ARRAY_SIZE(s_imageTests);
const int s_imageTestCount = ARRAY_SIZE(s_imageTests);
struct ImageSet
{
const char * name;
const char * basePath;
const char ** fileNames;
int fileCount;
};
static ImageSet s_imageSets[] = {
{"Kodak", s_kodakImageSet, ARRAY_SIZE(s_kodakImageSet)}, // 0
{"Waterloo", s_waterlooImageSet, ARRAY_SIZE(s_waterlooImageSet)}, // 1
{"Epic", s_epicImageSet, ARRAY_SIZE(s_epicImageSet)}, // 2
{"Farbraush", s_farbrauschImageSet, ARRAY_SIZE(s_farbrauschImageSet)}, // 3
{"Lugaru", s_lugaruImageSet, ARRAY_SIZE(s_lugaruImageSet)}, // 4
{"Quake3", s_quake3ImageSet, ARRAY_SIZE(s_quake3ImageSet)}, // 5
{"Witness", s_witnessImageSet, ARRAY_SIZE(s_witnessImageSet)} // 6
{"Kodak", "kodak", s_kodakImageSet, ARRAY_SIZE(s_kodakImageSet)}, // 0
{"Waterloo", "waterloo", s_waterlooImageSet, ARRAY_SIZE(s_waterlooImageSet)}, // 1
{"Epic", "epic", s_epicImageSet, ARRAY_SIZE(s_epicImageSet)}, // 2
{"Farbraush", "farbrausch", s_farbrauschImageSet, ARRAY_SIZE(s_farbrauschImageSet)}, // 3
{"Lugaru", "lugaru", s_lugaruImageSet, ARRAY_SIZE(s_lugaruImageSet)}, // 4
{"Quake3", "quake3", s_quake3ImageSet, ARRAY_SIZE(s_quake3ImageSet)}, // 5
{"Witness", "witness", s_witnessImageSet, ARRAY_SIZE(s_witnessImageSet)}, // 6
{"Lightmap", "lightmap", s_witnessLmapImageSet, ARRAY_SIZE(s_witnessLmapImageSet)}, // 7
};
const int s_imageSetCount = sizeof(s_imageSets)/sizeof(s_imageSets[0]);
@ -227,9 +240,10 @@ struct MyOutputHandler : public nvtt::OutputHandler
nvtt::TexImage decompress(Mode mode, nvtt::Decoder decoder)
{
nvtt::Format format;
if (mode == Mode_BC1) format = nvtt::Format_BC1;
if (mode == Mode_BC1 || mode == Mode_BC1_Alpha || mode == Mode_BC1_Normal) format = nvtt::Format_BC1;
else if (mode == Mode_BC2_Alpha) format = nvtt::Format_BC2;
else if (mode == Mode_BC5_Normal) format = nvtt::Format_BC5;
else format = nvtt::Format_BC3;
else format = nvtt::Format_BC3;
nvtt::TexImage img;
img.setImage2D(format, decoder, m_width, m_height, m_data);
@ -263,7 +277,7 @@ int main(int argc, char *argv[])
bool nocuda = false;
bool showHelp = false;
nvtt::Decoder decoder = nvtt::Decoder_Reference;
const char * basePath = "";
Path basePath = "";
const char * outPath = "output";
const char * regressPath = NULL;
@ -274,6 +288,14 @@ int main(int argc, char *argv[])
{
if (i+1 < argc && argv[i+1][0] != '-') {
setIndex = atoi(argv[i+1]);
for (int j = 0; j < s_imageSetCount; j++) {
if (strCaseCmp(s_imageSets[j].name, argv[i+1]) == 0) {
setIndex = j;
break;
}
}
i++;
}
}
@ -327,7 +349,7 @@ int main(int argc, char *argv[])
}
// Validate inputs.
if (testIndex >= s_testCount) {
if (testIndex >= s_imageTestCount) {
printf("Invalid test %d\n", testIndex);
return 0;
}
@ -343,17 +365,14 @@ int main(int argc, char *argv[])
printf("Input options:\n");
printf(" -path <path> \tInput image path.\n");
printf(" -regress <path>\tRegression directory.\n");
printf(" -set [0:5] \tImage set.\n");
printf(" 0: \tKodak.\n");
printf(" 1: \tWaterloo.\n");
printf(" 2: \tEpic.\n");
printf(" 3: \tFarbrausch.\n");
printf(" 4: \tLugaru.\n");
printf(" 5: \tQuake 3.\n");
printf(" -test [0:2] \tCompression tests to run.");
printf(" 0: \tDXT Color.\n");
printf(" 1: \tDXT Alpha.\n");
printf(" 2: \tDXT Normal.\n");
printf(" -set [0:%d] \tImage set.\n", s_imageSetCount-1);
for (int i = 0; i < s_imageSetCount; i++) {
printf(" %i: \t%s.\n", i, s_imageSets[i].name);
}
printf(" -test [0:%d] \tCompression tests to run.", s_imageTestCount);
for (int i = 0; i < s_imageTestCount; i++) {
printf(" %i: \t%s.\n", i, s_imageTests[i].name);
}
printf(" -dec x \tDecompressor.\n");
printf(" 0: \tReference.\n");
printf(" 1: \tNVIDIA.\n");
@ -397,7 +416,9 @@ int main(int argc, char *argv[])
nvtt::Context context;
context.enableCudaAcceleration(!nocuda);
FileSystem::changeDirectory(basePath);
basePath.append(set.basePath);
FileSystem::changeDirectory(basePath.str());
FileSystem::createDirectory(outPath);
//Path csvFileName;
@ -406,7 +427,7 @@ int main(int argc, char *argv[])
//TextWriter csvWriter(&csvStream);
Path graphFileName;
graphFileName.format("%s/result-%d.txt", outPath, setIndex);
graphFileName.format("%s/chart.txt", outPath/*, test.name*/);
StdOutputStream graphStream(graphFileName.str());
TextWriter graphWriter(&graphStream);
@ -434,7 +455,7 @@ int main(int argc, char *argv[])
{
const char * colors[] = {
"3D7930", "952826", "3D1FC1",
"3D7930", "952826", "3D1FC1", // pick other colors...
"FF9900", "999999", "999999", // pick other colors...
};
graphWriter << colors[t];
if (t != test.count-1) graphWriter << ",";
@ -484,10 +505,10 @@ int main(int argc, char *argv[])
for (int t = 0; t < test.count; t++)
{
Mode mode = test.modes[t];
if (mode == Mode_BC1) {
if (mode == Mode_BC1 || mode == Mode_BC1_Alpha || mode == Mode_BC1_Normal) {
compressionOptions.setFormat(nvtt::Format_BC1);
}
else if (mode == Mode_BC3_Alpha || mode == Mode_BC3_YCoCg || mode == Mode_BC3_RGBM) {
else if (mode == Mode_BC3_Alpha || mode == Mode_BC3_YCoCg || mode == Mode_BC3_RGBM || mode == Mode_BC3_LUVW || mode == Mode_BC3_Lightmap_1 || mode == Mode_BC3_Lightmap_2) {
compressionOptions.setFormat(nvtt::Format_BC3);
}
else if (mode == Mode_BC3_Normal) {
@ -497,10 +518,10 @@ int main(int argc, char *argv[])
compressionOptions.setFormat(nvtt::Format_BC5);
}
if (mode == Mode_BC3_Alpha) {
if (mode == Mode_BC3_Alpha || mode == Mode_BC3_Lightmap_1 || mode == Mode_BC3_Lightmap_2) { // Lightmap's alpha channel is coverage.
img.setAlphaMode(nvtt::AlphaMode_Transparency);
}
if (mode == Mode_BC3_Normal || mode == Mode_BC5_Normal) {
if (mode == Mode_BC1_Normal || mode == Mode_BC3_Normal || mode == Mode_BC5_Normal) {
img.setNormalMap(true);
}
@ -528,6 +549,56 @@ int main(int argc, char *argv[])
else if (mode == Mode_BC3_RGBM) {
tmp.toRGBM();
}
else if (mode == Mode_BC3_LUVW) {
tmp.toLUVW();
}
else if (mode == Mode_BC3_Lightmap_1) {
tmp.toRGBM(4);
/*float rmin, rmax;
tmp.range(0, &rmin, &rmax);
float gmin, gmax;
tmp.range(1, &gmin, &gmax);
float bmin, bmax;
tmp.range(2, &bmin, &bmax);
float lmin, lmax;
tmp.range(3, &lmin, &lmax);
printf("rmin: %.3f rmax: %.3f\n", rmin, rmax);
printf("gmin: %.3f gmax: %.3f\n", gmin, gmax);
printf("bmin: %.3f bmax: %.3f\n", bmin, bmax);
printf("lmin: %.3f lmax: %.3f\n", lmin, lmax);
const int N = 32;
int chistogram[N];
int lhistogram[N];
memset(chistogram, 0, sizeof(chistogram));
memset(lhistogram, 0, sizeof(lhistogram));
tmp.histogram(0, 0, 1, N, chistogram);
tmp.histogram(1, 0, 1, N, chistogram);
tmp.histogram(2, 0, 1, N, chistogram);
tmp.histogram(3, 0, 1, N, lhistogram);
printf("Color histogram:\n");
for (int i = 0; i < N; i++) {
printf("%d, ", chistogram[i]);
}
printf("\n");
printf("Luminance histogram:\n");
for (int i = 0; i < N; i++) {
printf("%d, ", lhistogram[i]);
}
printf("\n");*/
}
else if (mode == Mode_BC3_Lightmap_2) {
tmp.toLUVW(4);
}
printf("Compressing: \t'%s'\n", set.fileNames[i]);
@ -540,12 +611,8 @@ int main(int argc, char *argv[])
totalTime += timer.elapsed();
nvtt::TexImage img_out = outputHandler.decompress(mode, decoder);
if (mode == Mode_BC3_Alpha) {
img_out.setAlphaMode(nvtt::AlphaMode_Transparency);
}
if (mode == Mode_BC3_Normal || mode == Mode_BC5_Normal) {
img_out.setNormalMap(true);
}
img_out.setAlphaMode(img.alphaMode());
img_out.setNormalMap(img.isNormalMap());
if (mode == Mode_BC3_YCoCg) {
img_out.scaleBias(0, 1.0, -0.5);
@ -555,11 +622,30 @@ int main(int argc, char *argv[])
else if (mode == Mode_BC3_RGBM) {
img_out.fromRGBM();
}
else if (mode == Mode_BC3_LUVW) {
img_out.fromLUVW();
}
else if (mode == Mode_BC3_Lightmap_1) {
img_out.fromRGBM(4);
}
else if (mode == Mode_BC3_Lightmap_2) {
img_out.fromLUVW(4);
}
Path outputFilePath;
outputFilePath.format("%s/%s", outPath, s_modeNames[test.modes[t]]);
FileSystem::createDirectory(outputFilePath.str());
Path outputFileName;
outputFileName.format("%s/%s", outPath, set.fileNames[i]);
outputFileName.format("%s/%s", outputFilePath.str(), set.fileNames[i]);
outputFileName.stripExtension();
outputFileName.append(".png");
if (mode == Mode_BC3_Lightmap_1 || mode == Mode_BC3_Lightmap_2) {
outputFileName.append(".dds");
}
else {
outputFileName.append(".png");
}
if (!img_out.save(outputFileName.str()))
{
printf("Error saving file '%s'.\n", outputFileName.str());
@ -573,6 +659,12 @@ int main(int argc, char *argv[])
graphWriter << rmse;
if (i != set.fileCount-1) graphWriter << ",";
outputFileName.stripExtension();
outputFileName.append("_diff.png");
nvtt::diff(img, img_out, 4.0f).save(outputFileName.str());
// Output csv file
//csvWriter << "\"" << fileNames[i] << "\"," << rmse << "\n";
@ -615,7 +707,7 @@ int main(int argc, char *argv[])
printf(" Total Time: \t%.3f sec\n", totalTime);
printf(" Average RMSE:\t%.4f\n", totalRMSE);
if (t != s_testCount-1) graphWriter << "|";
if (t != test.count-1) graphWriter << "|";
}
/*if (regressPath != NULL)