Move fast DXT1a compressor to QuickCompress.
This commit is contained in:
parent
793611fe7f
commit
13335f3d97
@ -89,10 +89,7 @@ void nv::fastCompressDXT1a(const Image * image, const OutputOptions & outputOpti
|
|||||||
for (uint x = 0; x < w; x += 4) {
|
for (uint x = 0; x < w; x += 4) {
|
||||||
rgba.init(image, x, y);
|
rgba.init(image, x, y);
|
||||||
|
|
||||||
compressBlock_BoundsRangeAlpha(rgba, &block);
|
QuickCompress::compressDXT1a(rgba, &block);
|
||||||
|
|
||||||
// @@ Use iterative optimization.
|
|
||||||
//optimizeEndPoints(rgba, &block);
|
|
||||||
|
|
||||||
if (outputOptions.outputHandler != NULL) {
|
if (outputOptions.outputHandler != NULL) {
|
||||||
outputOptions.outputHandler->writeData(&block, sizeof(block));
|
outputOptions.outputHandler->writeData(&block, sizeof(block));
|
||||||
|
@ -43,25 +43,43 @@ inline static void extractColorBlockRGB(const ColorBlock & rgba, Vector3 block[1
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline static uint extractColorBlockRGBA(const ColorBlock & rgba, Vector3 block[16])
|
||||||
|
{
|
||||||
|
int num = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < 16; i++)
|
||||||
|
{
|
||||||
|
const Color32 c = rgba.color(i);
|
||||||
|
if (c.a > 127)
|
||||||
|
{
|
||||||
|
block[num++] = Vector3(c.r, c.g, c.b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// find minimum and maximum colors based on bounding box in color space
|
// find minimum and maximum colors based on bounding box in color space
|
||||||
inline static void findMinMaxColorsBox(Vector3 block[16], Vector3 * __restrict maxColor, Vector3 * __restrict minColor)
|
inline static void findMinMaxColorsBox(const Vector3 * block, uint num, Vector3 * __restrict maxColor, Vector3 * __restrict minColor)
|
||||||
{
|
{
|
||||||
*maxColor = Vector3(0, 0, 0);
|
*maxColor = Vector3(0, 0, 0);
|
||||||
*minColor = Vector3(255, 255, 255);
|
*minColor = Vector3(255, 255, 255);
|
||||||
|
|
||||||
for (int i = 0; i < 16; i++)
|
for (int i = 0; i < num; i++)
|
||||||
{
|
{
|
||||||
*maxColor = max(*maxColor, block[i]);
|
*maxColor = max(*maxColor, block[i]);
|
||||||
*minColor = min(*minColor, block[i]);
|
*minColor = min(*minColor, block[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static void selectDiagonal(Vector3 block[16], Vector3 * __restrict maxColor, Vector3 * __restrict minColor)
|
|
||||||
|
inline static void selectDiagonal(const Vector3 * block, uint num, Vector3 * __restrict maxColor, Vector3 * __restrict minColor)
|
||||||
{
|
{
|
||||||
Vector3 center = (*maxColor + *minColor) * 0.5;
|
Vector3 center = (*maxColor + *minColor) * 0.5;
|
||||||
|
|
||||||
Vector2 covariance = Vector2(zero);
|
Vector2 covariance = Vector2(zero);
|
||||||
for (int i = 0; i < 16; i++)
|
for (int i = 0; i < num; i++)
|
||||||
{
|
{
|
||||||
Vector3 t = block[i] - center;
|
Vector3 t = block[i] - center;
|
||||||
covariance += t.xy() * t.z();
|
covariance += t.xy() * t.z();
|
||||||
@ -111,21 +129,21 @@ inline static float colorDistance(Vector3::Arg c0, Vector3::Arg c1)
|
|||||||
return dot(c0-c1, c0-c1);
|
return dot(c0-c1, c0-c1);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static uint computeIndices(Vector3 block[16], Vector3::Arg maxColor, Vector3::Arg minColor)
|
inline static uint computeIndices4(Vector3 block[16], Vector3::Arg maxColor, Vector3::Arg minColor)
|
||||||
{
|
{
|
||||||
Vector3 c[4];
|
Vector3 palette[4];
|
||||||
c[0] = maxColor;
|
palette[0] = maxColor;
|
||||||
c[1] = minColor;
|
palette[1] = minColor;
|
||||||
c[2] = lerp(c[0], c[1], 1.0/3.0);
|
palette[2] = lerp(palette[0], palette[1], 1.0f / 3.0f);
|
||||||
c[3] = lerp(c[0], c[1], 2.0/3.0);
|
palette[3] = lerp(palette[0], palette[1], 2.0f / 3.0f);
|
||||||
|
|
||||||
uint indices = 0;
|
uint indices = 0;
|
||||||
for(int i = 0; i < 16; i++)
|
for(int i = 0; i < 16; i++)
|
||||||
{
|
{
|
||||||
float d0 = colorDistance(c[0], block[i]);
|
float d0 = colorDistance(palette[0], block[i]);
|
||||||
float d1 = colorDistance(c[1], block[i]);
|
float d1 = colorDistance(palette[1], block[i]);
|
||||||
float d2 = colorDistance(c[2], block[i]);
|
float d2 = colorDistance(palette[2], block[i]);
|
||||||
float d3 = colorDistance(c[3], block[i]);
|
float d3 = colorDistance(palette[3], block[i]);
|
||||||
|
|
||||||
uint b0 = d0 > d3;
|
uint b0 = d0 > d3;
|
||||||
uint b1 = d1 > d2;
|
uint b1 = d1 > d2;
|
||||||
@ -143,7 +161,37 @@ inline static uint computeIndices(Vector3 block[16], Vector3::Arg maxColor, Vect
|
|||||||
return indices;
|
return indices;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void optimizeEndPoints(Vector3 block[16], BlockDXT1 * dxtBlock)
|
inline static uint computeIndices3(const ColorBlock & rgba, 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++)
|
||||||
|
{
|
||||||
|
Color32 c = rgba.color(i);
|
||||||
|
Vector3 color = Vector3(c.r, c.g, c.b);
|
||||||
|
|
||||||
|
float d0 = colorDistance(palette[0], color);
|
||||||
|
float d1 = colorDistance(palette[1], color);
|
||||||
|
float d2 = colorDistance(palette[2], color);
|
||||||
|
|
||||||
|
uint index;
|
||||||
|
if (c.a < 128) index = 3;
|
||||||
|
else 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)
|
||||||
{
|
{
|
||||||
float alpha2_sum = 0.0f;
|
float alpha2_sum = 0.0f;
|
||||||
float beta2_sum = 0.0f;
|
float beta2_sum = 0.0f;
|
||||||
@ -166,7 +214,10 @@ static void optimizeEndPoints(Vector3 block[16], BlockDXT1 * dxtBlock)
|
|||||||
betax_sum += beta * block[i];
|
betax_sum += beta * block[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
float factor = 1.0f / (alpha2_sum * beta2_sum - alphabeta_sum * alphabeta_sum);
|
float denom = alpha2_sum * beta2_sum - alphabeta_sum * alphabeta_sum;
|
||||||
|
if (equal(denom, 0.0f)) return;
|
||||||
|
|
||||||
|
float factor = 1.0f / denom;
|
||||||
|
|
||||||
Vector3 a = (alphax_sum * beta2_sum - betax_sum * alphabeta_sum) * factor;
|
Vector3 a = (alphax_sum * beta2_sum - betax_sum * alphabeta_sum) * factor;
|
||||||
Vector3 b = (betax_sum * alpha2_sum - alphax_sum * alphabeta_sum) * factor;
|
Vector3 b = (betax_sum * alpha2_sum - alphax_sum * alphabeta_sum) * factor;
|
||||||
@ -185,9 +236,57 @@ static void optimizeEndPoints(Vector3 block[16], BlockDXT1 * dxtBlock)
|
|||||||
|
|
||||||
dxtBlock->col0 = Color16(color0);
|
dxtBlock->col0 = Color16(color0);
|
||||||
dxtBlock->col1 = Color16(color1);
|
dxtBlock->col1 = Color16(color1);
|
||||||
dxtBlock->indices = computeIndices(block, a, b);
|
dxtBlock->indices = computeIndices4(block, a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*static void optimizeEndPoints3(Vector3 block[16], BlockDXT1 * dxtBlock)
|
||||||
|
{
|
||||||
|
float alpha2_sum = 0.0f;
|
||||||
|
float beta2_sum = 0.0f;
|
||||||
|
float alphabeta_sum = 0.0f;
|
||||||
|
Vector3 alphax_sum(zero);
|
||||||
|
Vector3 betax_sum(zero);
|
||||||
|
|
||||||
|
for( int i = 0; i < 16; ++i )
|
||||||
|
{
|
||||||
|
const uint bits = dxtBlock->indices >> (2 * i);
|
||||||
|
|
||||||
|
float beta = (bits & 1);
|
||||||
|
if (bits & 2) beta = 0.5f;
|
||||||
|
float alpha = 1.0f - beta;
|
||||||
|
|
||||||
|
alpha2_sum += alpha * alpha;
|
||||||
|
beta2_sum += beta * beta;
|
||||||
|
alphabeta_sum += alpha * beta;
|
||||||
|
alphax_sum += alpha * block[i];
|
||||||
|
betax_sum += beta * block[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
float denom = alpha2_sum * beta2_sum - alphabeta_sum * alphabeta_sum;
|
||||||
|
if (equal(denom, 0.0f)) return;
|
||||||
|
|
||||||
|
float factor = 1.0f / denom;
|
||||||
|
|
||||||
|
Vector3 a = (alphax_sum * beta2_sum - betax_sum * alphabeta_sum) * factor;
|
||||||
|
Vector3 b = (betax_sum * alpha2_sum - alphax_sum * alphabeta_sum) * factor;
|
||||||
|
|
||||||
|
a = clamp(a, 0, 255);
|
||||||
|
b = clamp(b, 0, 255);
|
||||||
|
|
||||||
|
uint16 color0 = roundAndExpand(&a);
|
||||||
|
uint16 color1 = roundAndExpand(&b);
|
||||||
|
|
||||||
|
if (color0 < color1)
|
||||||
|
{
|
||||||
|
swap(a, b);
|
||||||
|
swap(color0, color1);
|
||||||
|
}
|
||||||
|
|
||||||
|
dxtBlock->col0 = Color16(color1);
|
||||||
|
dxtBlock->col1 = Color16(color0);
|
||||||
|
dxtBlock->indices = computeIndices3(block, a, b);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
|
||||||
void QuickCompress::compressDXT1(const ColorBlock & rgba, BlockDXT1 * dxtBlock)
|
void QuickCompress::compressDXT1(const ColorBlock & rgba, BlockDXT1 * dxtBlock)
|
||||||
{
|
{
|
||||||
@ -197,9 +296,9 @@ void QuickCompress::compressDXT1(const ColorBlock & rgba, BlockDXT1 * dxtBlock)
|
|||||||
|
|
||||||
// find min and max colors
|
// find min and max colors
|
||||||
Vector3 maxColor, minColor;
|
Vector3 maxColor, minColor;
|
||||||
findMinMaxColorsBox(block, &maxColor, &minColor);
|
findMinMaxColorsBox(block, 16, &maxColor, &minColor);
|
||||||
|
|
||||||
selectDiagonal(block, &maxColor, &minColor);
|
selectDiagonal(block, 16, &maxColor, &minColor);
|
||||||
|
|
||||||
insetBBox(&maxColor, &minColor);
|
insetBBox(&maxColor, &minColor);
|
||||||
|
|
||||||
@ -214,9 +313,48 @@ void QuickCompress::compressDXT1(const ColorBlock & rgba, BlockDXT1 * dxtBlock)
|
|||||||
|
|
||||||
dxtBlock->col0 = Color16(color0);
|
dxtBlock->col0 = Color16(color0);
|
||||||
dxtBlock->col1 = Color16(color1);
|
dxtBlock->col1 = Color16(color1);
|
||||||
dxtBlock->indices = computeIndices(block, maxColor, minColor);
|
dxtBlock->indices = computeIndices4(block, maxColor, minColor);
|
||||||
|
|
||||||
optimizeEndPoints(block, dxtBlock);
|
optimizeEndPoints4(block, dxtBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void QuickCompress::compressDXT1a(const ColorBlock & rgba, BlockDXT1 * dxtBlock)
|
||||||
|
{
|
||||||
|
if (!rgba.hasAlpha())
|
||||||
|
{
|
||||||
|
compressDXT1(rgba, dxtBlock);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// read block
|
||||||
|
Vector3 block[16];
|
||||||
|
uint num = extractColorBlockRGBA(rgba, block);
|
||||||
|
|
||||||
|
// find min and max colors
|
||||||
|
Vector3 maxColor, minColor;
|
||||||
|
findMinMaxColorsBox(block, num, &maxColor, &minColor);
|
||||||
|
|
||||||
|
selectDiagonal(block, num, &maxColor, &minColor);
|
||||||
|
|
||||||
|
insetBBox(&maxColor, &minColor);
|
||||||
|
|
||||||
|
uint16 color0 = roundAndExpand(&maxColor);
|
||||||
|
uint16 color1 = roundAndExpand(&minColor);
|
||||||
|
|
||||||
|
if (color0 < color1)
|
||||||
|
{
|
||||||
|
swap(maxColor, minColor);
|
||||||
|
swap(color0, color1);
|
||||||
|
}
|
||||||
|
|
||||||
|
dxtBlock->col0 = Color16(color1);
|
||||||
|
dxtBlock->col1 = Color16(color0);
|
||||||
|
dxtBlock->indices = computeIndices3(rgba, maxColor, minColor);
|
||||||
|
|
||||||
|
// optimizeEndPoints(block, dxtBlock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -33,7 +33,8 @@ namespace nv
|
|||||||
|
|
||||||
namespace QuickCompress
|
namespace QuickCompress
|
||||||
{
|
{
|
||||||
void compressDXT1(const ColorBlock & rgba, BlockDXT1 * block);
|
void compressDXT1(const ColorBlock & rgba, BlockDXT1 * dxtBlock);
|
||||||
|
void compressDXT1a(const ColorBlock & rgba, BlockDXT1 * dxtBlock);
|
||||||
}
|
}
|
||||||
} // nv namespace
|
} // nv namespace
|
||||||
|
|
||||||
|
@ -74,7 +74,6 @@ struct Error
|
|||||||
|
|
||||||
void addSample(float e)
|
void addSample(float e)
|
||||||
{
|
{
|
||||||
if (fabsf(e) >= 255) nvDebugBreak();
|
|
||||||
samples++;
|
samples++;
|
||||||
mabse += fabsf(e);
|
mabse += fabsf(e);
|
||||||
maxabse = nv::max(maxabse, fabsf(e));
|
maxabse = nv::max(maxabse, fabsf(e));
|
||||||
|
Loading…
Reference in New Issue
Block a user