Preliminary PVRTC alpha support.

This fixes #17.

However, it's a preliminary pass that only really operates on the image
included in #16. There are likely better ways to optimize the alpha
used in the images, but I'm not sure what that is. Likely it's better
to use separate alpha dilation than the intensity dilation algorithm
currently used.
This commit is contained in:
Pavel Krajcevski 2016-03-03 15:59:14 -05:00
parent d85b0d1add
commit 2859dbb6e4

View file

@ -68,7 +68,10 @@
#include "Block.h" #include "Block.h"
#include "Indexer.h" #include "Indexer.h"
#define USE_CONSTANT_LUTS // !FIXME! Figure out why the PSNR of these LUTs is worse than when
// we don't use them -- they should be optimal. This is reflected
// in Github issue #19
// #define USE_CONSTANT_LUTS
namespace PVRTCC { namespace PVRTCC {
@ -506,6 +509,9 @@ namespace PVRTCC {
for(uint32 j = 0; j < blocksH; j++) { for(uint32 j = 0; j < blocksH; j++) {
for(uint32 i = 0; i < blocksW; i++) { for(uint32 i = 0; i < blocksW; i++) {
bool isHole[2][16];
memset(isHole, 0, sizeof(isHole));
float minIntensity = 1.1f, maxIntensity = -0.1f; float minIntensity = 1.1f, maxIntensity = -0.1f;
uint32 minIntensityIdx = 0, maxIntensityIdx = 0; uint32 minIntensityIdx = 0, maxIntensityIdx = 0;
for(uint32 y = j*4; y <= (j+1)*4; y++) for(uint32 y = j*4; y <= (j+1)*4; y++)
@ -532,15 +538,13 @@ namespace PVRTCC {
if(labels[idx].highLabel.distance > 0) { if(labels[idx].highLabel.distance > 0) {
blockColors[0][localIdx] = CollectLabel(pixels, labels[idx].highLabel); blockColors[0][localIdx] = CollectLabel(pixels, labels[idx].highLabel);
} else { } else {
// Mark the color as unused isHole[0][localIdx] = true;
blockColors[0][localIdx].A() = -1.0f;
} }
if(labels[idx].lowLabel.distance > 0) { if(labels[idx].lowLabel.distance > 0) {
blockColors[1][localIdx] = CollectLabel(pixels, labels[idx].lowLabel); blockColors[1][localIdx] = CollectLabel(pixels, labels[idx].lowLabel);
} else { } else {
// Mark the color as unused isHole[1][localIdx] = true;
blockColors[1][localIdx].A() = -1.0f;
} }
} }
@ -550,7 +554,16 @@ namespace PVRTCC {
// Assume all same color // Assume all same color
FasTC::Pixel color(pixels[minIntensityIdx]); FasTC::Pixel color(pixels[minIntensityIdx]);
if(color.A() < 0xFF) { if(color.A() < 0xFF) {
assert(!"Implement me!"); if (color.A() == 0) {
color.Unpack(0); // Set to total black
b.SetColorA(color);
b.SetColorB(color);
} else {
// !FIXME! Actually compute better lookup tables for
// this case...
b.SetColorA(color, color.A() < 200);
b.SetColorB(color, color.A() < 200);
}
} else { } else {
FasTC::Pixel high, low; FasTC::Pixel high, low;
high.A() = low.A() = 0xFF; high.A() = low.A() = 0xFF;
@ -576,13 +589,13 @@ namespace PVRTCC {
for(uint32 x = 0; x < localIdxr.GetWidth(); x++) { for(uint32 x = 0; x < localIdxr.GetWidth(); x++) {
uint32 idx = localIdxr(x, y); uint32 idx = localIdxr(x, y);
FasTC::Color c = blockColors[0][idx]; FasTC::Color c = blockColors[0][idx];
if(c.A() < 0.0f) { if(isHole[0][idx]) {
c.Unpack(pixels[maxIntensityIdx]); c.Unpack(pixels[maxIntensityIdx]);
} }
high += c * (1.0f / 16.0f); high += c * (1.0f / 16.0f);
c = blockColors[1][idx]; c = blockColors[1][idx];
if(c.A() < 0.0f) { if(isHole[1][idx]) {
c.Unpack(pixels[minIntensityIdx]); c.Unpack(pixels[minIntensityIdx]);
} }
low += c * (1.0f / 16.0f); low += c * (1.0f / 16.0f);
@ -591,10 +604,10 @@ namespace PVRTCC {
// Store them as our endpoints for this block... // Store them as our endpoints for this block...
FasTC::Pixel p; FasTC::Pixel p;
p.Unpack(high.Pack()); p.Unpack(high.Pack());
b.SetColorA(p); b.SetColorA(p, p.A() < 200);
p.Unpack(low.Pack()); p.Unpack(low.Pack());
b.SetColorB(p); b.SetColorB(p, p.B() < 200);
#ifdef USE_CONSTANT_LUTS #ifdef USE_CONSTANT_LUTS
} }
#endif #endif
@ -739,6 +752,7 @@ namespace PVRTCC {
int32 o = original.Component(c); int32 o = original.Component(c);
errorVec[c] = r - o; errorVec[c] = r - o;
} }
uint32 error = static_cast<uint64>(errorVec.LengthSq()); uint32 error = static_cast<uint64>(errorVec.LengthSq());
if(error < bestError) { if(error < bestError) {