Remove legacy compressors.
Add iteration count parameter to iterative alpha compressor. Add optimal compressors.
This commit is contained in:
@ -29,7 +29,7 @@
|
||||
#include <nvimage/BlockDXT.h>
|
||||
|
||||
#include "QuickCompressDXT.h"
|
||||
#include "SingleColorLookup.h"
|
||||
#include "OptimalCompressDXT.h"
|
||||
|
||||
|
||||
using namespace nv;
|
||||
@ -290,70 +290,6 @@ static void optimizeEndPoints4(Vector3 block[16], BlockDXT1 * dxtBlock)
|
||||
dxtBlock->indices = computeIndices3(block, a, b);
|
||||
}*/
|
||||
|
||||
namespace
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
@ -505,79 +441,53 @@ namespace
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Single color compressor, based on:
|
||||
// https://mollyrocket.com/forums/viewtopic.php?t=392
|
||||
void QuickCompress::compressDXT1(Color32 c, BlockDXT1 * dxtBlock)
|
||||
{
|
||||
dxtBlock->col0.r = OMatch5[c.r][0];
|
||||
dxtBlock->col0.g = OMatch6[c.g][0];
|
||||
dxtBlock->col0.b = OMatch5[c.b][0];
|
||||
dxtBlock->col1.r = OMatch5[c.r][1];
|
||||
dxtBlock->col1.g = OMatch6[c.g][1];
|
||||
dxtBlock->col1.b = OMatch5[c.b][1];
|
||||
dxtBlock->indices = 0xaaaaaaaa;
|
||||
|
||||
if (dxtBlock->col0.u < dxtBlock->col1.u)
|
||||
{
|
||||
swap(dxtBlock->col0.u, dxtBlock->col1.u);
|
||||
dxtBlock->indices ^= 0x55555555;
|
||||
}
|
||||
}
|
||||
|
||||
void QuickCompress::compressDXT1(const ColorBlock & rgba, BlockDXT1 * dxtBlock)
|
||||
{
|
||||
// read block
|
||||
Vector3 block[16];
|
||||
extractColorBlockRGB(rgba, block);
|
||||
|
||||
// find min and max colors
|
||||
Vector3 maxColor, minColor;
|
||||
findMinMaxColorsBox(block, 16, &maxColor, &minColor);
|
||||
|
||||
selectDiagonal(block, 16, &maxColor, &minColor);
|
||||
|
||||
insetBBox(&maxColor, &minColor);
|
||||
|
||||
uint16 color0 = roundAndExpand(&maxColor);
|
||||
uint16 color1 = roundAndExpand(&minColor);
|
||||
|
||||
if (color0 < color1)
|
||||
if (rgba.isSingleColor())
|
||||
{
|
||||
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::compressDXT1a(Color32 rgba, BlockDXT1 * dxtBlock)
|
||||
{
|
||||
if (rgba.a == 0)
|
||||
{
|
||||
dxtBlock->col0.u = 0;
|
||||
dxtBlock->col1.u = 0;
|
||||
dxtBlock->indices = 0xFFFFFFFF;
|
||||
OptimalCompress::compressDXT1(rgba.color(0), dxtBlock);
|
||||
}
|
||||
else
|
||||
{
|
||||
compressDXT1(rgba, dxtBlock);
|
||||
// read block
|
||||
Vector3 block[16];
|
||||
extractColorBlockRGB(rgba, block);
|
||||
|
||||
// find min and max colors
|
||||
Vector3 maxColor, minColor;
|
||||
findMinMaxColorsBox(block, 16, &maxColor, &minColor);
|
||||
|
||||
selectDiagonal(block, 16, &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(color0);
|
||||
dxtBlock->col1 = Color16(color1);
|
||||
dxtBlock->indices = computeIndices4(block, maxColor, minColor);
|
||||
|
||||
optimizeEndPoints4(block, dxtBlock);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void QuickCompress::compressDXT1a(const ColorBlock & rgba, BlockDXT1 * dxtBlock)
|
||||
{
|
||||
if (!rgba.hasAlpha())
|
||||
{
|
||||
compressDXT1(rgba, dxtBlock);
|
||||
}
|
||||
else
|
||||
// @@ Handle single RGB, with varying alpha? We need tables for single color compressor in 3 color mode.
|
||||
//else if (rgba.isSingleColorNoAlpha()) { ... }
|
||||
else
|
||||
{
|
||||
// read block
|
||||
Vector3 block[16];
|
||||
@ -609,95 +519,14 @@ void QuickCompress::compressDXT1a(const ColorBlock & rgba, BlockDXT1 * dxtBlock)
|
||||
}
|
||||
|
||||
|
||||
// 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.r = 31;
|
||||
block->col1.r = 31;
|
||||
block->col0.g = maxg;
|
||||
block->col1.g = ming;
|
||||
block->col0.b = 0;
|
||||
block->col1.b = 0;
|
||||
|
||||
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)
|
||||
{
|
||||
// @@ Round instead of truncate. When rounding take into account bit expansion.
|
||||
dxtBlock->alpha0 = rgba.color(0).a >> 4;
|
||||
dxtBlock->alpha1 = rgba.color(1).a >> 4;
|
||||
dxtBlock->alpha2 = rgba.color(2).a >> 4;
|
||||
dxtBlock->alpha3 = rgba.color(3).a >> 4;
|
||||
dxtBlock->alpha4 = rgba.color(4).a >> 4;
|
||||
dxtBlock->alpha5 = rgba.color(5).a >> 4;
|
||||
dxtBlock->alpha6 = rgba.color(6).a >> 4;
|
||||
dxtBlock->alpha7 = rgba.color(7).a >> 4;
|
||||
dxtBlock->alpha8 = rgba.color(8).a >> 4;
|
||||
dxtBlock->alpha9 = rgba.color(9).a >> 4;
|
||||
dxtBlock->alphaA = rgba.color(10).a >> 4;
|
||||
dxtBlock->alphaB = rgba.color(11).a >> 4;
|
||||
dxtBlock->alphaC = rgba.color(12).a >> 4;
|
||||
dxtBlock->alphaD = rgba.color(13).a >> 4;
|
||||
dxtBlock->alphaE = rgba.color(14).a >> 4;
|
||||
dxtBlock->alphaF = rgba.color(15).a >> 4;
|
||||
}
|
||||
|
||||
void QuickCompress::compressDXT3(const ColorBlock & rgba, BlockDXT3 * dxtBlock)
|
||||
{
|
||||
compressDXT1(rgba, &dxtBlock->color);
|
||||
compressDXT3A(rgba, &dxtBlock->alpha);
|
||||
OptimalCompress::compressDXT3A(rgba, &dxtBlock->alpha);
|
||||
}
|
||||
|
||||
|
||||
void QuickCompress::compressDXT5A(const ColorBlock & rgba, AlphaBlockDXT5 * dxtBlock)
|
||||
void QuickCompress::compressDXT5A(const ColorBlock & rgba, AlphaBlockDXT5 * dxtBlock, int iterationCount/*=8*/)
|
||||
{
|
||||
uint8 alpha0 = 0;
|
||||
uint8 alpha1 = 255;
|
||||
@ -716,8 +545,8 @@ void QuickCompress::compressDXT5A(const ColorBlock & rgba, AlphaBlockDXT5 * dxtB
|
||||
uint besterror = computeAlphaIndices(rgba, &block);
|
||||
|
||||
AlphaBlockDXT5 bestblock = block;
|
||||
|
||||
while(true)
|
||||
|
||||
for (int i = 0; i < iterationCount; i++)
|
||||
{
|
||||
optimizeAlpha8(rgba, &block);
|
||||
uint error = computeAlphaIndices(rgba, &block);
|
||||
@ -741,9 +570,8 @@ void QuickCompress::compressDXT5A(const ColorBlock & rgba, AlphaBlockDXT5 * dxtB
|
||||
*dxtBlock = bestblock;
|
||||
}
|
||||
|
||||
void QuickCompress::compressDXT5(const ColorBlock & rgba, BlockDXT5 * dxtBlock)
|
||||
void QuickCompress::compressDXT5(const ColorBlock & rgba, BlockDXT5 * dxtBlock, int iterationCount/*=8*/)
|
||||
{
|
||||
compressDXT1(rgba, &dxtBlock->color);
|
||||
compressDXT5A(rgba, &dxtBlock->alpha);
|
||||
compressDXT5A(rgba, &dxtBlock->alpha, iterationCount);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user