Work in progress. Experiment with lightmap compression.
This commit is contained in:
parent
4cbf43165c
commit
23b140416a
@ -311,6 +311,14 @@
|
|||||||
RelativePath="..\..\..\src\nvimage\DirectDrawSurface.h"
|
RelativePath="..\..\..\src\nvimage\DirectDrawSurface.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\src\nvimage\ErrorMetric.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\src\nvimage\ErrorMetric.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\src\nvimage\Filter.cpp"
|
RelativePath="..\..\..\src\nvimage\Filter.cpp"
|
||||||
>
|
>
|
||||||
|
@ -25,6 +25,11 @@ EndProject
|
|||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nvmath", "nvmath\nvmath.vcproj", "{50C465FE-B308-42BC-894D-89484482AF06}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nvmath", "nvmath\nvmath.vcproj", "{50C465FE-B308-42BC-894D-89484482AF06}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "squish", "squish\squish.vcproj", "{CE017322-01FC-4851-9C8B-64E9A8E26C38}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "squish", "squish\squish.vcproj", "{CE017322-01FC-4851-9C8B-64E9A8E26C38}"
|
||||||
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
|
{F143D180-D4C4-4037-B3DE-BE89A21C8D1D} = {F143D180-D4C4-4037-B3DE-BE89A21C8D1D}
|
||||||
|
{4046F392-A18B-4C66-9639-3EABFFF5D531} = {4046F392-A18B-4C66-9639-3EABFFF5D531}
|
||||||
|
{50C465FE-B308-42BC-894D-89484482AF06} = {50C465FE-B308-42BC-894D-89484482AF06}
|
||||||
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nvddsinfo", "nvddsinfo\nvddsinfo.vcproj", "{841B73C5-C679-4EEF-A50A-7D6106642B49}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nvddsinfo", "nvddsinfo\nvddsinfo.vcproj", "{841B73C5-C679-4EEF-A50A-7D6106642B49}"
|
||||||
ProjectSection(ProjectDependencies) = postProject
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
|
@ -864,6 +864,14 @@
|
|||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\src\nvtt\ClusterFit.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\src\nvtt\ClusterFit.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\src\nvtt\CompressionOptions.cpp"
|
RelativePath="..\..\..\src\nvtt\CompressionOptions.cpp"
|
||||||
>
|
>
|
||||||
@ -887,10 +895,138 @@
|
|||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\src\nvtt\CompressorDX11.cpp"
|
RelativePath="..\..\..\src\nvtt\CompressorDX11.cpp"
|
||||||
>
|
>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
ExcludedFromBuild="true"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Debug|x64"
|
||||||
|
ExcludedFromBuild="true"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Release|Win32"
|
||||||
|
ExcludedFromBuild="true"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Release|x64"
|
||||||
|
ExcludedFromBuild="true"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Debug (no cuda)|Win32"
|
||||||
|
ExcludedFromBuild="true"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Debug (no cuda)|x64"
|
||||||
|
ExcludedFromBuild="true"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Release (no cuda)|Win32"
|
||||||
|
ExcludedFromBuild="true"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Release (no cuda)|x64"
|
||||||
|
ExcludedFromBuild="true"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\src\nvtt\CompressorDX11.h"
|
RelativePath="..\..\..\src\nvtt\CompressorDX11.h"
|
||||||
>
|
>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
ExcludedFromBuild="true"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Debug|x64"
|
||||||
|
ExcludedFromBuild="true"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Release|Win32"
|
||||||
|
ExcludedFromBuild="true"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Release|x64"
|
||||||
|
ExcludedFromBuild="true"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Debug (no cuda)|Win32"
|
||||||
|
ExcludedFromBuild="true"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Debug (no cuda)|x64"
|
||||||
|
ExcludedFromBuild="true"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Release (no cuda)|Win32"
|
||||||
|
ExcludedFromBuild="true"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Release (no cuda)|x64"
|
||||||
|
ExcludedFromBuild="true"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\src\nvtt\CompressorDX9.cpp"
|
RelativePath="..\..\..\src\nvtt\CompressorDX9.cpp"
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include "nvmath/Box.h"
|
#include "nvmath/Box.h"
|
||||||
#include "nvcore/Utils.h" // swap
|
#include "nvcore/Utils.h" // swap
|
||||||
|
|
||||||
|
#include <string.h> // memcpy
|
||||||
|
|
||||||
using namespace nv;
|
using namespace nv;
|
||||||
|
|
||||||
@ -457,44 +458,176 @@ float ColorBlock::volume() const
|
|||||||
return bounds.volume();
|
return bounds.volume();
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
#include "FloatImage.h"
|
||||||
|
|
||||||
|
void ColorSet::setColors(const float * data, uint img_w, uint img_h, uint img_x, uint img_y)
|
||||||
void ColorSet::init(const Image * img, uint x, uint y)
|
|
||||||
{
|
{
|
||||||
w = min(4U, img->width() - x);
|
nvDebugCheck(img_x < img_w && img_y < img_h);
|
||||||
h = min(4U, img->height() - y);
|
|
||||||
|
w = min(4U, img_w - img_x);
|
||||||
|
h = min(4U, img_h - img_y);
|
||||||
nvDebugCheck(w != 0 && h != 0);
|
nvDebugCheck(w != 0 && h != 0);
|
||||||
|
|
||||||
// Blocks that are smaller than 4x4 are handled by repeating the pixels.
|
count = w * h;
|
||||||
// @@ 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.
|
|
||||||
|
|
||||||
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 x = 0; x < w; x++, i++)
|
||||||
|
|
||||||
for (uint e = 0; e < 4; e++)
|
|
||||||
{
|
{
|
||||||
const uint bx = e % w;
|
colors[i].x = r[x + img_x, y + img_y];
|
||||||
Color32 c = img->pixel(x+bx, y+by);
|
colors[i].y = g[x + img_x, y + img_y];
|
||||||
Vector4 & v = color(e, i);
|
colors[i].z = b[x + img_x, y + img_y];
|
||||||
v.x = c.r / 255.0f;
|
colors[i].w = a[x + img_x, y + img_y];
|
||||||
v.y = c.g / 255.0f;
|
|
||||||
v.z = c.b / 255.0f;
|
|
||||||
v.w = c.a / 255.0f;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
struct ColorSet
|
||||||
{
|
{
|
||||||
ColorSet() : w(4), h(4) {}
|
void setColors(const float * data, uint img_w, uint img_h, uint img_x, uint img_y);
|
||||||
ColorSet(uint w, uint h) : w(w), h(h) {}
|
|
||||||
|
|
||||||
void init(const Image * img, uint x, uint y);
|
void setAlphaWeights();
|
||||||
void init(const FloatImage * img, uint x, uint y);
|
void setUniformWeights();
|
||||||
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);
|
|
||||||
|
|
||||||
Vector4 color(uint x, uint y) const { nvDebugCheck(x < w && y < h); return colors[y * 4 + x]; }
|
void createMinimalSet(bool ignoreTransparent);
|
||||||
Vector4 & color(uint x, uint y) { nvDebugCheck(x < w && y < h); return colors[y * 4 + x]; }
|
void wrapIndices();
|
||||||
|
|
||||||
Vector4 color(uint i) const { 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
|
||||||
Vector4 & color(uint i) { nvDebugCheck(i < 16); return colors[i]; }
|
|
||||||
|
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];
|
Vector4 colors[16];
|
||||||
uint w, h;
|
float weights[16];
|
||||||
|
int remap[16];
|
||||||
};
|
};
|
||||||
|
|
||||||
} // nv namespace
|
} // nv namespace
|
||||||
|
@ -146,7 +146,7 @@ static Vector3 xyzToCieLab(Vector3::Arg c)
|
|||||||
// Normalized white point.
|
// Normalized white point.
|
||||||
const float Xn = 0.950456f;
|
const float Xn = 0.950456f;
|
||||||
const float Yn = 1.0f;
|
const float Yn = 1.0f;
|
||||||
const float Zn = 1.088754;
|
const float Zn = 1.088754f;
|
||||||
|
|
||||||
float Xr = c.x / Xn;
|
float Xr = c.x / Xn;
|
||||||
float Yr = c.y / Yn;
|
float Yr = c.y / Yn;
|
||||||
@ -159,6 +159,8 @@ static Vector3 xyzToCieLab(Vector3::Arg c)
|
|||||||
float L = 116 * fx - 16;
|
float L = 116 * fx - 16;
|
||||||
float a = 500 * (fx - fy);
|
float a = 500 * (fx - fy);
|
||||||
float b = 200 * (fy - fz);
|
float b = 200 * (fy - fz);
|
||||||
|
|
||||||
|
return Vector3(L, a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Vector3 rgbToCieLab(Vector3::Arg c)
|
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]));
|
Vector3 lab1 = rgbToCieLab(Vector3(r1[i], g1[i], b1[i]));
|
||||||
|
|
||||||
// @@ Measure Delta E.
|
// @@ Measure Delta E.
|
||||||
|
Vector3 delta = lab0 - lab1;
|
||||||
|
|
||||||
|
error += length(delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
return float(error / count);
|
return float(error / count);
|
||||||
|
@ -30,7 +30,7 @@ static inline Vector3 firstEigenVector_PowerMethod(const float *__restrict matri
|
|||||||
{
|
{
|
||||||
if (matrix[0] == 0 && matrix[3] == 0 && matrix[5] == 0)
|
if (matrix[0] == 0 && matrix[3] == 0 && matrix[5] == 0)
|
||||||
{
|
{
|
||||||
return Vector3(zero);
|
return Vector3(0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 v = estimatePrincipleComponent(matrix);
|
Vector3 v = estimatePrincipleComponent(matrix);
|
||||||
@ -53,7 +53,7 @@ static inline Vector3 firstEigenVector_PowerMethod(const float *__restrict matri
|
|||||||
|
|
||||||
Vector3 nv::Fit::computeCentroid(int n, const Vector3 *__restrict points)
|
Vector3 nv::Fit::computeCentroid(int n, const Vector3 *__restrict points)
|
||||||
{
|
{
|
||||||
Vector3 centroid(zero);
|
Vector3 centroid(0.0f);
|
||||||
|
|
||||||
for (int i = 0; i < n; i++)
|
for (int i = 0; i < n; i++)
|
||||||
{
|
{
|
||||||
@ -66,7 +66,7 @@ Vector3 nv::Fit::computeCentroid(int n, const Vector3 *__restrict points)
|
|||||||
|
|
||||||
Vector3 nv::Fit::computeCentroid(int n, const Vector3 *__restrict points, const float *__restrict weights, Vector3::Arg metric)
|
Vector3 nv::Fit::computeCentroid(int n, const Vector3 *__restrict points, const float *__restrict weights, Vector3::Arg metric)
|
||||||
{
|
{
|
||||||
Vector3 centroid(zero);
|
Vector3 centroid(0.0f );
|
||||||
float total = 0.0f;
|
float total = 0.0f;
|
||||||
|
|
||||||
for (int i = 0; i < n; i++)
|
for (int i = 0; i < n; i++)
|
||||||
@ -210,7 +210,7 @@ int nv::Fit::compute4Means(int n, const Vector3 *__restrict points, const float
|
|||||||
// Now we have to iteratively refine the clusters.
|
// Now we have to iteratively refine the clusters.
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
Vector3 newCluster[4] = { Vector3(zero), Vector3(zero), Vector3(zero), Vector3(zero) };
|
Vector3 newCluster[4] = { Vector3(0.0f), Vector3(0.0f), Vector3(0.0f), Vector3(0.0f) };
|
||||||
float total[4] = {0, 0, 0, 0};
|
float total[4] = {0, 0, 0, 0};
|
||||||
|
|
||||||
for (int i = 0; i < n; ++i)
|
for (int i = 0; i < n; ++i)
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
|
|
||||||
namespace nv
|
namespace nv
|
||||||
{
|
{
|
||||||
|
enum zero_t { zero };
|
||||||
|
enum identity_t { identity };
|
||||||
|
|
||||||
class NVMATH_CLASS Matrix3
|
class NVMATH_CLASS Matrix3
|
||||||
{
|
{
|
||||||
|
@ -26,6 +26,8 @@
|
|||||||
#ifndef NV_SIMD_VECTOR_SSE_H
|
#ifndef NV_SIMD_VECTOR_SSE_H
|
||||||
#define NV_SIMD_VECTOR_SSE_H
|
#define NV_SIMD_VECTOR_SSE_H
|
||||||
|
|
||||||
|
#include "nvcore/Memory.h"
|
||||||
|
|
||||||
#include <xmmintrin.h>
|
#include <xmmintrin.h>
|
||||||
#if (NV_USE_SSE > 1)
|
#if (NV_USE_SSE > 1)
|
||||||
#include <emmintrin.h>
|
#include <emmintrin.h>
|
||||||
@ -35,6 +37,7 @@ namespace nv {
|
|||||||
|
|
||||||
class SimdVector
|
class SimdVector
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
__m128 vec;
|
__m128 vec;
|
||||||
|
|
||||||
typedef SimdVector const& Arg;
|
typedef SimdVector const& Arg;
|
||||||
@ -42,15 +45,13 @@ namespace nv {
|
|||||||
SimdVector() {}
|
SimdVector() {}
|
||||||
explicit SimdVector(float f) : vec(_mm_set1_ps(f)) {}
|
explicit SimdVector(float f) : vec(_mm_set1_ps(f)) {}
|
||||||
explicit SimdVector(__m128 v) : vec(v) {}
|
explicit SimdVector(__m128 v) : vec(v) {}
|
||||||
SimdVector(const SimdVector & arg) : vec(arg.vec) {}
|
|
||||||
|
|
||||||
SimdVector & operator=(const SimdVector & arg)
|
explicit SimdVector(Vector4::Arg v)
|
||||||
{
|
{
|
||||||
vec = arg.vec;
|
vec = _mm_load_ps( v.component );
|
||||||
return *this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SimdVector(const float * v)
|
explicit SimdVector(const float * v)
|
||||||
{
|
{
|
||||||
vec = _mm_load_ps( v );
|
vec = _mm_load_ps( v );
|
||||||
}
|
}
|
||||||
@ -60,6 +61,16 @@ namespace nv {
|
|||||||
vec = _mm_setr_ps( x, y, z, w );
|
vec = _mm_setr_ps( x, y, z, w );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SimdVector(const SimdVector & arg) : vec(arg.vec) {}
|
||||||
|
|
||||||
|
SimdVector & operator=(const SimdVector & arg)
|
||||||
|
{
|
||||||
|
vec = arg.vec;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
float toFloat() const
|
float toFloat() const
|
||||||
{
|
{
|
||||||
NV_ALIGN_16 float f;
|
NV_ALIGN_16 float f;
|
||||||
@ -77,7 +88,7 @@ namespace nv {
|
|||||||
Vector4 toVector4() const
|
Vector4 toVector4() const
|
||||||
{
|
{
|
||||||
NV_ALIGN_16 float c[4];
|
NV_ALIGN_16 float c[4];
|
||||||
_mm_store_ps( v.components, vec );
|
_mm_store_ps( c, vec );
|
||||||
return Vector4( c[0], c[1], c[2], c[3] );
|
return Vector4( c[0], c[1], c[2], c[3] );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,34 +119,34 @@ namespace nv {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
SimdVector operator+( SimdVector::Arg left, SimdVector::Arg right )
|
inline SimdVector operator+( SimdVector::Arg left, SimdVector::Arg right )
|
||||||
{
|
{
|
||||||
return SimdVector( _mm_add_ps( left.vec, right.vec ) );
|
return SimdVector( _mm_add_ps( left.vec, right.vec ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
SimdVector operator-( SimdVector::Arg left, SimdVector::Arg right )
|
inline SimdVector operator-( SimdVector::Arg left, SimdVector::Arg right )
|
||||||
{
|
{
|
||||||
return SimdVector( _mm_sub_ps( left.vec, right.vec ) );
|
return SimdVector( _mm_sub_ps( left.vec, right.vec ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
SimdVector operator*( SimdVector::Arg left, SimdVector::Arg right )
|
inline SimdVector operator*( SimdVector::Arg left, SimdVector::Arg right )
|
||||||
{
|
{
|
||||||
return SimdVector( _mm_mul_ps( left.vec, right.vec ) );
|
return SimdVector( _mm_mul_ps( left.vec, right.vec ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a*b + c
|
// Returns a*b + c
|
||||||
SimdVector multiplyAdd( SimdVector::Arg a, SimdVector::Arg b, SimdVector::Arg c )
|
inline SimdVector multiplyAdd( SimdVector::Arg a, SimdVector::Arg b, SimdVector::Arg c )
|
||||||
{
|
{
|
||||||
return SimdVector( _mm_add_ps( _mm_mul_ps( a.vec, b.vec ), c.vec ) );
|
return SimdVector( _mm_add_ps( _mm_mul_ps( a.vec, b.vec ), c.vec ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns -( a*b - c )
|
// Returns -( a*b - c )
|
||||||
SimdVector negativeMultiplySubtract( SimdVector::Arg a, SimdVector::Arg b, SimdVector::Arg c )
|
inline SimdVector negativeMultiplySubtract( SimdVector::Arg a, SimdVector::Arg b, SimdVector::Arg c )
|
||||||
{
|
{
|
||||||
return SimdVector( _mm_sub_ps( c.vec, _mm_mul_ps( a.vec, b.vec ) ) );
|
return SimdVector( _mm_sub_ps( c.vec, _mm_mul_ps( a.vec, b.vec ) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
SimdVector reciprocal( SimdVector::Arg v )
|
inline SimdVector reciprocal( SimdVector::Arg v )
|
||||||
{
|
{
|
||||||
// get the reciprocal estimate
|
// get the reciprocal estimate
|
||||||
__m128 estimate = _mm_rcp_ps( v.vec );
|
__m128 estimate = _mm_rcp_ps( v.vec );
|
||||||
@ -145,17 +156,17 @@ namespace nv {
|
|||||||
return SimdVector( _mm_add_ps( _mm_mul_ps( diff, estimate ), estimate ) );
|
return SimdVector( _mm_add_ps( _mm_mul_ps( diff, estimate ), estimate ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
SimdVector min( SimdVector::Arg left, SimdVector::Arg right )
|
inline SimdVector min( SimdVector::Arg left, SimdVector::Arg right )
|
||||||
{
|
{
|
||||||
return SimdVector( _mm_min_ps( left.vec, right.vec ) );
|
return SimdVector( _mm_min_ps( left.vec, right.vec ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
SimdVector max( SimdVector::Arg left, SimdVector::Arg right )
|
inline SimdVector max( SimdVector::Arg left, SimdVector::Arg right )
|
||||||
{
|
{
|
||||||
return SimdVector( _mm_max_ps( left.vec, right.vec ) );
|
return SimdVector( _mm_max_ps( left.vec, right.vec ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
SimdVector truncate( SimdVector::Arg v )
|
inline SimdVector truncate( SimdVector::Arg v )
|
||||||
{
|
{
|
||||||
#if (NV_USE_SSE == 1)
|
#if (NV_USE_SSE == 1)
|
||||||
// convert to ints
|
// convert to ints
|
||||||
@ -176,12 +187,12 @@ namespace nv {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SimdVector compareEqual( SimdVector::Arg left, SimdVector::Arg right )
|
inline SimdVector compareEqual( SimdVector::Arg left, SimdVector::Arg right )
|
||||||
{
|
{
|
||||||
return SimdVector( _mm_cmpeq_ps( left.vec, right.vec ) );
|
return SimdVector( _mm_cmpeq_ps( left.vec, right.vec ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
SimdVector select( SimdVector::Arg off, SimdVector::Arg on, SimdVector::Arg bits )
|
inline SimdVector select( SimdVector::Arg off, SimdVector::Arg on, SimdVector::Arg bits )
|
||||||
{
|
{
|
||||||
__m128 a = _mm_andnot_ps( bits.vec, off.vec );
|
__m128 a = _mm_andnot_ps( bits.vec, off.vec );
|
||||||
__m128 b = _mm_and_ps( bits.vec, on.vec );
|
__m128 b = _mm_and_ps( bits.vec, on.vec );
|
||||||
@ -189,7 +200,7 @@ namespace nv {
|
|||||||
return SimdVector( _mm_or_ps( a, b ) );
|
return SimdVector( _mm_or_ps( a, b ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool compareAnyLessThan( SimdVector::Arg left, SimdVector::Arg right )
|
inline bool compareAnyLessThan( SimdVector::Arg left, SimdVector::Arg right )
|
||||||
{
|
{
|
||||||
__m128 bits = _mm_cmplt_ps( left.vec, right.vec );
|
__m128 bits = _mm_cmplt_ps( left.vec, right.vec );
|
||||||
int value = _mm_movemask_ps( bits );
|
int value = _mm_movemask_ps( bits );
|
||||||
|
@ -10,9 +10,6 @@
|
|||||||
namespace nv
|
namespace nv
|
||||||
{
|
{
|
||||||
|
|
||||||
enum zero_t { zero };
|
|
||||||
enum identity_t { identity };
|
|
||||||
|
|
||||||
// I should probably use templates.
|
// I should probably use templates.
|
||||||
typedef float scalar;
|
typedef float scalar;
|
||||||
|
|
||||||
@ -22,7 +19,6 @@ namespace nv
|
|||||||
typedef Vector2 const & Arg;
|
typedef Vector2 const & Arg;
|
||||||
|
|
||||||
Vector2();
|
Vector2();
|
||||||
explicit Vector2(zero_t);
|
|
||||||
explicit Vector2(scalar f);
|
explicit Vector2(scalar f);
|
||||||
Vector2(scalar x, scalar y);
|
Vector2(scalar x, scalar y);
|
||||||
Vector2(Vector2::Arg v);
|
Vector2(Vector2::Arg v);
|
||||||
@ -57,7 +53,7 @@ namespace nv
|
|||||||
typedef Vector3 const & Arg;
|
typedef Vector3 const & Arg;
|
||||||
|
|
||||||
Vector3();
|
Vector3();
|
||||||
explicit Vector3(zero_t);
|
explicit Vector3(scalar x);
|
||||||
Vector3(scalar x, scalar y, scalar z);
|
Vector3(scalar x, scalar y, scalar z);
|
||||||
Vector3(Vector2::Arg v, scalar z);
|
Vector3(Vector2::Arg v, scalar z);
|
||||||
Vector3(Vector3::Arg v);
|
Vector3(Vector3::Arg v);
|
||||||
@ -99,7 +95,7 @@ namespace nv
|
|||||||
typedef Vector4 const & Arg;
|
typedef Vector4 const & Arg;
|
||||||
|
|
||||||
Vector4();
|
Vector4();
|
||||||
explicit Vector4(zero_t);
|
explicit Vector4(scalar x);
|
||||||
Vector4(scalar x, scalar y, scalar z, scalar w);
|
Vector4(scalar x, scalar y, scalar z, scalar w);
|
||||||
Vector4(Vector2::Arg v, scalar z, scalar w);
|
Vector4(Vector2::Arg v, scalar z, scalar w);
|
||||||
Vector4(Vector3::Arg v, scalar w);
|
Vector4(Vector3::Arg v, scalar w);
|
||||||
@ -136,7 +132,6 @@ namespace nv
|
|||||||
// Vector2
|
// Vector2
|
||||||
|
|
||||||
inline Vector2::Vector2() {}
|
inline Vector2::Vector2() {}
|
||||||
inline Vector2::Vector2(zero_t) : x(0.0f), y(0.0f) {}
|
|
||||||
inline Vector2::Vector2(scalar f) : x(f), y(f) {}
|
inline Vector2::Vector2(scalar f) : x(f), y(f) {}
|
||||||
inline Vector2::Vector2(scalar x, scalar y) : x(x), y(y) {}
|
inline Vector2::Vector2(scalar x, scalar y) : x(x), y(y) {}
|
||||||
inline Vector2::Vector2(Vector2::Arg v) : x(v.x), y(v.y) {}
|
inline Vector2::Vector2(Vector2::Arg v) : x(v.x), y(v.y) {}
|
||||||
@ -201,7 +196,7 @@ namespace nv
|
|||||||
// Vector3
|
// Vector3
|
||||||
|
|
||||||
inline Vector3::Vector3() {}
|
inline Vector3::Vector3() {}
|
||||||
inline Vector3::Vector3(zero_t) : x(0.0f), y(0.0f), z(0.0f) {}
|
inline Vector3::Vector3(scalar f) : x(f), y(f), z(f) {}
|
||||||
inline Vector3::Vector3(scalar x, scalar y, scalar z) : x(x), y(y), z(z) {}
|
inline Vector3::Vector3(scalar x, scalar y, scalar z) : x(x), y(y), z(z) {}
|
||||||
inline Vector3::Vector3(Vector2::Arg v, scalar z) : x(v.x), y(v.y), z(z) {}
|
inline Vector3::Vector3(Vector2::Arg v, scalar z) : x(v.x), y(v.y), z(z) {}
|
||||||
inline Vector3::Vector3(Vector3::Arg v) : x(v.x), y(v.y), z(v.z) {}
|
inline Vector3::Vector3(Vector3::Arg v) : x(v.x), y(v.y), z(v.z) {}
|
||||||
@ -286,7 +281,7 @@ namespace nv
|
|||||||
// Vector4
|
// Vector4
|
||||||
|
|
||||||
inline Vector4::Vector4() {}
|
inline Vector4::Vector4() {}
|
||||||
inline Vector4::Vector4(zero_t) : x(0.0f), y(0.0f), z(0.0f), w(0.0f) {}
|
inline Vector4::Vector4(scalar f) : x(f), y(f), z(f), w(f) {}
|
||||||
inline Vector4::Vector4(scalar x, scalar y, scalar z, scalar w) : x(x), y(y), z(z), w(w) {}
|
inline Vector4::Vector4(scalar x, scalar y, scalar z, scalar w) : x(x), y(y), z(z), w(w) {}
|
||||||
inline Vector4::Vector4(Vector2::Arg v, scalar z, scalar w) : x(v.x), y(v.y), z(z), w(w) {}
|
inline Vector4::Vector4(Vector2::Arg v, scalar z, scalar w) : x(v.x), y(v.y), z(z), w(w) {}
|
||||||
inline Vector4::Vector4(Vector3::Arg v, scalar w) : x(v.x), y(v.y), z(v.z), w(w) {}
|
inline Vector4::Vector4(Vector3::Arg v, scalar w) : x(v.x), y(v.y), z(v.z), w(w) {}
|
||||||
@ -640,6 +635,15 @@ namespace nv
|
|||||||
return isFinite(v.x) && isFinite(v.y) && isFinite(v.z);
|
return isFinite(v.x) && isFinite(v.y) && isFinite(v.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline Vector3 floor(Vector3::Arg v)
|
||||||
|
{
|
||||||
|
return Vector3(floorf(v.x), floorf(v.y), floorf(v.z));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Vector3 ceil(Vector3::Arg v)
|
||||||
|
{
|
||||||
|
return Vector3(ceilf(v.x), ceilf(v.y), ceilf(v.z));
|
||||||
|
}
|
||||||
|
|
||||||
// Vector4
|
// Vector4
|
||||||
|
|
||||||
|
@ -1,62 +1,62 @@
|
|||||||
// Copyright (c) 2009-2011 Ignacio Castano <castano@gmail.com>
|
// Copyright (c) 2009-2011 Ignacio Castano <castano@gmail.com>
|
||||||
// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano <icastano@nvidia.com>
|
// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano <icastano@nvidia.com>
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person
|
// Permission is hereby granted, free of charge, to any person
|
||||||
// obtaining a copy of this software and associated documentation
|
// obtaining a copy of this software and associated documentation
|
||||||
// files (the "Software"), to deal in the Software without
|
// files (the "Software"), to deal in the Software without
|
||||||
// restriction, including without limitation the rights to use,
|
// restriction, including without limitation the rights to use,
|
||||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
// copies of the Software, and to permit persons to whom the
|
// copies of the Software, and to permit persons to whom the
|
||||||
// Software is furnished to do so, subject to the following
|
// Software is furnished to do so, subject to the following
|
||||||
// conditions:
|
// conditions:
|
||||||
//
|
//
|
||||||
// The above copyright notice and this permission notice shall be
|
// The above copyright notice and this permission notice shall be
|
||||||
// included in all copies or substantial portions of the Software.
|
// included in all copies or substantial portions of the Software.
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
// OTHER DEALINGS IN THE SOFTWARE.
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
#include "CompressorDX11.h"
|
#include "CompressorDX11.h"
|
||||||
|
|
||||||
#include "nvtt.h"
|
#include "nvtt.h"
|
||||||
#include "CompressionOptions.h"
|
#include "CompressionOptions.h"
|
||||||
|
|
||||||
#include "bc6h/zoh.h"
|
#include "bc6h/zoh.h"
|
||||||
#include "bc6h/utils.h"
|
#include "bc6h/utils.h"
|
||||||
|
|
||||||
//#include "bc7/avpcl.h"
|
//#include "bc7/avpcl.h"
|
||||||
//#include "bc7/utils.h"
|
//#include "bc7/utils.h"
|
||||||
|
|
||||||
using namespace nv;
|
using namespace nv;
|
||||||
using namespace nvtt;
|
using namespace nvtt;
|
||||||
|
|
||||||
|
|
||||||
void CompressorBC6::compressBlock(Tile & tile, AlphaMode alphaMode, const CompressionOptions::Private & compressionOptions, void * output)
|
void CompressorBC6::compressBlock(Tile & tile, AlphaMode alphaMode, const CompressionOptions::Private & compressionOptions, void * output)
|
||||||
{
|
{
|
||||||
NV_UNUSED(alphaMode); // ZOH does not support alpha.
|
NV_UNUSED(alphaMode); // ZOH does not support alpha.
|
||||||
|
|
||||||
if (compressionOptions.pixelType == PixelType_UnsignedFloat ||
|
if (compressionOptions.pixelType == PixelType_UnsignedFloat ||
|
||||||
compressionOptions.pixelType == PixelType_UnsignedNorm ||
|
compressionOptions.pixelType == PixelType_UnsignedNorm ||
|
||||||
compressionOptions.pixelType == PixelType_UnsignedInt)
|
compressionOptions.pixelType == PixelType_UnsignedInt)
|
||||||
{
|
{
|
||||||
Utils::FORMAT = UNSIGNED_F16; // @@ Do not use globals.
|
Utils::FORMAT = UNSIGNED_F16; // @@ Do not use globals.
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Utils::FORMAT = SIGNED_F16;
|
Utils::FORMAT = SIGNED_F16;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZOH::compress(tile, (char *)output);
|
ZOH::compress(tile, (char *)output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CompressorBC7::compressBlock(Tile & tile, AlphaMode alphaMode, const CompressionOptions::Private & compressionOptions, void * output)
|
void CompressorBC7::compressBlock(Tile & tile, AlphaMode alphaMode, const CompressionOptions::Private & compressionOptions, void * output)
|
||||||
{
|
{
|
||||||
// @@ TODO
|
// @@ TODO
|
||||||
}
|
}
|
||||||
|
@ -28,15 +28,15 @@
|
|||||||
|
|
||||||
namespace nv
|
namespace nv
|
||||||
{
|
{
|
||||||
struct CompressorBC6 : public TileCompressor
|
struct CompressorBC6 : public ColorSetCompressor
|
||||||
{
|
{
|
||||||
virtual void compressBlock(Tile & tile, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output);
|
virtual void compressBlock(ColorSet & set, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output);
|
||||||
virtual uint blockSize() const { return 16; }
|
virtual uint blockSize() const { return 16; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CompressorBC7 : public TileCompressor
|
struct CompressorBC7 : public ColorSetCompressor
|
||||||
{
|
{
|
||||||
virtual void compressBlock(Tile & tile, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output);
|
virtual void compressBlock(ColorSet & set, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output);
|
||||||
virtual uint blockSize() const { return 16; }
|
virtual uint blockSize() const { return 16; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include "OptimalCompressDXT.h"
|
#include "OptimalCompressDXT.h"
|
||||||
#include "CompressionOptions.h"
|
#include "CompressionOptions.h"
|
||||||
#include "OutputOptions.h"
|
#include "OutputOptions.h"
|
||||||
|
#include "ClusterFit.h"
|
||||||
|
|
||||||
// squish
|
// squish
|
||||||
#include "squish/colourset.h"
|
#include "squish/colourset.h"
|
||||||
@ -109,30 +110,36 @@ void FastCompressorDXT5n::compressBlock(ColorBlock & rgba, nvtt::AlphaMode alpha
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline static Vector3 vec(nvsquish::Vec3 v) { return Vector3(v.X(), v.Y(), v.Z()); }
|
void NormalCompressorDXT1::compressBlock(ColorSet & set, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output)
|
||||||
|
|
||||||
void NormalCompressorDXT1::compressBlock(ColorBlock & rgba, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output)
|
|
||||||
{
|
{
|
||||||
nvsquish::WeightedClusterFit fit;
|
set.setUniformWeights();
|
||||||
fit.SetMetric(compressionOptions.colorWeight.x, compressionOptions.colorWeight.y, compressionOptions.colorWeight.z);
|
set.createMinimalSet(false);
|
||||||
|
|
||||||
|
ClusterFit fit;
|
||||||
|
fit.setMetric(compressionOptions.colorWeight);
|
||||||
|
|
||||||
BlockDXT1 * block = new(output) BlockDXT1;
|
BlockDXT1 * block = new(output) BlockDXT1;
|
||||||
if (rgba.isSingleColor())
|
|
||||||
|
if (set.isSingleColor(true))
|
||||||
{
|
{
|
||||||
OptimalCompress::compressDXT1(rgba.color(0), block);
|
Color32 c;
|
||||||
|
c.r = uint8(clamp(set.colors[0].x, 0.0f, 1.0f) * 255);
|
||||||
|
c.g = uint8(clamp(set.colors[0].y, 0.0f, 1.0f) * 255);
|
||||||
|
c.b = uint8(clamp(set.colors[0].z, 0.0f, 1.0f) * 255);
|
||||||
|
c.a = 255;
|
||||||
|
OptimalCompress::compressDXT1(c, block);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
nvsquish::ColourSet colours((uint8 *)rgba.colors(), 0);
|
fit.setColourSet(&set);
|
||||||
fit.SetColourSet(&colours, nvsquish::kDxt1);
|
|
||||||
|
|
||||||
nvsquish::Vec3 start, end;
|
Vector3 start, end;
|
||||||
|
|
||||||
fit.Compress4(&start, &end);
|
fit.compress4(&start, &end);
|
||||||
QuickCompress::outputBlock4(rgba, vec(start), vec(end), block);
|
QuickCompress::outputBlock4(set, start, end, block);
|
||||||
|
|
||||||
if (fit.Compress3(&start, &end)) {
|
if (fit.compress3(&start, &end)) {
|
||||||
QuickCompress::outputBlock3(rgba, vec(start), vec(end), block);
|
QuickCompress::outputBlock3(set, start, end, block);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -140,8 +147,6 @@ void NormalCompressorDXT1::compressBlock(ColorBlock & rgba, nvtt::AlphaMode alph
|
|||||||
|
|
||||||
void NormalCompressorDXT1a::compressBlock(ColorBlock & rgba, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output)
|
void NormalCompressorDXT1a::compressBlock(ColorBlock & rgba, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output)
|
||||||
{
|
{
|
||||||
#pragma NV_MESSAGE("NormalCompressorDXT1a - Not implemented!")
|
|
||||||
/*
|
|
||||||
uint alphaMask = 0;
|
uint alphaMask = 0;
|
||||||
for (uint i = 0; i < 16; i++)
|
for (uint i = 0; i < 16; i++)
|
||||||
{
|
{
|
||||||
@ -168,14 +173,11 @@ void NormalCompressorDXT1a::compressBlock(ColorBlock & rgba, nvtt::AlphaMode alp
|
|||||||
|
|
||||||
fit.Compress(output);
|
fit.Compress(output);
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void NormalCompressorDXT3::compressBlock(ColorBlock & rgba, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output)
|
void NormalCompressorDXT3::compressBlock(ColorBlock & rgba, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output)
|
||||||
{
|
{
|
||||||
#pragma NV_MESSAGE("NormalCompressorDXT1a - Not implemented!")
|
|
||||||
/*
|
|
||||||
BlockDXT3 * block = new(output) BlockDXT3;
|
BlockDXT3 * block = new(output) BlockDXT3;
|
||||||
|
|
||||||
// Compress explicit alpha.
|
// Compress explicit alpha.
|
||||||
@ -198,14 +200,11 @@ void NormalCompressorDXT3::compressBlock(ColorBlock & rgba, nvtt::AlphaMode alph
|
|||||||
fit.SetColourSet(&colours, 0);
|
fit.SetColourSet(&colours, 0);
|
||||||
fit.Compress(&block->color);
|
fit.Compress(&block->color);
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void NormalCompressorDXT5::compressBlock(ColorBlock & rgba, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output)
|
void NormalCompressorDXT5::compressBlock(ColorBlock & rgba, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output)
|
||||||
{
|
{
|
||||||
#pragma NV_MESSAGE("NormalCompressorDXT1a - Not implemented!")
|
|
||||||
/*
|
|
||||||
BlockDXT5 * block = new(output) BlockDXT5;
|
BlockDXT5 * block = new(output) BlockDXT5;
|
||||||
|
|
||||||
// Compress alpha.
|
// Compress alpha.
|
||||||
@ -235,14 +234,11 @@ void NormalCompressorDXT5::compressBlock(ColorBlock & rgba, nvtt::AlphaMode alph
|
|||||||
fit.SetColourSet(&colours, 0);
|
fit.SetColourSet(&colours, 0);
|
||||||
fit.Compress(&block->color);
|
fit.Compress(&block->color);
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void NormalCompressorDXT5n::compressBlock(ColorBlock & rgba, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output)
|
void NormalCompressorDXT5n::compressBlock(ColorBlock & rgba, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output)
|
||||||
{
|
{
|
||||||
#pragma NV_MESSAGE("NormalCompressorDXT1a - Not implemented!")
|
|
||||||
/*
|
|
||||||
BlockDXT5 * block = new(output) BlockDXT5;
|
BlockDXT5 * block = new(output) BlockDXT5;
|
||||||
|
|
||||||
// Compress Y.
|
// Compress Y.
|
||||||
@ -284,7 +280,6 @@ void NormalCompressorDXT5n::compressBlock(ColorBlock & rgba, nvtt::AlphaMode alp
|
|||||||
{
|
{
|
||||||
QuickCompress::compressDXT5A(rgba, &block->alpha);
|
QuickCompress::compressDXT5A(rgba, &block->alpha);
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -64,9 +64,9 @@ namespace nv
|
|||||||
|
|
||||||
|
|
||||||
// Normal CPU compressors.
|
// Normal CPU compressors.
|
||||||
struct NormalCompressorDXT1 : public FixedBlockCompressor
|
struct NormalCompressorDXT1 : public ColorSetCompressor
|
||||||
{
|
{
|
||||||
virtual void compressBlock(ColorBlock & rgba, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output);
|
virtual void compressBlock(ColorSet & set, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output);
|
||||||
virtual uint blockSize() const { return 8; }
|
virtual uint blockSize() const { return 8; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -111,33 +111,33 @@ void FixedBlockCompressor::compress(nvtt::AlphaMode alphaMode, uint w, uint h, c
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#include "bc6h/tile.h"
|
//#include "bc6h/tile.h"
|
||||||
|
|
||||||
void TileCompressor::compress(AlphaMode alphaMode, uint w, uint h, const float * data, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions)
|
void ColorSetCompressor::compress(AlphaMode alphaMode, uint w, uint h, const float * data, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions)
|
||||||
{
|
{
|
||||||
const uint bs = blockSize();
|
const uint bs = blockSize();
|
||||||
const uint bw = (w + 3) / 4;
|
const uint bw = (w + 3) / 4;
|
||||||
const uint bh = (h + 3) / 4;
|
const uint bh = (h + 3) / 4;
|
||||||
|
|
||||||
bool singleThreaded = true;
|
//bool singleThreaded = true;
|
||||||
|
//if (singleThreaded)
|
||||||
if (singleThreaded)
|
|
||||||
{
|
{
|
||||||
nvDebugCheck(bs <= 16);
|
uint8 * mem = malloc<uint8>(bs * bw);
|
||||||
uint8 mem[16]; // @@ Output one row at a time!
|
uint8 * ptr = mem;
|
||||||
|
|
||||||
|
ColorSet set;
|
||||||
|
|
||||||
for (uint y = 0; y < h; y += 4) {
|
for (uint y = 0; y < h; y += 4) {
|
||||||
for (uint x = 0; x < w; x += 4) {
|
for (uint x = 0; x < w; x += 4, ptr += bs) {
|
||||||
|
set.setColors(data, w, h, x, y);
|
||||||
|
compressBlock(set, alphaMode, compressionOptions, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
Tile tile;
|
if (outputOptions.outputHandler != NULL) {
|
||||||
//tile.init((const float *)data, w, h, x, y);
|
outputOptions.outputHandler->writeData(mem, bs * bw);
|
||||||
|
|
||||||
compressBlock(tile, alphaMode, compressionOptions, mem);
|
|
||||||
|
|
||||||
if (outputOptions.outputHandler != NULL) {
|
|
||||||
outputOptions.outputHandler->writeData(mem, bs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(mem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,26 +27,26 @@
|
|||||||
|
|
||||||
#include "Compressor.h"
|
#include "Compressor.h"
|
||||||
|
|
||||||
class Tile;
|
|
||||||
|
|
||||||
namespace nv
|
namespace nv
|
||||||
{
|
{
|
||||||
|
struct ColorSet;
|
||||||
struct ColorBlock;
|
struct ColorBlock;
|
||||||
|
|
||||||
struct FixedBlockCompressor : public CompressorInterface
|
struct FixedBlockCompressor : public CompressorInterface
|
||||||
{
|
{
|
||||||
virtual void compress(nvtt::AlphaMode alphaMode, uint w, uint h, const float * rgba, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions);
|
virtual void compress(nvtt::AlphaMode alphaMode, uint w, uint h, const float * rgba, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions);
|
||||||
|
|
||||||
virtual void compressBlock(ColorBlock & rgba, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output) = 0;
|
virtual void compressBlock(ColorBlock & rgba, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output) = 0;
|
||||||
virtual uint blockSize() const = 0;
|
virtual uint blockSize() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TileCompressor : public CompressorInterface
|
struct ColorSetCompressor : public CompressorInterface
|
||||||
{
|
{
|
||||||
virtual void compress(nvtt::AlphaMode alphaMode, uint w, uint h, const float * rgba, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions);
|
virtual void compress(nvtt::AlphaMode alphaMode, uint w, uint h, const float * rgba, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions);
|
||||||
|
|
||||||
virtual void compressBlock(Tile & tile, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output) = 0;
|
virtual void compressBlock(ColorSet & set, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output) = 0;
|
||||||
virtual uint blockSize() const = 0;
|
virtual uint blockSize() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // nv namespace
|
} // nv namespace
|
||||||
|
@ -83,7 +83,7 @@ inline static void selectDiagonal(const Vector3 * block, uint num, Vector3 * res
|
|||||||
{
|
{
|
||||||
Vector3 center = (*maxColor + *minColor) * 0.5;
|
Vector3 center = (*maxColor + *minColor) * 0.5;
|
||||||
|
|
||||||
Vector2 covariance = Vector2(zero);
|
Vector2 covariance = Vector2(0.0f);
|
||||||
for (uint i = 0; i < num; i++)
|
for (uint i = 0; i < num; i++)
|
||||||
{
|
{
|
||||||
Vector3 t = block[i] - center;
|
Vector3 t = block[i] - center;
|
||||||
@ -166,6 +166,40 @@ inline static uint computeIndices4(const Vector3 block[16], Vector3::Arg maxColo
|
|||||||
return indices;
|
return indices;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline static uint computeIndices4(const ColorSet & set, Vector3::Arg maxColor, Vector3::Arg minColor)
|
||||||
|
{
|
||||||
|
Vector3 palette[4];
|
||||||
|
palette[0] = maxColor;
|
||||||
|
palette[1] = minColor;
|
||||||
|
palette[2] = lerp(palette[0], palette[1], 1.0f / 3.0f);
|
||||||
|
palette[3] = lerp(palette[0], palette[1], 2.0f / 3.0f);
|
||||||
|
|
||||||
|
uint indices = 0;
|
||||||
|
for(int i = 0; i < 16; i++)
|
||||||
|
{
|
||||||
|
Vector3 color = set.color(i).xyz();
|
||||||
|
|
||||||
|
float d0 = colorDistance(palette[0], color);
|
||||||
|
float d1 = colorDistance(palette[1], color);
|
||||||
|
float d2 = colorDistance(palette[2], color);
|
||||||
|
float d3 = colorDistance(palette[3], 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;
|
||||||
|
}
|
||||||
|
|
||||||
inline static float evaluatePaletteError4(const Vector3 block[16], Vector3::Arg maxColor, Vector3::Arg minColor)
|
inline static float evaluatePaletteError4(const Vector3 block[16], Vector3::Arg maxColor, Vector3::Arg minColor)
|
||||||
{
|
{
|
||||||
Vector3 palette[4];
|
Vector3 palette[4];
|
||||||
@ -188,7 +222,7 @@ inline static float evaluatePaletteError4(const Vector3 block[16], Vector3::Arg
|
|||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static uint computeIndices3(const ColorBlock & rgba, Vector3::Arg maxColor, Vector3::Arg minColor)
|
inline static uint computeIndices3(const ColorSet & set, Vector3::Arg maxColor, Vector3::Arg minColor)
|
||||||
{
|
{
|
||||||
Vector3 palette[4];
|
Vector3 palette[4];
|
||||||
palette[0] = minColor;
|
palette[0] = minColor;
|
||||||
@ -198,15 +232,15 @@ inline static uint computeIndices3(const ColorBlock & rgba, Vector3::Arg maxColo
|
|||||||
uint indices = 0;
|
uint indices = 0;
|
||||||
for(int i = 0; i < 16; i++)
|
for(int i = 0; i < 16; i++)
|
||||||
{
|
{
|
||||||
Color32 c = rgba.color(i);
|
Vector3 color = set.color(i).xyz();
|
||||||
Vector3 color = Vector3(c.r, c.g, c.b);
|
float alpha = set.color(i).w;
|
||||||
|
|
||||||
float d0 = colorDistance(palette[0], color);
|
float d0 = colorDistance(palette[0], color);
|
||||||
float d1 = colorDistance(palette[1], color);
|
float d1 = colorDistance(palette[1], color);
|
||||||
float d2 = colorDistance(palette[2], color);
|
float d2 = colorDistance(palette[2], color);
|
||||||
|
|
||||||
uint index;
|
uint index;
|
||||||
if (c.a < 128) index = 3;
|
if (alpha == 0) index = 3;
|
||||||
else if (d0 < d1 && d0 < d2) index = 0;
|
else if (d0 < d1 && d0 < d2) index = 0;
|
||||||
else if (d1 < d2) index = 1;
|
else if (d1 < d2) index = 1;
|
||||||
else index = 2;
|
else index = 2;
|
||||||
@ -250,8 +284,8 @@ 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;
|
||||||
float alphabeta_sum = 0.0f;
|
float alphabeta_sum = 0.0f;
|
||||||
Vector3 alphax_sum(zero);
|
Vector3 alphax_sum(0.0f);
|
||||||
Vector3 betax_sum(zero);
|
Vector3 betax_sum(0.0f);
|
||||||
|
|
||||||
for( int i = 0; i < 16; ++i )
|
for( int i = 0; i < 16; ++i )
|
||||||
{
|
{
|
||||||
@ -298,8 +332,8 @@ static void optimizeEndPoints3(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;
|
||||||
float alphabeta_sum = 0.0f;
|
float alphabeta_sum = 0.0f;
|
||||||
Vector3 alphax_sum(zero);
|
Vector3 alphax_sum(0.0f);
|
||||||
Vector3 betax_sum(zero);
|
Vector3 betax_sum(0.0f);
|
||||||
|
|
||||||
for( int i = 0; i < 16; ++i )
|
for( int i = 0; i < 16; ++i )
|
||||||
{
|
{
|
||||||
@ -664,11 +698,8 @@ void QuickCompress::compressDXT5(const ColorBlock & rgba, BlockDXT5 * dxtBlock,
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void QuickCompress::outputBlock4(const ColorBlock & rgba, const Vector3 & start, const Vector3 & end, BlockDXT1 * dxtBlock)
|
void QuickCompress::outputBlock4(const ColorSet & set, const Vector3 & start, const Vector3 & end, BlockDXT1 * block)
|
||||||
{
|
{
|
||||||
Vector3 block[16];
|
|
||||||
extractColorBlockRGB(rgba, block);
|
|
||||||
|
|
||||||
Vector3 maxColor = start * 255;
|
Vector3 maxColor = start * 255;
|
||||||
Vector3 minColor = end * 255;
|
Vector3 minColor = end * 255;
|
||||||
uint16 color0 = roundAndExpand(&maxColor);
|
uint16 color0 = roundAndExpand(&maxColor);
|
||||||
@ -680,18 +711,15 @@ void QuickCompress::outputBlock4(const ColorBlock & rgba, const Vector3 & start,
|
|||||||
swap(color0, color1);
|
swap(color0, color1);
|
||||||
}
|
}
|
||||||
|
|
||||||
dxtBlock->col0 = Color16(color0);
|
block->col0 = Color16(color0);
|
||||||
dxtBlock->col1 = Color16(color1);
|
block->col1 = Color16(color1);
|
||||||
dxtBlock->indices = computeIndices4(block, maxColor, minColor);
|
block->indices = computeIndices4(set, maxColor, minColor);
|
||||||
|
|
||||||
optimizeEndPoints4(block, dxtBlock);
|
//optimizeEndPoints4(set, block);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QuickCompress::outputBlock3(const ColorBlock & rgba, const Vector3 & start, const Vector3 & end, BlockDXT1 * dxtBlock)
|
void QuickCompress::outputBlock3(const ColorSet & set, const Vector3 & start, const Vector3 & end, BlockDXT1 * block)
|
||||||
{
|
{
|
||||||
Vector3 block[16];
|
|
||||||
extractColorBlockRGB(rgba, block);
|
|
||||||
|
|
||||||
Vector3 maxColor = start * 255;
|
Vector3 maxColor = start * 255;
|
||||||
Vector3 minColor = end * 255;
|
Vector3 minColor = end * 255;
|
||||||
uint16 color0 = roundAndExpand(&maxColor);
|
uint16 color0 = roundAndExpand(&maxColor);
|
||||||
@ -703,9 +731,9 @@ void QuickCompress::outputBlock3(const ColorBlock & rgba, const Vector3 & start,
|
|||||||
swap(color0, color1);
|
swap(color0, color1);
|
||||||
}
|
}
|
||||||
|
|
||||||
dxtBlock->col0 = Color16(color0);
|
block->col0 = Color16(color0);
|
||||||
dxtBlock->col1 = Color16(color1);
|
block->col1 = Color16(color1);
|
||||||
dxtBlock->indices = computeIndices3(block, maxColor, minColor);
|
block->indices = computeIndices3(set, maxColor, minColor);
|
||||||
|
|
||||||
optimizeEndPoints3(block, dxtBlock);
|
//optimizeEndPoints3(set, block);
|
||||||
}
|
}
|
@ -30,6 +30,7 @@
|
|||||||
namespace nv
|
namespace nv
|
||||||
{
|
{
|
||||||
struct ColorBlock;
|
struct ColorBlock;
|
||||||
|
struct ColorSet;
|
||||||
struct BlockDXT1;
|
struct BlockDXT1;
|
||||||
struct BlockDXT3;
|
struct BlockDXT3;
|
||||||
struct BlockDXT5;
|
struct BlockDXT5;
|
||||||
@ -47,8 +48,8 @@ namespace nv
|
|||||||
void compressDXT5A(const ColorBlock & rgba, AlphaBlockDXT5 * dxtBlock, int iterationCount=8);
|
void compressDXT5A(const ColorBlock & rgba, AlphaBlockDXT5 * dxtBlock, int iterationCount=8);
|
||||||
void compressDXT5(const ColorBlock & rgba, BlockDXT5 * dxtBlock, int iterationCount=8);
|
void compressDXT5(const ColorBlock & rgba, BlockDXT5 * dxtBlock, int iterationCount=8);
|
||||||
|
|
||||||
void outputBlock4(const ColorBlock & rgba, const Vector3 & start, const Vector3 & end, BlockDXT1 * block);
|
void outputBlock4(const ColorSet & set, const Vector3 & start, const Vector3 & end, BlockDXT1 * block);
|
||||||
void outputBlock3(const ColorBlock & rgba, const Vector3 & start, const Vector3 & end, BlockDXT1 * block);
|
void outputBlock3(const ColorSet & set, const Vector3 & start, const Vector3 & end, BlockDXT1 * block);
|
||||||
}
|
}
|
||||||
} // nv namespace
|
} // nv namespace
|
||||||
|
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
#include "nvimage/BlockDXT.h"
|
#include "nvimage/BlockDXT.h"
|
||||||
#include "nvimage/ColorBlock.h"
|
#include "nvimage/ColorBlock.h"
|
||||||
#include "nvimage/PixelFormat.h"
|
#include "nvimage/PixelFormat.h"
|
||||||
|
#include "nvimage/ErrorMetric.h"
|
||||||
|
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
|
|
||||||
@ -332,7 +333,8 @@ void TexImage::range(int channel, float * rangeMin, float * rangeMax)
|
|||||||
for (uint p = 0; p < count; p++) {
|
for (uint p = 0; p < count; p++) {
|
||||||
float f = c[p];
|
float f = c[p];
|
||||||
if (f < range.x) range.x = f;
|
if (f < range.x) range.x = f;
|
||||||
if (f > range.y) range.y = f;
|
if (f > range.y)
|
||||||
|
range.y = f;
|
||||||
}
|
}
|
||||||
|
|
||||||
*rangeMin = range.x;
|
*rangeMin = range.x;
|
||||||
@ -340,7 +342,7 @@ void TexImage::range(int channel, float * rangeMin, float * rangeMax)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool TexImage::load(const char * fileName)
|
bool TexImage::load(const char * fileName, bool * hasAlpha/*= NULL*/)
|
||||||
{
|
{
|
||||||
AutoPtr<FloatImage> img(ImageIO::loadFloat(fileName));
|
AutoPtr<FloatImage> img(ImageIO::loadFloat(fileName));
|
||||||
if (img == NULL) {
|
if (img == NULL) {
|
||||||
@ -349,6 +351,10 @@ bool TexImage::load(const char * fileName)
|
|||||||
|
|
||||||
detach();
|
detach();
|
||||||
|
|
||||||
|
if (hasAlpha != NULL) {
|
||||||
|
*hasAlpha = (img->componentNum() == 4);
|
||||||
|
}
|
||||||
|
|
||||||
// @@ Have loadFloat allocate the image with the desired number of channels.
|
// @@ Have loadFloat allocate the image with the desired number of channels.
|
||||||
img->resizeChannelCount(4);
|
img->resizeChannelCount(4);
|
||||||
|
|
||||||
@ -388,52 +394,52 @@ bool TexImage::setImage2D(nvtt::InputFormat format, int w, int h, const void * d
|
|||||||
{
|
{
|
||||||
const Color32 * src = (const Color32 *)data;
|
const Color32 * src = (const Color32 *)data;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
rdst[i] = float(src[i].r) / 255.0f;
|
rdst[i] = float(src[i].r) / 255.0f;
|
||||||
gdst[i] = float(src[i].g) / 255.0f;
|
gdst[i] = float(src[i].g) / 255.0f;
|
||||||
bdst[i] = float(src[i].b) / 255.0f;
|
bdst[i] = float(src[i].b) / 255.0f;
|
||||||
adst[i] = float(src[i].a) / 255.0f;
|
adst[i] = float(src[i].a) / 255.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(...) {
|
catch(...) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (format == InputFormat_RGBA_16F)
|
else if (format == InputFormat_RGBA_16F)
|
||||||
{
|
{
|
||||||
const uint16 * src = (const uint16 *)data;
|
const uint16 * src = (const uint16 *)data;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
((uint32 *)rdst)[i] = half_to_float(src[4*i+0]);
|
((uint32 *)rdst)[i] = half_to_float(src[4*i+0]);
|
||||||
((uint32 *)gdst)[i] = half_to_float(src[4*i+1]);
|
((uint32 *)gdst)[i] = half_to_float(src[4*i+1]);
|
||||||
((uint32 *)bdst)[i] = half_to_float(src[4*i+2]);
|
((uint32 *)bdst)[i] = half_to_float(src[4*i+2]);
|
||||||
((uint32 *)adst)[i] = half_to_float(src[4*i+3]);
|
((uint32 *)adst)[i] = half_to_float(src[4*i+3]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(...) {
|
catch(...) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (format == InputFormat_RGBA_32F)
|
else if (format == InputFormat_RGBA_32F)
|
||||||
{
|
{
|
||||||
const float * src = (const float *)data;
|
const float * src = (const float *)data;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
rdst[i] = src[4 * i + 0];
|
rdst[i] = src[4 * i + 0];
|
||||||
gdst[i] = src[4 * i + 1];
|
gdst[i] = src[4 * i + 1];
|
||||||
bdst[i] = src[4 * i + 2];
|
bdst[i] = src[4 * i + 2];
|
||||||
adst[i] = src[4 * i + 3];
|
adst[i] = src[4 * i + 3];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(...) {
|
catch(...) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -462,15 +468,15 @@ bool TexImage::setImage2D(InputFormat format, int w, int h, const void * r, cons
|
|||||||
const uint8 * bsrc = (const uint8 *)b;
|
const uint8 * bsrc = (const uint8 *)b;
|
||||||
const uint8 * asrc = (const uint8 *)a;
|
const uint8 * asrc = (const uint8 *)a;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
for (int i = 0; i < count; i++) rdst[i] = float(rsrc[i]) / 255.0f;
|
for (int i = 0; i < count; i++) rdst[i] = float(rsrc[i]) / 255.0f;
|
||||||
for (int i = 0; i < count; i++) gdst[i] = float(gsrc[i]) / 255.0f;
|
for (int i = 0; i < count; i++) gdst[i] = float(gsrc[i]) / 255.0f;
|
||||||
for (int i = 0; i < count; i++) bdst[i] = float(bsrc[i]) / 255.0f;
|
for (int i = 0; i < count; i++) bdst[i] = float(bsrc[i]) / 255.0f;
|
||||||
for (int i = 0; i < count; i++) adst[i] = float(asrc[i]) / 255.0f;
|
for (int i = 0; i < count; i++) adst[i] = float(asrc[i]) / 255.0f;
|
||||||
}
|
}
|
||||||
catch(...) {
|
catch(...) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (format == InputFormat_RGBA_16F)
|
else if (format == InputFormat_RGBA_16F)
|
||||||
{
|
{
|
||||||
@ -479,15 +485,15 @@ bool TexImage::setImage2D(InputFormat format, int w, int h, const void * r, cons
|
|||||||
const uint16 * bsrc = (const uint16 *)b;
|
const uint16 * bsrc = (const uint16 *)b;
|
||||||
const uint16 * asrc = (const uint16 *)a;
|
const uint16 * asrc = (const uint16 *)a;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
for (int i = 0; i < count; i++) ((uint32 *)rdst)[i] = half_to_float(rsrc[i]);
|
for (int i = 0; i < count; i++) ((uint32 *)rdst)[i] = half_to_float(rsrc[i]);
|
||||||
for (int i = 0; i < count; i++) ((uint32 *)gdst)[i] = half_to_float(gsrc[i]);
|
for (int i = 0; i < count; i++) ((uint32 *)gdst)[i] = half_to_float(gsrc[i]);
|
||||||
for (int i = 0; i < count; i++) ((uint32 *)bdst)[i] = half_to_float(bsrc[i]);
|
for (int i = 0; i < count; i++) ((uint32 *)bdst)[i] = half_to_float(bsrc[i]);
|
||||||
for (int i = 0; i < count; i++) ((uint32 *)adst)[i] = half_to_float(asrc[i]);
|
for (int i = 0; i < count; i++) ((uint32 *)adst)[i] = half_to_float(asrc[i]);
|
||||||
}
|
}
|
||||||
catch(...) {
|
catch(...) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (format == InputFormat_RGBA_32F)
|
else if (format == InputFormat_RGBA_32F)
|
||||||
{
|
{
|
||||||
@ -496,15 +502,15 @@ bool TexImage::setImage2D(InputFormat format, int w, int h, const void * r, cons
|
|||||||
const float * bsrc = (const float *)b;
|
const float * bsrc = (const float *)b;
|
||||||
const float * asrc = (const float *)a;
|
const float * asrc = (const float *)a;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
memcpy(rdst, rsrc, count * sizeof(float));
|
memcpy(rdst, rsrc, count * sizeof(float));
|
||||||
memcpy(gdst, gsrc, count * sizeof(float));
|
memcpy(gdst, gsrc, count * sizeof(float));
|
||||||
memcpy(bdst, bsrc, count * sizeof(float));
|
memcpy(bdst, bsrc, count * sizeof(float));
|
||||||
memcpy(adst, asrc, count * sizeof(float));
|
memcpy(adst, asrc, count * sizeof(float));
|
||||||
}
|
}
|
||||||
catch(...) {
|
catch(...) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -987,10 +993,10 @@ void TexImage::setBorder(float r, float g, float b, float a)
|
|||||||
img->pixel(0, i, 2) = b;
|
img->pixel(0, i, 2) = b;
|
||||||
img->pixel(0, i, 3) = a;
|
img->pixel(0, i, 3) = a;
|
||||||
|
|
||||||
img->pixel(w-1, i, 0) = r;
|
img->pixel(w-1, i, 0) = r;
|
||||||
img->pixel(w-1, i, 1) = g;
|
img->pixel(w-1, i, 1) = g;
|
||||||
img->pixel(w-1, i, 2) = b;
|
img->pixel(w-1, i, 2) = b;
|
||||||
img->pixel(w-1, i, 3) = a;
|
img->pixel(w-1, i, 3) = a;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1164,11 +1170,14 @@ void TexImage::blockScaleCoCg(int bits/*= 5*/, float threshold/*= 0.0*/)
|
|||||||
for (uint bi = 0; bi < bw; bi++) {
|
for (uint bi = 0; bi < bw; bi++) {
|
||||||
|
|
||||||
// Compute per block scale.
|
// Compute per block scale.
|
||||||
float m = 1.0f / 256.0f;
|
float m = 1.0f / 255.0f;
|
||||||
for (uint j = 0; j < 4; j++) {
|
for (uint j = 0; j < 4; j++) {
|
||||||
|
const uint y = bj*4 + j;
|
||||||
|
if (y >= h) continue;
|
||||||
|
|
||||||
for (uint i = 0; i < 4; i++) {
|
for (uint i = 0; i < 4; i++) {
|
||||||
uint x = min(bi*4 + i, w);
|
const uint x = bi*4 + i;
|
||||||
uint y = min(bj*4 + j, h);
|
if (x >= w) continue;
|
||||||
|
|
||||||
float Co = img->pixel(x, y, 0);
|
float Co = img->pixel(x, y, 0);
|
||||||
float Cg = img->pixel(x, y, 1);
|
float Cg = img->pixel(x, y, 1);
|
||||||
@ -1219,7 +1228,7 @@ void TexImage::fromYCoCg()
|
|||||||
for (uint i = 0; i < count; i++) {
|
for (uint i = 0; i < count; i++) {
|
||||||
float Co = r[i];
|
float Co = r[i];
|
||||||
float Cg = g[i];
|
float Cg = g[i];
|
||||||
float scale = b[i];
|
float scale = b[i] * 0.5f;
|
||||||
float Y = a[i];
|
float Y = a[i];
|
||||||
|
|
||||||
Co *= scale;
|
Co *= scale;
|
||||||
@ -1271,6 +1280,141 @@ void TexImage::fromLUVW(float range/*= 1.0f*/)
|
|||||||
fromRGBM(range * sqrtf(3));
|
fromRGBM(range * sqrtf(3));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TexImage::abs(int channel)
|
||||||
|
{
|
||||||
|
if (m->image == NULL) return;
|
||||||
|
|
||||||
|
detach();
|
||||||
|
|
||||||
|
FloatImage * img = m->image;
|
||||||
|
float * c = img->channel(channel);
|
||||||
|
|
||||||
|
const uint count = img->width() * img->height();
|
||||||
|
for (uint i = 0; i < count; i++) {
|
||||||
|
c[i] = fabsf(c[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TexImage::blockLuminanceScale(float scale)
|
||||||
|
{
|
||||||
|
if (m->image == NULL) return;
|
||||||
|
|
||||||
|
detach();
|
||||||
|
|
||||||
|
FloatImage * img = m->image;
|
||||||
|
|
||||||
|
//float * r = img->channel(0);
|
||||||
|
//float * g = img->channel(1);
|
||||||
|
//float * b = img->channel(2);
|
||||||
|
//float * a = img->channel(3);
|
||||||
|
|
||||||
|
const uint w = img->width();
|
||||||
|
const uint h = img->height();
|
||||||
|
const uint bw = max(1U, w/4);
|
||||||
|
const uint bh = max(1U, h/4);
|
||||||
|
|
||||||
|
Vector3 L = normalize(Vector3(1, 1, 1));
|
||||||
|
|
||||||
|
for (uint bj = 0; bj < bh; bj++) {
|
||||||
|
for (uint bi = 0; bi < bw; bi++) {
|
||||||
|
|
||||||
|
// Compute block centroid.
|
||||||
|
Vector3 centroid(0.0f);
|
||||||
|
int count = 0;
|
||||||
|
for (uint j = 0; j < 4; j++) {
|
||||||
|
const uint y = bj*4 + j;
|
||||||
|
if (y >= h) continue;
|
||||||
|
|
||||||
|
for (uint i = 0; i < 4; i++) {
|
||||||
|
const uint x = bi*4 + i;
|
||||||
|
if (x >= w) continue;
|
||||||
|
|
||||||
|
float r = img->pixel(x, y, 0);
|
||||||
|
float g = img->pixel(x, y, 1);
|
||||||
|
float b = img->pixel(x, y, 2);
|
||||||
|
Vector3 rgb(r, g, b);
|
||||||
|
|
||||||
|
centroid += rgb;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
centroid /= float(count);
|
||||||
|
|
||||||
|
// Project to luminance plane.
|
||||||
|
for (uint j = 0; j < 4; j++) {
|
||||||
|
const uint y = bj*4 + j;
|
||||||
|
if (y >= h) continue;
|
||||||
|
|
||||||
|
for (uint i = 0; i < 4; i++) {
|
||||||
|
const uint x = bi*4 + i;
|
||||||
|
if (x >= w) continue;
|
||||||
|
|
||||||
|
float & r = img->pixel(x, y, 0);
|
||||||
|
float & g = img->pixel(x, y, 1);
|
||||||
|
float & b = img->pixel(x, y, 2);
|
||||||
|
Vector3 rgb(r, g, b);
|
||||||
|
|
||||||
|
Vector3 delta = rgb - centroid;
|
||||||
|
|
||||||
|
delta -= scale * dot(delta, L) * L;
|
||||||
|
|
||||||
|
r = centroid.x + delta.x;
|
||||||
|
g = centroid.y + delta.y;
|
||||||
|
b = centroid.z + delta.z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TexImage::toJPEGLS()
|
||||||
|
{
|
||||||
|
if (m->image == NULL) return;
|
||||||
|
|
||||||
|
detach();
|
||||||
|
|
||||||
|
FloatImage * img = m->image;
|
||||||
|
float * r = img->channel(0);
|
||||||
|
float * g = img->channel(1);
|
||||||
|
float * b = img->channel(2);
|
||||||
|
|
||||||
|
const uint count = img->width() * img->height();
|
||||||
|
for (uint i = 0; i < count; i++) {
|
||||||
|
float R = nv::clamp(r[i], 0.0f, 1.0f);
|
||||||
|
float G = nv::clamp(g[i], 0.0f, 1.0f);
|
||||||
|
float B = nv::clamp(b[i], 0.0f, 1.0f);
|
||||||
|
|
||||||
|
r[i] = R-G;
|
||||||
|
g[i] = G;
|
||||||
|
b[i] = B-G;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TexImage::fromJPEGLS()
|
||||||
|
{
|
||||||
|
if (m->image == NULL) return;
|
||||||
|
|
||||||
|
detach();
|
||||||
|
|
||||||
|
FloatImage * img = m->image;
|
||||||
|
float * r = img->channel(0);
|
||||||
|
float * g = img->channel(1);
|
||||||
|
float * b = img->channel(2);
|
||||||
|
|
||||||
|
const uint count = img->width() * img->height();
|
||||||
|
for (uint i = 0; i < count; i++) {
|
||||||
|
float R = nv::clamp(r[i], -1.0f, 1.0f);
|
||||||
|
float G = nv::clamp(g[i], 0.0f, 1.0f);
|
||||||
|
float B = nv::clamp(b[i], -1.0f, 1.0f);
|
||||||
|
|
||||||
|
r[i] = R+G;
|
||||||
|
g[i] = G;
|
||||||
|
b[i] = B+G;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void TexImage::binarize(int channel, float threshold, bool dither)
|
void TexImage::binarize(int channel, float threshold, bool dither)
|
||||||
{
|
{
|
||||||
@ -1350,113 +1494,52 @@ bool TexImage::copyChannel(const TexImage & srcImage, int srcChannel, int dstCha
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TexImage::addChannel(const TexImage & srcImage, int srcChannel, int dstChannel, float scale)
|
||||||
|
{
|
||||||
|
if (srcChannel < 0 || srcChannel > 3 || dstChannel < 0 || dstChannel > 3) return false;
|
||||||
|
|
||||||
|
FloatImage * dst = m->image;
|
||||||
|
const FloatImage * src = srcImage.m->image;
|
||||||
|
|
||||||
|
if (dst == NULL || src == NULL || dst->width() != src->width() || dst->height() != src->height()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
nvDebugCheck(dst->componentNum() == 4 && src->componentNum() == 4);
|
||||||
|
|
||||||
|
detach();
|
||||||
|
|
||||||
|
const uint w = src->width();
|
||||||
|
const uint h = src->height();
|
||||||
|
|
||||||
|
float * d = dst->channel(dstChannel);
|
||||||
|
const float * s = src->channel(srcChannel);
|
||||||
|
for (uint i = 0; i < w*h; i++) {
|
||||||
|
d[i] += s[i] * scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
float nvtt::rmsError(const TexImage & reference, const TexImage & image)
|
float nvtt::rmsError(const TexImage & reference, const TexImage & image)
|
||||||
{
|
{
|
||||||
double mse = 0;
|
return nv::rmsColorError(reference.m->image, image.m->image, reference.alphaMode() == nvtt::AlphaMode_Transparency);
|
||||||
|
|
||||||
const FloatImage * ref = reference.m->image;
|
|
||||||
const FloatImage * img = image.m->image;
|
|
||||||
|
|
||||||
if (img == NULL || ref == NULL || img->width() != ref->width() || img->height() != ref->height()) {
|
|
||||||
return FLT_MAX;
|
|
||||||
}
|
|
||||||
nvDebugCheck(img->componentNum() == 4);
|
|
||||||
nvDebugCheck(ref->componentNum() == 4);
|
|
||||||
|
|
||||||
const uint count = img->width() * img->height();
|
|
||||||
for (uint i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
float r0 = img->pixel(i + count * 0);
|
|
||||||
float g0 = img->pixel(i + count * 1);
|
|
||||||
float b0 = img->pixel(i + count * 2);
|
|
||||||
//float a0 = img->pixel(i + count * 3);
|
|
||||||
float r1 = ref->pixel(i + count * 0);
|
|
||||||
float g1 = ref->pixel(i + count * 1);
|
|
||||||
float b1 = ref->pixel(i + count * 2);
|
|
||||||
float a1 = ref->pixel(i + count * 3);
|
|
||||||
|
|
||||||
float r = r0 - r1;
|
|
||||||
float g = g0 - g1;
|
|
||||||
float b = b0 - b1;
|
|
||||||
//float a = a0 - a1;
|
|
||||||
|
|
||||||
if (reference.alphaMode() == nvtt::AlphaMode_Transparency)
|
|
||||||
{
|
|
||||||
mse += double(r * r) * a1;
|
|
||||||
mse += double(g * g) * a1;
|
|
||||||
mse += double(b * b) * a1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mse += r * r;
|
|
||||||
mse += g * g;
|
|
||||||
mse += b * b;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return float(sqrt(mse / count));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*float rmsError(const Image * a, const Image * b)
|
|
||||||
{
|
|
||||||
nvCheck(a != NULL);
|
|
||||||
nvCheck(b != NULL);
|
|
||||||
nvCheck(a->width() == b->width());
|
|
||||||
nvCheck(a->height() == b->height());
|
|
||||||
|
|
||||||
double mse = 0;
|
|
||||||
|
|
||||||
const uint count = a->width() * a->height();
|
|
||||||
|
|
||||||
for (uint i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
Color32 c0 = a->pixel(i);
|
|
||||||
Color32 c1 = b->pixel(i);
|
|
||||||
|
|
||||||
int r = c0.r - c1.r;
|
|
||||||
int g = c0.g - c1.g;
|
|
||||||
int b = c0.b - c1.b;
|
|
||||||
int a = c0.a - c1.a;
|
|
||||||
|
|
||||||
mse += double(r * r * c0.a) / 255;
|
|
||||||
mse += double(g * g * c0.a) / 255;
|
|
||||||
mse += double(b * b * c0.a) / 255;
|
|
||||||
}
|
|
||||||
|
|
||||||
return float(sqrt(mse / count));
|
|
||||||
}*/
|
|
||||||
|
|
||||||
|
|
||||||
float nvtt::rmsAlphaError(const TexImage & reference, const TexImage & image)
|
float nvtt::rmsAlphaError(const TexImage & reference, const TexImage & image)
|
||||||
{
|
{
|
||||||
double mse = 0;
|
return nv::rmsAlphaError(reference.m->image, image.m->image);
|
||||||
|
|
||||||
const FloatImage * img = image.m->image;
|
|
||||||
const FloatImage * ref = reference.m->image;
|
|
||||||
|
|
||||||
if (img == NULL || ref == NULL || img->width() != ref->width() || img->height() != ref->height()) {
|
|
||||||
return FLT_MAX;
|
|
||||||
}
|
|
||||||
nvDebugCheck(img->componentNum() == 4 && ref->componentNum() == 4);
|
|
||||||
|
|
||||||
const uint count = img->width() * img->height();
|
|
||||||
for (uint i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
float a0 = img->pixel(i + count * 3);
|
|
||||||
float a1 = ref->pixel(i + count * 3);
|
|
||||||
|
|
||||||
float a = a0 - a1;
|
|
||||||
|
|
||||||
mse += double(a * a);
|
|
||||||
}
|
|
||||||
|
|
||||||
return float(sqrt(mse / count));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float nvtt::cieLabError(const TexImage & reference, const TexImage & image)
|
||||||
|
{
|
||||||
|
return nv::cieLabError(reference.m->image, image.m->image);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
TexImage nvtt::diff(const TexImage & reference, const TexImage & image, float scale)
|
TexImage nvtt::diff(const TexImage & reference, const TexImage & image, float scale)
|
||||||
{
|
{
|
||||||
const FloatImage * ref = reference.m->image;
|
const FloatImage * ref = reference.m->image;
|
||||||
|
@ -49,7 +49,7 @@ namespace nvtt
|
|||||||
wrapMode = WrapMode_Mirror;
|
wrapMode = WrapMode_Mirror;
|
||||||
alphaMode = AlphaMode_None;
|
alphaMode = AlphaMode_None;
|
||||||
isNormalMap = false;
|
isNormalMap = false;
|
||||||
|
|
||||||
image = NULL;
|
image = NULL;
|
||||||
}
|
}
|
||||||
Private(const Private & p) : RefCounted() // Copy ctor. inits refcount to 0.
|
Private(const Private & p) : RefCounted() // Copy ctor. inits refcount to 0.
|
||||||
|
@ -445,7 +445,7 @@ void ZOH::decompresstwo(const char *block, Tile &t)
|
|||||||
// reserved mode, return all zeroes
|
// reserved mode, return all zeroes
|
||||||
for (int y = 0; y < Tile::TILE_H; y++)
|
for (int y = 0; y < Tile::TILE_H; y++)
|
||||||
for (int x = 0; x < Tile::TILE_W; x++)
|
for (int x = 0; x < Tile::TILE_W; x++)
|
||||||
t.data[y][x] = Vector3 (zero);
|
t.data[y][x] = Vector3(0.0f);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -399,7 +399,7 @@ namespace nvtt
|
|||||||
NVTT_API void range(int channel, float * rangeMin, float * rangeMax);
|
NVTT_API void range(int channel, float * rangeMin, float * rangeMax);
|
||||||
|
|
||||||
// Texture data.
|
// Texture data.
|
||||||
NVTT_API bool load(const char * fileName);
|
NVTT_API bool load(const char * fileName, bool * hasAlpha = 0);
|
||||||
NVTT_API bool save(const char * fileName) const;
|
NVTT_API bool save(const char * fileName) const;
|
||||||
NVTT_API bool setImage2D(InputFormat format, int w, int h, const void * data);
|
NVTT_API bool setImage2D(InputFormat format, int w, int h, const void * data);
|
||||||
NVTT_API bool setImage2D(InputFormat format, int w, int h, const void * r, const void * g, const void * b, const void * a);
|
NVTT_API bool setImage2D(InputFormat format, int w, int h, const void * r, const void * g, const void * b, const void * a);
|
||||||
@ -436,6 +436,11 @@ namespace nvtt
|
|||||||
NVTT_API void fromYCoCg();
|
NVTT_API void fromYCoCg();
|
||||||
NVTT_API void toLUVW(float range = 1.0f);
|
NVTT_API void toLUVW(float range = 1.0f);
|
||||||
NVTT_API void fromLUVW(float range = 1.0f);
|
NVTT_API void fromLUVW(float range = 1.0f);
|
||||||
|
NVTT_API void abs(int channel);
|
||||||
|
NVTT_API void toJPEGLS();
|
||||||
|
NVTT_API void fromJPEGLS();
|
||||||
|
|
||||||
|
NVTT_API void blockLuminanceScale(float scale);
|
||||||
|
|
||||||
// Color quantization.
|
// Color quantization.
|
||||||
NVTT_API void binarize(int channel, float threshold, bool dither);
|
NVTT_API void binarize(int channel, float threshold, bool dither);
|
||||||
@ -452,9 +457,12 @@ namespace nvtt
|
|||||||
NVTT_API bool copyChannel(const TexImage & srcImage, int srcChannel);
|
NVTT_API bool copyChannel(const TexImage & srcImage, int srcChannel);
|
||||||
NVTT_API bool copyChannel(const TexImage & srcImage, int srcChannel, int dstChannel);
|
NVTT_API bool copyChannel(const TexImage & srcImage, int srcChannel, int dstChannel);
|
||||||
|
|
||||||
|
NVTT_API bool addChannel(const TexImage & img, int srcChannel, int dstChannel, float scale);
|
||||||
|
|
||||||
// Error compare.
|
// Error compare.
|
||||||
NVTT_API friend float rmsError(const TexImage & reference, const TexImage & img);
|
NVTT_API friend float rmsError(const TexImage & reference, const TexImage & img);
|
||||||
NVTT_API friend float rmsAlphaError(const TexImage & reference, const TexImage & img);
|
NVTT_API friend float rmsAlphaError(const TexImage & reference, const TexImage & img);
|
||||||
|
NVTT_API friend float cieLabError(const TexImage & reference, const TexImage & img);
|
||||||
NVTT_API friend TexImage diff(const TexImage & reference, const TexImage & img, float scale);
|
NVTT_API friend TexImage diff(const TexImage & reference, const TexImage & img, float scale);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -473,8 +481,10 @@ namespace nvtt
|
|||||||
|
|
||||||
NVTT_API float rmsError(const TexImage & reference, const TexImage & img);
|
NVTT_API float rmsError(const TexImage & reference, const TexImage & img);
|
||||||
NVTT_API float rmsAlphaError(const TexImage & reference, const TexImage & img);
|
NVTT_API float rmsAlphaError(const TexImage & reference, const TexImage & img);
|
||||||
|
NVTT_API float cieLabError(const TexImage & reference, const TexImage & img);
|
||||||
NVTT_API TexImage diff(const TexImage & reference, const TexImage & img, float scale);
|
NVTT_API TexImage diff(const TexImage & reference, const TexImage & img, float scale);
|
||||||
|
|
||||||
|
|
||||||
} // nvtt namespace
|
} // nvtt namespace
|
||||||
|
|
||||||
#endif // NVTT_H
|
#endif // NVTT_H
|
||||||
|
@ -147,6 +147,8 @@ static const char * s_witnessImageSet[] = {
|
|||||||
|
|
||||||
static const char * s_witnessLmapImageSet[] = {
|
static const char * s_witnessLmapImageSet[] = {
|
||||||
"specruin.dds",
|
"specruin.dds",
|
||||||
|
"cottage.dds",
|
||||||
|
"tower.dds",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -158,56 +160,64 @@ enum Mode {
|
|||||||
Mode_BC3_YCoCg,
|
Mode_BC3_YCoCg,
|
||||||
Mode_BC3_RGBM,
|
Mode_BC3_RGBM,
|
||||||
Mode_BC3_LUVW,
|
Mode_BC3_LUVW,
|
||||||
|
Mode_BC3_RGBS,
|
||||||
Mode_BC1_Normal,
|
Mode_BC1_Normal,
|
||||||
Mode_BC3_Normal,
|
Mode_BC3_Normal,
|
||||||
Mode_BC5_Normal,
|
Mode_BC5_Normal,
|
||||||
Mode_BC3_Lightmap_1,
|
Mode_Count
|
||||||
Mode_BC3_Lightmap_2,
|
|
||||||
};
|
};
|
||||||
static const char * s_modeNames[] = {
|
static const char * s_modeNames[] = {
|
||||||
"BC1",
|
"BC1", // Mode_BC1,
|
||||||
"BC1-Alpha",
|
"BC1-Alpha", // Mode_BC1_Alpha,
|
||||||
"BC2-Alpha",
|
"BC2-Alpha", // Mode_BC2_Alpha,
|
||||||
"BC3-Alpha",
|
"BC3-Alpha", // Mode_BC3_Alpha,
|
||||||
"BC3-YCoCg",
|
"BC3-YCoCg", // Mode_BC3_YCoCg,
|
||||||
"BC3-RGBM",
|
"BC3-RGBM", // Mode_BC3_RGBM,
|
||||||
"BC3-LUVW",
|
"BC3-LUVW", // Mode_BC3_LUVW,
|
||||||
"BC1-Normal",
|
"BC3-RGBS", // Mode_BC3_RGBS,
|
||||||
"BC3-Normal",
|
"BC1-Normal", // Mode_BC1_Normal,
|
||||||
"BC5-Normal",
|
"BC3-Normal", // Mode_BC3_Normal,
|
||||||
"BC3-RGBM",
|
"BC5-Normal", // Mode_BC5_Normal,
|
||||||
"BC3-LUVW",
|
|
||||||
};
|
};
|
||||||
|
nvStaticCheck(ARRAY_SIZE(s_modeNames) == Mode_Count);
|
||||||
|
|
||||||
struct Test {
|
struct Test {
|
||||||
const char * name;
|
const char * name;
|
||||||
int count;
|
int count;
|
||||||
Mode modes[4];
|
Mode modes[6];
|
||||||
};
|
};
|
||||||
static Test s_imageTests[] = {
|
static Test s_imageTests[] = {
|
||||||
{"DXT Color", 1, {Mode_BC1, Mode_BC3_YCoCg, Mode_BC3_RGBM, Mode_BC3_LUVW}},
|
{"Color", 3, {Mode_BC1, Mode_BC3_YCoCg, Mode_BC3_RGBM, Mode_BC3_LUVW}},
|
||||||
{"DXT Alpha", 3, {Mode_BC1_Alpha, Mode_BC2_Alpha, Mode_BC3_Alpha}},
|
{"Alpha", 3, {Mode_BC1_Alpha, Mode_BC2_Alpha, Mode_BC3_Alpha}},
|
||||||
{"DXT Normal", 3, {Mode_BC1_Normal, Mode_BC3_Normal, Mode_BC5_Normal}},
|
{"Normal", 3, {Mode_BC1_Normal, Mode_BC3_Normal, Mode_BC5_Normal}},
|
||||||
{"DXT Lightmap", 2, {Mode_BC3_Lightmap_1, Mode_BC3_Lightmap_2}},
|
{"Lightmap", 4, {Mode_BC1, Mode_BC3_YCoCg, Mode_BC3_RGBM, Mode_BC3_RGBS}},
|
||||||
};
|
};
|
||||||
const int s_imageTestCount = ARRAY_SIZE(s_imageTests);
|
const int s_imageTestCount = ARRAY_SIZE(s_imageTests);
|
||||||
|
|
||||||
|
enum ImageType {
|
||||||
|
ImageType_RGB,
|
||||||
|
ImageType_RGBA,
|
||||||
|
ImageType_Normal,
|
||||||
|
ImageType_HDR,
|
||||||
|
};
|
||||||
|
|
||||||
struct ImageSet
|
struct ImageSet
|
||||||
{
|
{
|
||||||
const char * name;
|
const char * name;
|
||||||
const char * basePath;
|
const char * basePath;
|
||||||
const char ** fileNames;
|
const char ** fileNames;
|
||||||
int fileCount;
|
int fileCount;
|
||||||
|
ImageType type;
|
||||||
};
|
};
|
||||||
static ImageSet s_imageSets[] = {
|
static ImageSet s_imageSets[] = {
|
||||||
{"Kodak", "kodak", s_kodakImageSet, ARRAY_SIZE(s_kodakImageSet)}, // 0
|
{"Kodak", "kodak", s_kodakImageSet, ARRAY_SIZE(s_kodakImageSet), ImageType_RGB}, // 0
|
||||||
{"Waterloo", "waterloo", s_waterlooImageSet, ARRAY_SIZE(s_waterlooImageSet)}, // 1
|
{"Waterloo", "waterloo", s_waterlooImageSet, ARRAY_SIZE(s_waterlooImageSet), ImageType_RGB}, // 1
|
||||||
{"Epic", "epic", s_epicImageSet, ARRAY_SIZE(s_epicImageSet)}, // 2
|
{"Epic", "epic", s_epicImageSet, ARRAY_SIZE(s_epicImageSet), ImageType_RGB}, // 2
|
||||||
{"Farbraush", "farbrausch", s_farbrauschImageSet, ARRAY_SIZE(s_farbrauschImageSet)}, // 3
|
{"Farbraush", "farbrausch", s_farbrauschImageSet, ARRAY_SIZE(s_farbrauschImageSet), ImageType_RGB}, // 3
|
||||||
{"Lugaru", "lugaru", s_lugaruImageSet, ARRAY_SIZE(s_lugaruImageSet)}, // 4
|
{"Lugaru", "lugaru", s_lugaruImageSet, ARRAY_SIZE(s_lugaruImageSet), ImageType_RGBA}, // 4
|
||||||
{"Quake3", "quake3", s_quake3ImageSet, ARRAY_SIZE(s_quake3ImageSet)}, // 5
|
{"Quake3", "quake3", s_quake3ImageSet, ARRAY_SIZE(s_quake3ImageSet), ImageType_RGBA}, // 5
|
||||||
{"Witness", "witness", s_witnessImageSet, ARRAY_SIZE(s_witnessImageSet)}, // 6
|
{"Witness", "witness", s_witnessImageSet, ARRAY_SIZE(s_witnessImageSet), ImageType_RGB}, // 6
|
||||||
{"Lightmap", "lightmap", s_witnessLmapImageSet, ARRAY_SIZE(s_witnessLmapImageSet)}, // 7
|
{"Lightmap", "lightmap", s_witnessLmapImageSet, ARRAY_SIZE(s_witnessLmapImageSet), ImageType_HDR}, // 7
|
||||||
};
|
};
|
||||||
const int s_imageSetCount = sizeof(s_imageSets)/sizeof(s_imageSets[0]);
|
const int s_imageSetCount = sizeof(s_imageSets)/sizeof(s_imageSets[0]);
|
||||||
|
|
||||||
@ -237,14 +247,8 @@ struct MyOutputHandler : public nvtt::OutputHandler
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
nvtt::TexImage decompress(Mode mode, nvtt::Decoder decoder)
|
nvtt::TexImage decompress(Mode mode, nvtt::Format format, nvtt::Decoder decoder)
|
||||||
{
|
{
|
||||||
nvtt::Format format;
|
|
||||||
if (mode == Mode_BC1 || mode == Mode_BC1_Alpha || mode == Mode_BC1_Normal) format = nvtt::Format_BC1;
|
|
||||||
else if (mode == Mode_BC2_Alpha) format = nvtt::Format_BC2;
|
|
||||||
else if (mode == Mode_BC5_Normal) format = nvtt::Format_BC5;
|
|
||||||
else format = nvtt::Format_BC3;
|
|
||||||
|
|
||||||
nvtt::TexImage img;
|
nvtt::TexImage img;
|
||||||
img.setImage2D(format, decoder, m_width, m_height, m_data);
|
img.setImage2D(format, decoder, m_width, m_height, m_data);
|
||||||
|
|
||||||
@ -427,7 +431,8 @@ int main(int argc, char *argv[])
|
|||||||
//TextWriter csvWriter(&csvStream);
|
//TextWriter csvWriter(&csvStream);
|
||||||
|
|
||||||
Path graphFileName;
|
Path graphFileName;
|
||||||
graphFileName.format("%s/chart.txt", outPath/*, test.name*/);
|
graphFileName.format("%s/chart_%s_CIE-Lab.txt", outPath, test.name);
|
||||||
|
//graphFileName.format("%s/chart_%s_RMSE.txt", outPath, test.name);
|
||||||
StdOutputStream graphStream(graphFileName.str());
|
StdOutputStream graphStream(graphFileName.str());
|
||||||
TextWriter graphWriter(&graphStream);
|
TextWriter graphWriter(&graphStream);
|
||||||
|
|
||||||
@ -446,7 +451,8 @@ int main(int argc, char *argv[])
|
|||||||
graphWriter << "&chxt=x,y&chxtc=0,-1000|1,-1000";
|
graphWriter << "&chxt=x,y&chxtc=0,-1000|1,-1000";
|
||||||
|
|
||||||
// Labels.
|
// Labels.
|
||||||
graphWriter << "&chxr=0,1," << set.fileCount << ",1|1,0,0.05,0.01";
|
graphWriter << "&chxr=0,1," << set.fileCount << ",1|1,0,0.05,0.01"; // rmse
|
||||||
|
//graphWriter << "&chxr=0,1," << set.fileCount << ",1|1,4,22,1"; // cielab
|
||||||
graphWriter << "&chdlp=b"; // Labels at the bottom.
|
graphWriter << "&chdlp=b"; // Labels at the bottom.
|
||||||
|
|
||||||
// Line colors.
|
// Line colors.
|
||||||
@ -473,7 +479,8 @@ int main(int argc, char *argv[])
|
|||||||
graphWriter << "&chds=";
|
graphWriter << "&chds=";
|
||||||
for (int t = 0; t < test.count; t++)
|
for (int t = 0; t < test.count; t++)
|
||||||
{
|
{
|
||||||
graphWriter << "0,0.05";
|
graphWriter << "0,0.05"; // rmse
|
||||||
|
//graphWriter << "4,22"; // cielab
|
||||||
if (t != test.count-1) graphWriter << ",";
|
if (t != test.count-1) graphWriter << ",";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -486,15 +493,14 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Title
|
// Title
|
||||||
graphWriter << "&chtt=" << set.name << " - " << test.name;
|
graphWriter << "&chtt=" << set.name << "%20-%20" << test.name << "%20-%20RMSE";
|
||||||
|
//graphWriter << "&chtt=" << set.name << "%20-%20" << test.name << "%20-%20CIE-Lab";
|
||||||
float totalTime = 0;
|
|
||||||
float totalRMSE = 0;
|
|
||||||
//int failedTests = 0;
|
|
||||||
float totalDiff = 0;
|
|
||||||
|
|
||||||
|
|
||||||
Timer timer;
|
Timer timer;
|
||||||
|
//int failedTests = 0;
|
||||||
|
//float totalDiff = 0;
|
||||||
|
|
||||||
nvtt::TexImage img;
|
nvtt::TexImage img;
|
||||||
|
|
||||||
@ -504,26 +510,42 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
for (int t = 0; t < test.count; t++)
|
for (int t = 0; t < test.count; t++)
|
||||||
{
|
{
|
||||||
|
float totalTime = 0;
|
||||||
|
float totalRMSE = 0;
|
||||||
|
float totalDeltaE = 0;
|
||||||
|
|
||||||
Mode mode = test.modes[t];
|
Mode mode = test.modes[t];
|
||||||
if (mode == Mode_BC1 || mode == Mode_BC1_Alpha || mode == Mode_BC1_Normal) {
|
|
||||||
compressionOptions.setFormat(nvtt::Format_BC1);
|
nvtt::Format format;
|
||||||
|
if (mode == Mode_BC1 || mode == Mode_BC1_Alpha || mode == Mode_BC1_Normal || mode == Mode_BC3_RGBS) {
|
||||||
|
format = nvtt::Format_BC1;
|
||||||
}
|
}
|
||||||
else if (mode == Mode_BC3_Alpha || mode == Mode_BC3_YCoCg || mode == Mode_BC3_RGBM || mode == Mode_BC3_LUVW || mode == Mode_BC3_Lightmap_1 || mode == Mode_BC3_Lightmap_2) {
|
else if (mode == Mode_BC3_Alpha || mode == Mode_BC3_YCoCg || mode == Mode_BC3_RGBM || mode == Mode_BC3_LUVW) {
|
||||||
compressionOptions.setFormat(nvtt::Format_BC3);
|
format = nvtt::Format_BC3;
|
||||||
}
|
}
|
||||||
else if (mode == Mode_BC3_Normal) {
|
else if (mode == Mode_BC3_Normal) {
|
||||||
compressionOptions.setFormat(nvtt::Format_BC3n);
|
format = nvtt::Format_BC3n;
|
||||||
}
|
}
|
||||||
else if (mode == Mode_BC5_Normal) {
|
else if (mode == Mode_BC5_Normal) {
|
||||||
compressionOptions.setFormat(nvtt::Format_BC5);
|
format = nvtt::Format_BC5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
compressionOptions.setFormat(format);
|
||||||
|
|
||||||
if (mode == Mode_BC3_Alpha || mode == Mode_BC3_Lightmap_1 || mode == Mode_BC3_Lightmap_2) { // Lightmap's alpha channel is coverage.
|
if (set.type == ImageType_RGBA) {
|
||||||
img.setAlphaMode(nvtt::AlphaMode_Transparency);
|
img.setAlphaMode(nvtt::AlphaMode_Transparency);
|
||||||
}
|
}
|
||||||
if (mode == Mode_BC1_Normal || mode == Mode_BC3_Normal || mode == Mode_BC5_Normal) {
|
else if (set.type == ImageType_Normal) {
|
||||||
img.setNormalMap(true);
|
img.setNormalMap(true);
|
||||||
}
|
}
|
||||||
|
else if (set.type == ImageType_HDR) { // Lightmap's alpha channel is coverage.
|
||||||
|
img.setAlphaMode(nvtt::AlphaMode_Transparency);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create output directory.
|
||||||
|
Path outputFilePath;
|
||||||
|
outputFilePath.format("%s/%s", outPath, s_modeNames[test.modes[t]]);
|
||||||
|
FileSystem::createDirectory(outputFilePath.str());
|
||||||
|
|
||||||
|
|
||||||
printf("Processing Set: %s\n", set.name);
|
printf("Processing Set: %s\n", set.name);
|
||||||
@ -538,65 +560,72 @@ int main(int argc, char *argv[])
|
|||||||
if (img.isNormalMap()) {
|
if (img.isNormalMap()) {
|
||||||
img.normalizeNormalMap();
|
img.normalizeNormalMap();
|
||||||
}
|
}
|
||||||
|
if (set.type == ImageType_HDR) {
|
||||||
|
img.scaleBias(0, 1.0f/4.0f, 0.0f); img.clamp(0);
|
||||||
|
img.scaleBias(1, 1.0f/4.0f, 0.0f); img.clamp(1);
|
||||||
|
img.scaleBias(2, 1.0f/4.0f, 0.0f); img.clamp(2);
|
||||||
|
img.toGamma(2);
|
||||||
|
}
|
||||||
|
|
||||||
nvtt::TexImage tmp = img;
|
nvtt::TexImage tmp = img;
|
||||||
|
if (mode == Mode_BC1) {
|
||||||
|
if (set.type == ImageType_HDR) {
|
||||||
|
/*for (int i = 0; i < 3; i++) {
|
||||||
|
tmp.scaleBias(i, 0.25f, 0);
|
||||||
|
tmp.clamp(i);
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
}
|
||||||
if (mode == Mode_BC3_YCoCg) {
|
if (mode == Mode_BC3_YCoCg) {
|
||||||
tmp.toYCoCg();
|
tmp.setAlphaMode(nvtt::AlphaMode_None);
|
||||||
tmp.blockScaleCoCg();
|
if (set.type == ImageType_HDR) {
|
||||||
tmp.scaleBias(0, 0.5, 0.5);
|
/*for (int i = 0; i < 3; i++) {
|
||||||
tmp.scaleBias(1, 0.5, 0.5);
|
tmp.scaleBias(i, 1.0f/4.0f, 0);
|
||||||
|
tmp.clamp(i);
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
tmp.toYCoCg(); // Y=3, Co=0, Cg=1
|
||||||
|
tmp.blockScaleCoCg(); // Co=0, Cg=1, Scale=2, ScaleBits = 5
|
||||||
|
|
||||||
|
tmp.scaleBias(0, 123.0f/255.0f, 123.0f/255.0f); tmp.clamp(0, 0, 246.0f/255.0f); // -1->0, 0->123, 1->246
|
||||||
|
tmp.scaleBias(1, 125.0f/255.0f, 125.0f/255.0f); tmp.clamp(1, 0, 250.0f/255.0f); // -1->0, 0->125, 1->250
|
||||||
|
|
||||||
|
//tmp.scaleBias(0, 0.5f, 0.5f); tmp.clamp(0);
|
||||||
|
//tmp.scaleBias(1, 0.5f, 0.5f); tmp.clamp(1);
|
||||||
|
|
||||||
|
tmp.clamp(2);
|
||||||
|
tmp.clamp(3);
|
||||||
}
|
}
|
||||||
else if (mode == Mode_BC3_RGBM) {
|
else if (mode == Mode_BC3_RGBM) {
|
||||||
tmp.toRGBM();
|
tmp.setAlphaMode(nvtt::AlphaMode_None);
|
||||||
|
if (set.type == ImageType_HDR) {
|
||||||
|
tmp.toRGBM(/*4*/);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
tmp.toRGBM();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (mode == Mode_BC3_LUVW) {
|
else if (mode == Mode_BC3_LUVW) {
|
||||||
tmp.toLUVW();
|
tmp.setAlphaMode(nvtt::AlphaMode_None);
|
||||||
}
|
if (set.type == ImageType_HDR) {
|
||||||
else if (mode == Mode_BC3_Lightmap_1) {
|
tmp.toLUVW(/*4*/);
|
||||||
tmp.toRGBM(4);
|
|
||||||
|
|
||||||
/*float rmin, rmax;
|
|
||||||
tmp.range(0, &rmin, &rmax);
|
|
||||||
|
|
||||||
float gmin, gmax;
|
|
||||||
tmp.range(1, &gmin, &gmax);
|
|
||||||
|
|
||||||
float bmin, bmax;
|
|
||||||
tmp.range(2, &bmin, &bmax);
|
|
||||||
|
|
||||||
float lmin, lmax;
|
|
||||||
tmp.range(3, &lmin, &lmax);
|
|
||||||
|
|
||||||
printf("rmin: %.3f rmax: %.3f\n", rmin, rmax);
|
|
||||||
printf("gmin: %.3f gmax: %.3f\n", gmin, gmax);
|
|
||||||
printf("bmin: %.3f bmax: %.3f\n", bmin, bmax);
|
|
||||||
printf("lmin: %.3f lmax: %.3f\n", lmin, lmax);
|
|
||||||
|
|
||||||
const int N = 32;
|
|
||||||
int chistogram[N];
|
|
||||||
int lhistogram[N];
|
|
||||||
memset(chistogram, 0, sizeof(chistogram));
|
|
||||||
memset(lhistogram, 0, sizeof(lhistogram));
|
|
||||||
|
|
||||||
tmp.histogram(0, 0, 1, N, chistogram);
|
|
||||||
tmp.histogram(1, 0, 1, N, chistogram);
|
|
||||||
tmp.histogram(2, 0, 1, N, chistogram);
|
|
||||||
tmp.histogram(3, 0, 1, N, lhistogram);
|
|
||||||
|
|
||||||
printf("Color histogram:\n");
|
|
||||||
for (int i = 0; i < N; i++) {
|
|
||||||
printf("%d, ", chistogram[i]);
|
|
||||||
}
|
}
|
||||||
printf("\n");
|
else {
|
||||||
|
tmp.toLUVW();
|
||||||
printf("Luminance histogram:\n");
|
|
||||||
for (int i = 0; i < N; i++) {
|
|
||||||
printf("%d, ", lhistogram[i]);
|
|
||||||
}
|
}
|
||||||
printf("\n");*/
|
|
||||||
}
|
}
|
||||||
else if (mode == Mode_BC3_Lightmap_2) {
|
else if (mode == Mode_BC3_RGBS) {
|
||||||
tmp.toLUVW(4);
|
//tmp.toJPEGLS();
|
||||||
|
//tmp.scaleBias(0, 123.0f/255.0f, 123.0f/255.0f); tmp.clamp(0, 0, 246.0f/255.0f); // -1->0, 0->123, 1->246
|
||||||
|
//tmp.scaleBias(2, 123.0f/255.0f, 123.0f/255.0f); tmp.clamp(0, 0, 246.0f/255.0f); // -1->0, 0->123, 1->246
|
||||||
|
|
||||||
|
// Not helping...
|
||||||
|
//tmp.blockLuminanceScale(0.1f);
|
||||||
|
/*tmp.toYCoCg();
|
||||||
|
tmp.scaleBias(0, 0.5, 0.5);
|
||||||
|
tmp.scaleBias(1, 0.5, 0.5);
|
||||||
|
tmp.swizzle(0, 3, 1, 4); // Co Cg 1 Y -> Co Y Cg 1
|
||||||
|
tmp.copyChannel(img, 3); // Restore alpha channel for weighting.*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -610,59 +639,152 @@ int main(int argc, char *argv[])
|
|||||||
printf(" Time: \t%.3f sec\n", timer.elapsed());
|
printf(" Time: \t%.3f sec\n", timer.elapsed());
|
||||||
totalTime += timer.elapsed();
|
totalTime += timer.elapsed();
|
||||||
|
|
||||||
nvtt::TexImage img_out = outputHandler.decompress(mode, decoder);
|
nvtt::TexImage img_out = outputHandler.decompress(mode, format, decoder);
|
||||||
img_out.setAlphaMode(img.alphaMode());
|
img_out.setAlphaMode(img.alphaMode());
|
||||||
img_out.setNormalMap(img.isNormalMap());
|
img_out.setNormalMap(img.isNormalMap());
|
||||||
|
|
||||||
if (mode == Mode_BC3_YCoCg) {
|
if (mode == Mode_BC1) {
|
||||||
img_out.scaleBias(0, 1.0, -0.5);
|
if (set.type == ImageType_HDR) {
|
||||||
img_out.scaleBias(1, 1.0, -0.5);
|
/*for (int i = 0; i < 3; i++) {
|
||||||
|
img_out.scaleBias(i, 4.0f, 0);
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (mode == Mode_BC3_YCoCg) {
|
||||||
|
img_out.scaleBias(0, 255.0f/123, -1.0f); // 0->-1, 123->0, 246->1
|
||||||
|
img_out.scaleBias(1, 255.0f/125, -1.0f); // 0->-1, 125->0, 150->1
|
||||||
|
|
||||||
|
//img_out.scaleBias(0, 2.0f, -1.0f);
|
||||||
|
//img_out.scaleBias(1, 2.0f, -1.0f);
|
||||||
|
|
||||||
img_out.fromYCoCg();
|
img_out.fromYCoCg();
|
||||||
|
img_out.clamp(0);
|
||||||
|
img_out.clamp(1);
|
||||||
|
img_out.clamp(2);
|
||||||
|
if (set.type == ImageType_HDR) {
|
||||||
|
/*for (int i = 0; i < 3; i++) {
|
||||||
|
img_out.scaleBias(i, 4.0f, 0);
|
||||||
|
}*/
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (mode == Mode_BC3_RGBM) {
|
else if (mode == Mode_BC3_RGBM) {
|
||||||
img_out.fromRGBM();
|
if (set.type == ImageType_HDR) {
|
||||||
|
img_out.fromRGBM(/*4*/);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
img_out.fromRGBM();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (mode == Mode_BC3_LUVW) {
|
else if (mode == Mode_BC3_LUVW) {
|
||||||
img_out.fromLUVW();
|
if (set.type == ImageType_HDR) {
|
||||||
|
img_out.fromLUVW(/*4*/);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
img_out.fromLUVW();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (mode == Mode_BC3_Lightmap_1) {
|
else if (mode == Mode_BC3_RGBS) {
|
||||||
img_out.fromRGBM(4);
|
//img_out.scaleBias(0, 255.0f/123, -1.0f);
|
||||||
}
|
//img_out.scaleBias(2, 255.0f/123, -1.0f);
|
||||||
else if (mode == Mode_BC3_Lightmap_2) {
|
//img_out.fromJPEGLS();
|
||||||
img_out.fromLUVW(4);
|
/*img_out.swizzle(0, 2, 4, 1); // Co Y Cg 1 - > Co Cg 1 Y
|
||||||
|
img_out.scaleBias(0, 1.0, -0.5);
|
||||||
|
img_out.scaleBias(1, 1.0, -0.5);
|
||||||
|
img_out.fromYCoCg();*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nvtt::TexImage diff = nvtt::diff(img, img_out, 1.0f);
|
||||||
|
|
||||||
Path outputFilePath;
|
//bool residualCompression = (set.type == ImageType_HDR);
|
||||||
outputFilePath.format("%s/%s", outPath, s_modeNames[test.modes[t]]);
|
bool residualCompression = (mode == Mode_BC3_RGBS);
|
||||||
FileSystem::createDirectory(outputFilePath.str());
|
if (residualCompression)
|
||||||
|
{
|
||||||
|
float residualScale = 8.0f;
|
||||||
|
nvtt::TexImage residual = diff;
|
||||||
|
for (int j = 0; j < 3; j++) {
|
||||||
|
residual.scaleBias(j, residualScale, 0.5); // @@ The residual scale is fairly arbitrary.
|
||||||
|
residual.clamp(j);
|
||||||
|
}
|
||||||
|
residual.toGreyScale(1, 1, 1, 0);
|
||||||
|
|
||||||
|
/*outputFileName.format("%s/%s", outputFilePath.str(), set.fileNames[i]);
|
||||||
|
outputFileName.stripExtension();
|
||||||
|
outputFileName.append("_residual.png");
|
||||||
|
residual.save(outputFileName.str());*/
|
||||||
|
|
||||||
|
nvtt::CompressionOptions residualCompressionOptions;
|
||||||
|
residualCompressionOptions.setFormat(nvtt::Format_BC4);
|
||||||
|
residualCompressionOptions.setQuality(nvtt::Quality_Production);
|
||||||
|
|
||||||
|
context.compress(residual, 0, 0, compressionOptions, outputOptions);
|
||||||
|
|
||||||
|
nvtt::TexImage residual_out = outputHandler.decompress(mode, format, decoder);
|
||||||
|
|
||||||
|
/*outputFileName.format("%s/%s", outputFilePath.str(), set.fileNames[i]);
|
||||||
|
outputFileName.stripExtension();
|
||||||
|
outputFileName.append("_residual_out.png");
|
||||||
|
residual_out.save(outputFileName.str());*/
|
||||||
|
|
||||||
|
residual_out.scaleBias(0, 1.0f/residualScale, -0.5f/residualScale);
|
||||||
|
residual_out.scaleBias(1, 1.0f/residualScale, -0.5f/residualScale);
|
||||||
|
residual_out.scaleBias(2, 1.0f/residualScale, -0.5f/residualScale);
|
||||||
|
|
||||||
|
img_out.addChannel(residual_out, 0, 0, -1.0f); img_out.clamp(0);
|
||||||
|
img_out.addChannel(residual_out, 1, 1, -1.0f); img_out.clamp(1);
|
||||||
|
img_out.addChannel(residual_out, 2, 2, -1.0f); img_out.clamp(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (set.type == ImageType_HDR)
|
||||||
|
{
|
||||||
|
Path outputFileName;
|
||||||
|
outputFileName.format("%s/%s", outPath, set.fileNames[i]);
|
||||||
|
outputFileName.stripExtension();
|
||||||
|
if (set.type == ImageType_HDR) outputFileName.append(".dds");
|
||||||
|
else outputFileName.append(".png");
|
||||||
|
if (!img.save(outputFileName.str()))
|
||||||
|
{
|
||||||
|
printf("Error saving file '%s'.\n", outputFileName.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output compressed image.
|
||||||
Path outputFileName;
|
Path outputFileName;
|
||||||
outputFileName.format("%s/%s", outputFilePath.str(), set.fileNames[i]);
|
outputFileName.format("%s/%s", outputFilePath.str(), set.fileNames[i]);
|
||||||
outputFileName.stripExtension();
|
outputFileName.stripExtension();
|
||||||
if (mode == Mode_BC3_Lightmap_1 || mode == Mode_BC3_Lightmap_2) {
|
if (set.type == ImageType_HDR) outputFileName.append(".dds");
|
||||||
outputFileName.append(".dds");
|
else outputFileName.append(".png");
|
||||||
}
|
|
||||||
else {
|
|
||||||
outputFileName.append(".png");
|
|
||||||
}
|
|
||||||
if (!img_out.save(outputFileName.str()))
|
if (!img_out.save(outputFileName.str()))
|
||||||
{
|
{
|
||||||
printf("Error saving file '%s'.\n", outputFileName.str());
|
printf("Error saving file '%s'.\n", outputFileName.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Output RMSE.
|
||||||
float rmse = nvtt::rmsError(img, img_out);
|
float rmse = nvtt::rmsError(img, img_out);
|
||||||
|
if (set.type == ImageType_HDR) rmse *= 4;
|
||||||
totalRMSE += rmse;
|
totalRMSE += rmse;
|
||||||
|
printf(" RMSE: \t%.4f\n", rmse);
|
||||||
|
|
||||||
|
float deltae = nvtt::cieLabError(img, img_out);
|
||||||
|
totalDeltaE += deltae;
|
||||||
|
printf(" CIE-Lab DeltaE:\t%.4f\n", deltae);
|
||||||
|
|
||||||
printf(" RMSE: \t%.4f\n", rmse);
|
|
||||||
|
|
||||||
graphWriter << rmse;
|
graphWriter << rmse;
|
||||||
|
//graphWriter << deltae;
|
||||||
if (i != set.fileCount-1) graphWriter << ",";
|
if (i != set.fileCount-1) graphWriter << ",";
|
||||||
|
|
||||||
|
|
||||||
|
// Output diff.
|
||||||
|
for (int j = 0; j < 3; j++) {
|
||||||
|
diff.scaleBias(j, 4.0f, 0.0f);
|
||||||
|
diff.abs(j);
|
||||||
|
diff.clamp(j);
|
||||||
|
}
|
||||||
|
|
||||||
|
outputFileName.format("%s/%s", outputFilePath.str(), set.fileNames[i]);
|
||||||
outputFileName.stripExtension();
|
outputFileName.stripExtension();
|
||||||
outputFileName.append("_diff.png");
|
outputFileName.append("_diff.png");
|
||||||
nvtt::diff(img, img_out, 4.0f).save(outputFileName.str());
|
diff.save(outputFileName.str());
|
||||||
|
|
||||||
|
|
||||||
// Output csv file
|
// Output csv file
|
||||||
@ -701,11 +823,13 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
totalRMSE /= set.fileCount;
|
totalRMSE /= set.fileCount;
|
||||||
totalDiff /= set.fileCount;
|
totalDeltaE /= set.fileCount;
|
||||||
|
//totalDiff /= set.fileCount;
|
||||||
|
|
||||||
printf("Total Results:\n");
|
printf("Total Results:\n");
|
||||||
printf(" Total Time: \t%.3f sec\n", totalTime);
|
printf(" Total Time: \t%.3f sec\n", totalTime);
|
||||||
printf(" Average RMSE:\t%.4f\n", totalRMSE);
|
printf(" Average RMSE: \t%.4f\n", totalRMSE);
|
||||||
|
printf(" Average CIE-Lab DeltaE:\t%.4f\n", totalDeltaE);
|
||||||
|
|
||||||
if (t != test.count-1) graphWriter << "|";
|
if (t != test.count-1) graphWriter << "|";
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user