|
|
|
@ -430,6 +430,124 @@ void QuickCompress::compressDXT1a(const ColorBlock & rgba, BlockDXT1 * dxtBlock)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int computeGreenError(const ColorBlock & rgba, const BlockDXT1 * block)
|
|
|
|
|
{
|
|
|
|
|
nvDebugCheck(block != NULL);
|
|
|
|
|
|
|
|
|
|
int palette[4];
|
|
|
|
|
palette[0] = (block->col0.g << 2) | (block->col0.g >> 4);
|
|
|
|
|
palette[1] = (block->col1.g << 2) | (block->col1.g >> 4);
|
|
|
|
|
palette[2] = (2 * palette[0] + palette[1]) / 3;
|
|
|
|
|
palette[3] = (2 * palette[1] + palette[0]) / 3;
|
|
|
|
|
|
|
|
|
|
int totalError = 0;
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 16; i++)
|
|
|
|
|
{
|
|
|
|
|
const int green = rgba.color(i).g;
|
|
|
|
|
|
|
|
|
|
int error = abs(green - palette[0]);
|
|
|
|
|
error = min(error, abs(green - palette[1]));
|
|
|
|
|
error = min(error, abs(green - palette[2]));
|
|
|
|
|
error = min(error, abs(green - palette[3]));
|
|
|
|
|
|
|
|
|
|
totalError += error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return totalError;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static uint computeGreenIndices(const ColorBlock & rgba, const Color32 palette[4])
|
|
|
|
|
{
|
|
|
|
|
const int color0 = palette[0].g;
|
|
|
|
|
const int color1 = palette[1].g;
|
|
|
|
|
const int color2 = palette[2].g;
|
|
|
|
|
const int color3 = palette[3].g;
|
|
|
|
|
|
|
|
|
|
uint indices = 0;
|
|
|
|
|
for (int i = 0; i < 16; i++)
|
|
|
|
|
{
|
|
|
|
|
const int color = rgba.color(i).g;
|
|
|
|
|
|
|
|
|
|
uint d0 = abs(color0 - color);
|
|
|
|
|
uint d1 = abs(color1 - color);
|
|
|
|
|
uint d2 = abs(color2 - color);
|
|
|
|
|
uint d3 = abs(color3 - color);
|
|
|
|
|
|
|
|
|
|
uint b0 = d0 > d3;
|
|
|
|
|
uint b1 = d1 > d2;
|
|
|
|
|
uint b2 = d0 > d2;
|
|
|
|
|
uint b3 = d1 > d3;
|
|
|
|
|
uint b4 = d2 > d3;
|
|
|
|
|
|
|
|
|
|
uint x0 = b1 & b2;
|
|
|
|
|
uint x1 = b0 & b3;
|
|
|
|
|
uint x2 = b0 & b4;
|
|
|
|
|
|
|
|
|
|
indices |= (x2 | ((x0 | x1) << 1)) << (2 * i);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return indices;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Brute force green channel compressor
|
|
|
|
|
void QuickCompress::compressDXT1G(const ColorBlock & rgba, BlockDXT1 * block)
|
|
|
|
|
{
|
|
|
|
|
nvDebugCheck(block != NULL);
|
|
|
|
|
|
|
|
|
|
uint8 ming = 63;
|
|
|
|
|
uint8 maxg = 0;
|
|
|
|
|
|
|
|
|
|
// Get min/max green.
|
|
|
|
|
for (uint i = 0; i < 16; i++)
|
|
|
|
|
{
|
|
|
|
|
uint8 green = rgba.color(i).g >> 2;
|
|
|
|
|
ming = min(ming, green);
|
|
|
|
|
maxg = max(maxg, green);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
block->col0.u = 0;
|
|
|
|
|
block->col1.u = 0;
|
|
|
|
|
block->col0.g = maxg;
|
|
|
|
|
block->col1.g = ming;
|
|
|
|
|
|
|
|
|
|
if (maxg - ming > 4)
|
|
|
|
|
{
|
|
|
|
|
int besterror = computeGreenError(rgba, block);
|
|
|
|
|
int bestg0 = maxg;
|
|
|
|
|
int bestg1 = ming;
|
|
|
|
|
|
|
|
|
|
for (int g0 = ming+5; g0 < maxg; g0++)
|
|
|
|
|
{
|
|
|
|
|
for (int g1 = ming; g1 < g0-4; g1++)
|
|
|
|
|
{
|
|
|
|
|
if ((maxg-g0) + (g1-ming) > besterror)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
block->col0.g = g0;
|
|
|
|
|
block->col1.g = g1;
|
|
|
|
|
int error = computeGreenError(rgba, block);
|
|
|
|
|
|
|
|
|
|
if (error < besterror)
|
|
|
|
|
{
|
|
|
|
|
besterror = error;
|
|
|
|
|
bestg0 = g0;
|
|
|
|
|
bestg1 = g1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
block->col0.g = bestg0;
|
|
|
|
|
block->col1.g = bestg1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Color32 palette[4];
|
|
|
|
|
block->evaluatePalette(palette);
|
|
|
|
|
block->indices = computeGreenIndices(rgba, palette);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void QuickCompress::compressDXT3A(const ColorBlock & rgba, AlphaBlockDXT3 * dxtBlock)
|
|
|
|
|
{
|
|
|
|
|
dxtBlock->alpha0 = rgba.color(0).a >> 4;
|
|
|
|
|