Work in progress. Experiment with lightmap compression.
This commit is contained in:
@ -6,6 +6,7 @@
|
||||
#include "nvmath/Box.h"
|
||||
#include "nvcore/Utils.h" // swap
|
||||
|
||||
#include <string.h> // memcpy
|
||||
|
||||
using namespace nv;
|
||||
|
||||
@ -457,44 +458,176 @@ float ColorBlock::volume() const
|
||||
return bounds.volume();
|
||||
}*/
|
||||
|
||||
#include "FloatImage.h"
|
||||
|
||||
|
||||
void ColorSet::init(const Image * img, uint x, uint y)
|
||||
void ColorSet::setColors(const float * data, uint img_w, uint img_h, uint img_x, uint img_y)
|
||||
{
|
||||
w = min(4U, img->width() - x);
|
||||
h = min(4U, img->height() - y);
|
||||
nvDebugCheck(img_x < img_w && img_y < img_h);
|
||||
|
||||
w = min(4U, img_w - img_x);
|
||||
h = min(4U, img_h - img_y);
|
||||
nvDebugCheck(w != 0 && h != 0);
|
||||
|
||||
// Blocks that are smaller than 4x4 are handled by repeating the pixels.
|
||||
// @@ Thats only correct when block size is 1, 2 or 4, but not with 3. :(
|
||||
// @@ Ideally we should zero the weights of the pixels out of range.
|
||||
count = w * h;
|
||||
|
||||
for (uint i = 0; i < 4; i++)
|
||||
const float * r = data + img_w * img_h * 0;
|
||||
const float * g = data + img_w * img_h * 1;
|
||||
const float * b = data + img_w * img_h * 2;
|
||||
const float * a = data + img_w * img_h * 3;
|
||||
|
||||
// Set colors.
|
||||
for (uint y = 0, i = 0; y < h; y++)
|
||||
{
|
||||
const uint by = i % h;
|
||||
|
||||
for (uint e = 0; e < 4; e++)
|
||||
for (uint x = 0; x < w; x++, i++)
|
||||
{
|
||||
const uint bx = e % w;
|
||||
Color32 c = img->pixel(x+bx, y+by);
|
||||
Vector4 & v = color(e, i);
|
||||
v.x = c.r / 255.0f;
|
||||
v.y = c.g / 255.0f;
|
||||
v.z = c.b / 255.0f;
|
||||
v.w = c.a / 255.0f;
|
||||
colors[i].x = r[x + img_x, y + img_y];
|
||||
colors[i].y = g[x + img_x, y + img_y];
|
||||
colors[i].z = b[x + img_x, y + img_y];
|
||||
colors[i].w = a[x + img_x, y + img_y];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ColorSet::init(const FloatImage * img, uint x, uint y)
|
||||
void ColorSet::setAlphaWeights()
|
||||
{
|
||||
for (uint i = 0; i < count; i++)
|
||||
{
|
||||
weights[i] = max(colors[i].w, 0.001f); // Avoid division by zero.
|
||||
}
|
||||
}
|
||||
|
||||
void ColorSet::init(const uint * data, uint w, uint h, uint x, uint y)
|
||||
void ColorSet::setUniformWeights()
|
||||
{
|
||||
for (uint i = 0; i < count; i++)
|
||||
{
|
||||
weights[i] = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void ColorSet::init(const float * data, uint w, uint h, uint x, uint y)
|
||||
|
||||
void ColorSet::createMinimalSet(bool ignoreTransparent)
|
||||
{
|
||||
nvDebugCheck(count == w*h); // Do not call this method multiple times.
|
||||
|
||||
Vector4 C[16];
|
||||
float W[16];
|
||||
memcpy(C, colors, sizeof(Vector4)*count);
|
||||
memcpy(W, weights, sizeof(float)*count);
|
||||
|
||||
uint n = 0;
|
||||
for (uint y = 0, i = 0; y < h; y++)
|
||||
{
|
||||
for (uint x = 0; x < w; x++, i++)
|
||||
{
|
||||
if (ignoreTransparent && C[i].w == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
uint idx = y * 4 + x;
|
||||
|
||||
// loop over previous points for a match
|
||||
for (int j = 0; ; j++)
|
||||
{
|
||||
// allocate a new point
|
||||
if (j == i)
|
||||
{
|
||||
colors[n] = C[i];
|
||||
weights[n] = W[i];
|
||||
remap[idx] = n;
|
||||
n++;
|
||||
break;
|
||||
}
|
||||
|
||||
// check for a match
|
||||
bool colorMatch = (C[i].x == C[j].x) && (C[i].w == C[j].w) && (C[i].z == C[j].z);
|
||||
//bool alphaMatch = (C[i].w == C[j].w);
|
||||
|
||||
if (colorMatch)
|
||||
{
|
||||
// get the index of the match
|
||||
int index = remap[j];
|
||||
|
||||
// map to this point and increase the weight
|
||||
weights[index] += W[i];
|
||||
remap[idx] = index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
count = n;
|
||||
|
||||
// Avoid empty blocks.
|
||||
if (count == 0) {
|
||||
count = 1;
|
||||
//colors[0] = C[0];
|
||||
//weights[0] = W[0];
|
||||
memset(remap, 0, sizeof(int)*16);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Fill blocks that are smaller than (4,4) by wrapping indices.
|
||||
void ColorSet::wrapIndices()
|
||||
{
|
||||
for (uint y = h; y < 4; y++)
|
||||
{
|
||||
uint base = (y % h) * w;
|
||||
for (uint x = w; x < 4; x++)
|
||||
{
|
||||
remap[y*4+3] = remap[base + (x % w)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ColorSet::isSingleColor(bool ignoreAlpha) const
|
||||
{
|
||||
Vector4 v = colors[0];
|
||||
if (ignoreAlpha) v.w = 1.0f;
|
||||
|
||||
for (uint i = 1; i < count; i++)
|
||||
{
|
||||
Vector4 c = colors[i];
|
||||
if (ignoreAlpha) c.w = 1.0f;
|
||||
|
||||
if (v != c) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// 0=r, 1=g, 2=b, 3=a, 4=0xFF, 5=0
|
||||
static inline float component(Vector4::Arg c, uint i)
|
||||
{
|
||||
if (i == 0) return c.x;
|
||||
if (i == 1) return c.y;
|
||||
if (i == 2) return c.z;
|
||||
if (i == 3) return c.w;
|
||||
if (i == 4) return 0xFF;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ColorSet::swizzle(uint x, uint y, uint z, uint w)
|
||||
{
|
||||
for (uint i = 0; i < count; i++)
|
||||
{
|
||||
Vector4 c = colors[i];
|
||||
colors[i].x = component(c, x);
|
||||
colors[i].y = component(c, y);
|
||||
colors[i].z = component(c, z);
|
||||
colors[i].w = component(c, w);
|
||||
}
|
||||
}
|
||||
|
||||
bool ColorSet::hasAlpha() const
|
||||
{
|
||||
for (uint i = 0; i < count; i++)
|
||||
{
|
||||
if (colors[i].w != 0.0f) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -82,22 +82,33 @@ namespace nv
|
||||
|
||||
struct ColorSet
|
||||
{
|
||||
ColorSet() : w(4), h(4) {}
|
||||
ColorSet(uint w, uint h) : w(w), h(h) {}
|
||||
void setColors(const float * data, uint img_w, uint img_h, uint img_x, uint img_y);
|
||||
|
||||
void init(const Image * img, uint x, uint y);
|
||||
void init(const FloatImage * img, uint x, uint y);
|
||||
void init(const uint * data, uint w, uint h, uint x, uint y);
|
||||
void init(const float * data, uint w, uint h, uint x, uint y);
|
||||
void setAlphaWeights();
|
||||
void setUniformWeights();
|
||||
|
||||
Vector4 color(uint x, uint y) const { nvDebugCheck(x < w && y < h); return colors[y * 4 + x]; }
|
||||
Vector4 & color(uint x, uint y) { nvDebugCheck(x < w && y < h); return colors[y * 4 + x]; }
|
||||
void createMinimalSet(bool ignoreTransparent);
|
||||
void wrapIndices();
|
||||
|
||||
Vector4 color(uint i) const { nvDebugCheck(i < 16); return colors[i]; }
|
||||
Vector4 & color(uint i) { nvDebugCheck(i < 16); return colors[i]; }
|
||||
void swizzle(uint x, uint y, uint z, uint w); // 0=r, 1=g, 2=b, 3=a, 4=0xFF, 5=0
|
||||
|
||||
bool isSingleColor(bool ignoreAlpha) const;
|
||||
bool hasAlpha() const;
|
||||
|
||||
// These methods require indices to be set:
|
||||
Vector4 color(uint x, uint y) const { nvDebugCheck(x < w && y < h); return colors[remap[y * 4 + x]]; }
|
||||
Vector4 & color(uint x, uint y) { nvDebugCheck(x < w && y < h); return colors[remap[y * 4 + x]]; }
|
||||
|
||||
Vector4 color(uint i) const { nvDebugCheck(i < 16); return colors[remap[i]]; }
|
||||
Vector4 & color(uint i) { nvDebugCheck(i < 16); return colors[remap[i]]; }
|
||||
|
||||
|
||||
uint count;
|
||||
uint w, h;
|
||||
|
||||
Vector4 colors[16];
|
||||
uint w, h;
|
||||
float weights[16];
|
||||
int remap[16];
|
||||
};
|
||||
|
||||
} // nv namespace
|
||||
|
@ -146,7 +146,7 @@ static Vector3 xyzToCieLab(Vector3::Arg c)
|
||||
// Normalized white point.
|
||||
const float Xn = 0.950456f;
|
||||
const float Yn = 1.0f;
|
||||
const float Zn = 1.088754;
|
||||
const float Zn = 1.088754f;
|
||||
|
||||
float Xr = c.x / Xn;
|
||||
float Yr = c.y / Yn;
|
||||
@ -159,6 +159,8 @@ static Vector3 xyzToCieLab(Vector3::Arg c)
|
||||
float L = 116 * fx - 16;
|
||||
float a = 500 * (fx - fy);
|
||||
float b = 200 * (fy - fz);
|
||||
|
||||
return Vector3(L, a, b);
|
||||
}
|
||||
|
||||
static Vector3 rgbToCieLab(Vector3::Arg c)
|
||||
@ -222,6 +224,9 @@ float nv::cieLabError(const FloatImage * img0, const FloatImage * img1)
|
||||
Vector3 lab1 = rgbToCieLab(Vector3(r1[i], g1[i], b1[i]));
|
||||
|
||||
// @@ Measure Delta E.
|
||||
Vector3 delta = lab0 - lab1;
|
||||
|
||||
error += length(delta);
|
||||
}
|
||||
|
||||
return float(error / count);
|
||||
|
Reference in New Issue
Block a user