Work in progress.
Merging squish into nvtt. Using squish only to find endpoints, do discrete refinement afterwards.
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@ -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);
|
||||
}
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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)
|
||||
|
Reference in New Issue
Block a user