Get black 3-color blocks working

hotfix/mipmap-alpha-fix
Andrew Cassidy 3 years ago
parent 0924e43dc2
commit 06c9bacab0

@ -39,6 +39,8 @@
#include "SingleColorTable.h"
namespace rgbcx {
using namespace BC1;
using InterpolatorPtr = std::shared_ptr<Interpolator>;
using Hash = uint16_t;
using BlockMetrics = Color4x4::BlockMetrics;
@ -47,7 +49,8 @@ using ColorMode = BC1Encoder::ColorMode;
// constructors
BC1Encoder::BC1Encoder(InterpolatorPtr interpolator) : _interpolator(interpolator) {
_flags = Flags::UseFullMSEEval | Flags::TwoLeastSquaresPasses | Flags::UseLikelyTotalOrderings | Flags::Use3ColorBlocks;
_flags =
Flags::UseFullMSEEval | Flags::TwoLeastSquaresPasses | Flags::UseLikelyTotalOrderings | Flags::Use3ColorBlocks | Flags::Use3ColorBlocksForBlackPixels;
_error_mode = ErrorMode::Full;
_endpoint_mode = EndpointMode::PCA;
_orderings4 = 16;
@ -123,7 +126,20 @@ void BC1Encoder::EncodeBlock(Color4x4 pixels, BC1Block *dest) const {
}
}
if (trial_result.error < result.error) { result = trial_result; };
if (trial_result.error < result.error) { result = trial_result; }
}
// try for 3-color block with black
if (result.error > 0 && (bool)(_flags & Flags::Use3ColorBlocksForBlackPixels) && metrics.has_black && !metrics.max.IsBlack()) {
EncodeResults trial_result;
BlockMetrics metrics_no_black = pixels.GetMetrics(true);
FindEndpoints(pixels, trial_result, metrics_no_black, EndpointMode::PCA, true);
FindSelectors<ColorMode::ThreeColorBlack>(pixels, trial_result, ErrorMode::Full);
RefineBlockLS<ColorMode::ThreeColorBlack>(pixels, trial_result, metrics_no_black, ErrorMode::Full, total_ls_passes);
if (trial_result.error < result.error) {
result = trial_result; }
}
WriteBlock(result, dest);
@ -230,8 +246,6 @@ void BC1Encoder::WriteBlock(EncodeResults &block, BC1Block *dest) const {
if (block.color_mode == ColorMode::ThreeColor) { assert(selectors[y][x] != 3); }
}
// if (block.color_mode != ColorMode::ThreeColor) return;
dest->SetLowColor(color0);
dest->SetHighColor(color1);
dest->PackSelectors(selectors);
@ -267,7 +281,7 @@ void BC1Encoder::FindEndpointsSingleColor(EncodeResults &block, Color4x4 &pixels
}
}
void BC1Encoder::FindEndpoints(Color4x4 pixels, EncodeResults &block, const BlockMetrics &metrics, EndpointMode endpoint_mode) const {
void BC1Encoder::FindEndpoints(Color4x4 pixels, EncodeResults &block, const BlockMetrics &metrics, EndpointMode endpoint_mode, bool ignore_black) const {
if (metrics.is_greyscale) {
// specialized greyscale case
const unsigned fr = pixels.Get(0).r;
@ -407,15 +421,16 @@ void BC1Encoder::FindEndpoints(Color4x4 pixels, EncodeResults &block, const Bloc
auto max = Vector4::FromColorRGB(metrics.max);
auto avg = Vector4::FromColorRGB(metrics.avg);
std::array<Vector4, 16> colors;
Vector4 axis = {306, 601, 117}; // Luma vector
Matrix4x4 covariance = Matrix4x4::Identity();
const unsigned total_power_iters = (_flags & Flags::Use6PowerIters) != Flags::None ? 6 : 4;
for (unsigned i = 0; i < 16; i++) {
colors[i] = Vector4::FromColorRGB(pixels.Get(i));
Vector4 diff = colors[i] - avg;
auto val = pixels.Get(i);
if (ignore_black && val.IsBlack()) continue;
auto colorVec = Vector4::FromColorRGB(val);
Vector4 diff = colorVec - avg;
for (unsigned c1 = 0; c1 < 3; c1++) {
for (unsigned c2 = c1; c2 < 3; c2++) {
covariance[c1][c2] += (diff[c1] * diff[c2]);
@ -449,9 +464,13 @@ void BC1Encoder::FindEndpoints(Color4x4 pixels, EncodeResults &block, const Bloc
unsigned min_index = 0, max_index = 0;
for (unsigned i = 0; i < 16; i++) {
auto val = pixels.Get(i);
if (ignore_black && val.IsBlack()) continue;
auto colorVec = Vector4::FromColorRGB(val);
// since axis is constant here, I dont think its magnitude actually matters,
// since we only care about the min or max dot product
float dot = colors[i].Dot(axis);
float dot = colorVec.Dot(axis);
if (dot > max_dot) {
max_dot = dot;
max_index = i;
@ -479,9 +498,11 @@ template <ColorMode M> void BC1Encoder::FindSelectors(Color4x4 &pixels, EncodeRe
std::array<Vector4Int, 4> color_vectors;
if (color_count == 4) {
color_vectors = {(Vector4Int)colors[0], (Vector4Int)colors[2], (Vector4Int)colors[3], (Vector4Int)colors[1]};
color_vectors = {Vector4Int::FromColorRGB(colors[0]), Vector4Int::FromColorRGB(colors[2]), Vector4Int::FromColorRGB(colors[3]),
Vector4Int::FromColorRGB(colors[1])};
} else {
color_vectors = {(Vector4Int)colors[0], (Vector4Int)colors[2], (Vector4Int)colors[1], (Vector4Int)colors[3]};
color_vectors = {Vector4Int::FromColorRGB(colors[0]), Vector4Int::FromColorRGB(colors[2]), Vector4Int::FromColorRGB(colors[1]),
Vector4Int::FromColorRGB(colors[3])};
}
unsigned total_error = 0;
@ -545,7 +566,7 @@ template <ColorMode M> void BC1Encoder::FindSelectors(Color4x4 &pixels, EncodeRe
for (unsigned i = 0; i < 16; i++) {
unsigned best_error = UINT_MAX;
uint8_t best_sel = 0;
Vector4Int pixel_vector = (Vector4Int)pixels.Get(i);
Vector4Int pixel_vector = Vector4Int::FromColorRGB(pixels.Get(i));
// exhasustively check every pixel's distance from each color, and calculate the error
for (uint8_t j = 0; j < max_sel; j++) {

@ -134,10 +134,10 @@ class BC1Encoder final : public BlockEncoder<BC1Block, 4, 4> {
// Each entry includes a high and low pair that best reproduces the 8-bit index as well as possible,
// with an included error value
// these depend on the interpolator
const MatchListPtr _single_match5 = SingleColorTable<5, 4>(_interpolator);
const MatchListPtr _single_match6 = SingleColorTable<6, 4>(_interpolator);
const MatchListPtr _single_match5_half = SingleColorTable<5, 3>(_interpolator);
const MatchListPtr _single_match6_half = SingleColorTable<6, 3>(_interpolator);
const BC1::MatchListPtr _single_match5 = BC1::SingleColorTable<5, 4>(_interpolator);
const BC1::MatchListPtr _single_match6 = BC1::SingleColorTable<6, 4>(_interpolator);
const BC1::MatchListPtr _single_match5_half = BC1::SingleColorTable<5, 3>(_interpolator);
const BC1::MatchListPtr _single_match6_half = BC1::SingleColorTable<6, 3>(_interpolator);
Flags _flags;
ErrorMode _error_mode;
@ -149,7 +149,7 @@ class BC1Encoder final : public BlockEncoder<BC1Block, 4, 4> {
void WriteBlockSolid(Color color, BC1Block *dest) const;
void WriteBlock(EncodeResults &block, BC1Block *dest) const;
void FindEndpoints(Color4x4 pixels, EncodeResults &block, const BlockMetrics &metrics, EndpointMode endpoint_mode) const;
void FindEndpoints(Color4x4 pixels, EncodeResults &block, const BlockMetrics &metrics, EndpointMode endpoint_mode, bool ignore_black = false) const;
void FindEndpointsSingleColor(EncodeResults &block, Color color, bool is_3color = false) const;
void FindEndpointsSingleColor(EncodeResults &block, Color4x4 &pixels, Color color, bool is_3color) const;

@ -1,26 +0,0 @@
/* Python-rgbcx Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
namespace rgbcx {
void ComputeEndpoints()
} // namespace rgbcx::ClusterFit

@ -30,7 +30,7 @@
#include "../Vector4.h"
#include "../util.h"
namespace rgbcx {
namespace rgbcx::BC1 {
template <size_t N> class Histogram {
public:
using Hash = uint16_t;

@ -23,7 +23,7 @@
#include "../Vector4.h"
namespace rgbcx {
namespace rgbcx::BC1 {
using Hash = uint16_t;
template <> std::atomic<bool> OrderTable<3>::generated = false;

@ -29,7 +29,7 @@
#include "../Vector4.h"
#include "Histogram.h"
namespace rgbcx {
namespace rgbcx::BC1 {
template <size_t N> class OrderTable {
public:
static constexpr unsigned HashCount = 1 << ((N - 1) * 4); // 16**(N-1)

@ -26,7 +26,7 @@
#include "../Interpolator.h"
#include "../util.h"
namespace rgbcx {
namespace rgbcx::BC1 {
struct BC1MatchEntry {
uint8_t high;

@ -61,6 +61,8 @@ template <class B, size_t M, size_t N> class BlockEncoder {
unsigned top_left = pixel_x + (pixel_y * image_width);
auto src = DecodedBlock(&decoded[top_left], (int)image_width);
// if (pixel_x != 684 || pixel_y != 492) continue;
EncodeBlock(src, &blocks[x + block_width * y]);
}
}

Loading…
Cancel
Save