Add support for 3D texture. Integrate patch provided in issue 28 plus some additional changes.
This commit is contained in:
@ -33,7 +33,7 @@ namespace nv
|
||||
struct CompressorInterface
|
||||
{
|
||||
virtual ~CompressorInterface() {}
|
||||
virtual void compress(nvtt::AlphaMode alphaMode, uint w, uint h, const float * rgba, nvtt::TaskDispatcher * dispatcher, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions) = 0;
|
||||
virtual void compress(nvtt::AlphaMode alphaMode, uint w, uint h, uint d, const float * rgba, nvtt::TaskDispatcher * dispatcher, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions) = 0;
|
||||
};
|
||||
|
||||
} // nv namespace
|
||||
|
@ -301,214 +301,132 @@ void NormalCompressorDXT5n::compressBlock(ColorBlock & rgba, nvtt::AlphaMode alp
|
||||
}
|
||||
|
||||
|
||||
#if defined(HAVE_S3QUANT)
|
||||
|
||||
void S3CompressorDXT1::compress(nvtt::InputFormat inputFormat, nvtt::AlphaMode alphaMode, uint w, uint h, void * data, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions)
|
||||
{
|
||||
float error = 0.0f;
|
||||
|
||||
BlockDXT1 dxtBlock3;
|
||||
BlockDXT1 dxtBlock4;
|
||||
ColorBlock block;
|
||||
|
||||
for (uint y = 0; y < h; y += 4) {
|
||||
for (uint x = 0; x < w; x += 4) {
|
||||
block.init(inputFormat, w, h, data, x, y);
|
||||
|
||||
// Init rgb block.
|
||||
RGBBlock rgbBlock;
|
||||
rgbBlock.n = 16;
|
||||
for (uint i = 0; i < 16; i++) {
|
||||
rgbBlock.colorChannel[i][0] = clamp(float(block.color(i).r) / 255.0f, 0.0f, 1.0f);
|
||||
rgbBlock.colorChannel[i][1] = clamp(float(block.color(i).g) / 255.0f, 0.0f, 1.0f);
|
||||
rgbBlock.colorChannel[i][2] = clamp(float(block.color(i).b) / 255.0f, 0.0f, 1.0f);
|
||||
}
|
||||
rgbBlock.weight[0] = 1.0f;
|
||||
rgbBlock.weight[1] = 1.0f;
|
||||
rgbBlock.weight[2] = 1.0f;
|
||||
|
||||
rgbBlock.inLevel = 4;
|
||||
CodeRGBBlock(&rgbBlock);
|
||||
|
||||
// Copy results to DXT block.
|
||||
dxtBlock4.col0.r = rgbBlock.endPoint[0][0];
|
||||
dxtBlock4.col0.g = rgbBlock.endPoint[0][1];
|
||||
dxtBlock4.col0.b = rgbBlock.endPoint[0][2];
|
||||
|
||||
dxtBlock4.col1.r = rgbBlock.endPoint[1][0];
|
||||
dxtBlock4.col1.g = rgbBlock.endPoint[1][1];
|
||||
dxtBlock4.col1.b = rgbBlock.endPoint[1][2];
|
||||
|
||||
dxtBlock4.setIndices(rgbBlock.index);
|
||||
|
||||
if (dxtBlock4.col0.u < dxtBlock4.col1.u) {
|
||||
swap(dxtBlock4.col0.u, dxtBlock4.col1.u);
|
||||
dxtBlock4.indices ^= 0x55555555;
|
||||
}
|
||||
|
||||
uint error4 = blockError(block, dxtBlock4);
|
||||
|
||||
rgbBlock.inLevel = 3;
|
||||
|
||||
CodeRGBBlock(&rgbBlock);
|
||||
|
||||
// Copy results to DXT block.
|
||||
dxtBlock3.col0.r = rgbBlock.endPoint[0][0];
|
||||
dxtBlock3.col0.g = rgbBlock.endPoint[0][1];
|
||||
dxtBlock3.col0.b = rgbBlock.endPoint[0][2];
|
||||
|
||||
dxtBlock3.col1.r = rgbBlock.endPoint[1][0];
|
||||
dxtBlock3.col1.g = rgbBlock.endPoint[1][1];
|
||||
dxtBlock3.col1.b = rgbBlock.endPoint[1][2];
|
||||
|
||||
dxtBlock3.setIndices(rgbBlock.index);
|
||||
|
||||
if (dxtBlock3.col0.u > dxtBlock3.col1.u) {
|
||||
swap(dxtBlock3.col0.u, dxtBlock3.col1.u);
|
||||
dxtBlock3.indices ^= (~dxtBlock3.indices >> 1) & 0x55555555;
|
||||
}
|
||||
|
||||
uint error3 = blockError(block, dxtBlock3);
|
||||
|
||||
if (error3 < error4) {
|
||||
error += error3;
|
||||
|
||||
if (outputOptions.outputHandler != NULL) {
|
||||
outputOptions.outputHandler->writeData(&dxtBlock3, sizeof(dxtBlock3));
|
||||
}
|
||||
}
|
||||
else {
|
||||
error += error4;
|
||||
|
||||
if (outputOptions.outputHandler != NULL) {
|
||||
outputOptions.outputHandler->writeData(&dxtBlock4, sizeof(dxtBlock4));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // defined(HAVE_S3QUANT)
|
||||
|
||||
|
||||
#if defined(HAVE_ATITC)
|
||||
|
||||
void AtiCompressorDXT1::compress(nvtt::InputFormat inputFormat, nvtt::AlphaMode alphaMode, uint w, uint h, void * data, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions)
|
||||
void AtiCompressorDXT1::compress(nvtt::InputFormat inputFormat, nvtt::AlphaMode alphaMode, uint w, uint h, uint d, void * data, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions)
|
||||
{
|
||||
// Init source texture
|
||||
ATI_TC_Texture srcTexture;
|
||||
srcTexture.dwSize = sizeof(srcTexture);
|
||||
srcTexture.dwWidth = w;
|
||||
srcTexture.dwHeight = h;
|
||||
if (inputFormat == nvtt::InputFormat_BGRA_8UB)
|
||||
{
|
||||
srcTexture.dwPitch = w * 4;
|
||||
srcTexture.format = ATI_TC_FORMAT_ARGB_8888;
|
||||
}
|
||||
else
|
||||
{
|
||||
srcTexture.dwPitch = w * 16;
|
||||
srcTexture.format = ATI_TC_FORMAT_ARGB_32F;
|
||||
}
|
||||
srcTexture.dwDataSize = ATI_TC_CalculateBufferSize(&srcTexture);
|
||||
srcTexture.pData = (ATI_TC_BYTE*) data;
|
||||
nvDebugCheck(d == 1);
|
||||
|
||||
// Init dest texture
|
||||
ATI_TC_Texture destTexture;
|
||||
destTexture.dwSize = sizeof(destTexture);
|
||||
destTexture.dwWidth = w;
|
||||
destTexture.dwHeight = h;
|
||||
destTexture.dwPitch = 0;
|
||||
destTexture.format = ATI_TC_FORMAT_DXT1;
|
||||
destTexture.dwDataSize = ATI_TC_CalculateBufferSize(&destTexture);
|
||||
destTexture.pData = (ATI_TC_BYTE*) mem::malloc(destTexture.dwDataSize);
|
||||
// Init source texture
|
||||
ATI_TC_Texture srcTexture;
|
||||
srcTexture.dwSize = sizeof(srcTexture);
|
||||
srcTexture.dwWidth = w;
|
||||
srcTexture.dwHeight = h;
|
||||
if (inputFormat == nvtt::InputFormat_BGRA_8UB)
|
||||
{
|
||||
srcTexture.dwPitch = w * 4;
|
||||
srcTexture.format = ATI_TC_FORMAT_ARGB_8888;
|
||||
}
|
||||
else
|
||||
{
|
||||
// @@ Floating point input is not swizzled.
|
||||
srcTexture.dwPitch = w * 16;
|
||||
srcTexture.format = ATI_TC_FORMAT_ARGB_32F;
|
||||
}
|
||||
srcTexture.dwDataSize = ATI_TC_CalculateBufferSize(&srcTexture);
|
||||
srcTexture.pData = (ATI_TC_BYTE*) data;
|
||||
|
||||
ATI_TC_CompressOptions options;
|
||||
options.dwSize = sizeof(options);
|
||||
options.bUseChannelWeighting = false;
|
||||
options.bUseAdaptiveWeighting = false;
|
||||
options.bDXT1UseAlpha = false;
|
||||
options.nCompressionSpeed = ATI_TC_Speed_Normal;
|
||||
options.bDisableMultiThreading = false;
|
||||
//options.bDisableMultiThreading = true;
|
||||
// Init dest texture
|
||||
ATI_TC_Texture destTexture;
|
||||
destTexture.dwSize = sizeof(destTexture);
|
||||
destTexture.dwWidth = w;
|
||||
destTexture.dwHeight = h;
|
||||
destTexture.dwPitch = 0;
|
||||
destTexture.format = ATI_TC_FORMAT_DXT1;
|
||||
destTexture.dwDataSize = ATI_TC_CalculateBufferSize(&destTexture);
|
||||
destTexture.pData = (ATI_TC_BYTE*) mem::malloc(destTexture.dwDataSize);
|
||||
|
||||
// Compress
|
||||
ATI_TC_ConvertTexture(&srcTexture, &destTexture, &options, NULL, NULL, NULL);
|
||||
ATI_TC_CompressOptions options;
|
||||
options.dwSize = sizeof(options);
|
||||
options.bUseChannelWeighting = false;
|
||||
options.bUseAdaptiveWeighting = false;
|
||||
options.bDXT1UseAlpha = false;
|
||||
options.nCompressionSpeed = ATI_TC_Speed_Normal;
|
||||
options.bDisableMultiThreading = false;
|
||||
//options.bDisableMultiThreading = true;
|
||||
|
||||
if (outputOptions.outputHandler != NULL) {
|
||||
outputOptions.outputHandler->writeData(destTexture.pData, destTexture.dwDataSize);
|
||||
}
|
||||
// Compress
|
||||
ATI_TC_ConvertTexture(&srcTexture, &destTexture, &options, NULL, NULL, NULL);
|
||||
|
||||
mem::free(destTexture.pData);
|
||||
if (outputOptions.outputHandler != NULL) {
|
||||
outputOptions.outputHandler->writeData(destTexture.pData, destTexture.dwDataSize);
|
||||
}
|
||||
|
||||
mem::free(destTexture.pData);
|
||||
}
|
||||
|
||||
void AtiCompressorDXT5::compress(nvtt::InputFormat inputFormat, nvtt::AlphaMode alphaMode, uint w, uint h, void * data, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions)
|
||||
void AtiCompressorDXT5::compress(nvtt::InputFormat inputFormat, nvtt::AlphaMode alphaMode, uint w, uint h, uint d, void * data, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions)
|
||||
{
|
||||
// Init source texture
|
||||
ATI_TC_Texture srcTexture;
|
||||
srcTexture.dwSize = sizeof(srcTexture);
|
||||
srcTexture.dwWidth = w;
|
||||
srcTexture.dwHeight = h;
|
||||
if (inputFormat == nvtt::InputFormat_BGRA_8UB)
|
||||
{
|
||||
srcTexture.dwPitch = w * 4;
|
||||
srcTexture.format = ATI_TC_FORMAT_ARGB_8888;
|
||||
}
|
||||
else
|
||||
{
|
||||
srcTexture.dwPitch = w * 16;
|
||||
srcTexture.format = ATI_TC_FORMAT_ARGB_32F;
|
||||
}
|
||||
srcTexture.dwDataSize = ATI_TC_CalculateBufferSize(&srcTexture);
|
||||
srcTexture.pData = (ATI_TC_BYTE*) data;
|
||||
nvDebugCheck(d == 1);
|
||||
|
||||
// Init dest texture
|
||||
ATI_TC_Texture destTexture;
|
||||
destTexture.dwSize = sizeof(destTexture);
|
||||
destTexture.dwWidth = w;
|
||||
destTexture.dwHeight = h;
|
||||
destTexture.dwPitch = 0;
|
||||
destTexture.format = ATI_TC_FORMAT_DXT5;
|
||||
destTexture.dwDataSize = ATI_TC_CalculateBufferSize(&destTexture);
|
||||
destTexture.pData = (ATI_TC_BYTE*) mem::malloc(destTexture.dwDataSize);
|
||||
// Init source texture
|
||||
ATI_TC_Texture srcTexture;
|
||||
srcTexture.dwSize = sizeof(srcTexture);
|
||||
srcTexture.dwWidth = w;
|
||||
srcTexture.dwHeight = h;
|
||||
if (inputFormat == nvtt::InputFormat_BGRA_8UB)
|
||||
{
|
||||
srcTexture.dwPitch = w * 4;
|
||||
srcTexture.format = ATI_TC_FORMAT_ARGB_8888;
|
||||
}
|
||||
else
|
||||
{
|
||||
srcTexture.dwPitch = w * 16;
|
||||
srcTexture.format = ATI_TC_FORMAT_ARGB_32F;
|
||||
}
|
||||
srcTexture.dwDataSize = ATI_TC_CalculateBufferSize(&srcTexture);
|
||||
srcTexture.pData = (ATI_TC_BYTE*) data;
|
||||
|
||||
// Compress
|
||||
ATI_TC_ConvertTexture(&srcTexture, &destTexture, NULL, NULL, NULL, NULL);
|
||||
// Init dest texture
|
||||
ATI_TC_Texture destTexture;
|
||||
destTexture.dwSize = sizeof(destTexture);
|
||||
destTexture.dwWidth = w;
|
||||
destTexture.dwHeight = h;
|
||||
destTexture.dwPitch = 0;
|
||||
destTexture.format = ATI_TC_FORMAT_DXT5;
|
||||
destTexture.dwDataSize = ATI_TC_CalculateBufferSize(&destTexture);
|
||||
destTexture.pData = (ATI_TC_BYTE*) mem::malloc(destTexture.dwDataSize);
|
||||
|
||||
if (outputOptions.outputHandler != NULL) {
|
||||
outputOptions.outputHandler->writeData(destTexture.pData, destTexture.dwDataSize);
|
||||
}
|
||||
// Compress
|
||||
ATI_TC_ConvertTexture(&srcTexture, &destTexture, NULL, NULL, NULL, NULL);
|
||||
|
||||
mem::free(destTexture.pData);
|
||||
if (outputOptions.outputHandler != NULL) {
|
||||
outputOptions.outputHandler->writeData(destTexture.pData, destTexture.dwDataSize);
|
||||
}
|
||||
|
||||
mem::free(destTexture.pData);
|
||||
}
|
||||
|
||||
#endif // defined(HAVE_ATITC)
|
||||
|
||||
#if defined(HAVE_SQUISH)
|
||||
|
||||
void SquishCompressorDXT1::compress(nvtt::InputFormat inputFormat, nvtt::AlphaMode alphaMode, uint w, uint h, void * data, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions)
|
||||
void SquishCompressorDXT1::compress(nvtt::InputFormat inputFormat, nvtt::AlphaMode alphaMode, uint w, uint h, uint d, void * data, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions)
|
||||
{
|
||||
nvDebugCheck(d == 1);
|
||||
nvDebugCheck(false);
|
||||
|
||||
#pragma message(NV_FILE_LINE "TODO: Convert input to fixed point ABGR format instead of ARGB")
|
||||
/*
|
||||
Image img(*image);
|
||||
int count = img.width() * img.height();
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
Color32 c = img.pixel(i);
|
||||
img.pixel(i) = Color32(c.b, c.g, c.r, c.a);
|
||||
}
|
||||
/*
|
||||
Image img(*image);
|
||||
int count = img.width() * img.height();
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
Color32 c = img.pixel(i);
|
||||
img.pixel(i) = Color32(c.b, c.g, c.r, c.a);
|
||||
}
|
||||
|
||||
int size = squish::GetStorageRequirements(img.width(), img.height(), squish::kDxt1);
|
||||
void * blocks = mem::malloc(size);
|
||||
int size = squish::GetStorageRequirements(img.width(), img.height(), squish::kDxt1);
|
||||
void * blocks = mem::malloc(size);
|
||||
|
||||
squish::CompressImage((const squish::u8 *)img.pixels(), img.width(), img.height(), blocks, squish::kDxt1 | squish::kColourClusterFit);
|
||||
squish::CompressImage((const squish::u8 *)img.pixels(), img.width(), img.height(), blocks, squish::kDxt1 | squish::kColourClusterFit);
|
||||
|
||||
if (outputOptions.outputHandler != NULL) {
|
||||
outputOptions.outputHandler->writeData(blocks, size);
|
||||
}
|
||||
if (outputOptions.outputHandler != NULL) {
|
||||
outputOptions.outputHandler->writeData(blocks, size);
|
||||
}
|
||||
|
||||
mem::free(blocks);
|
||||
*/
|
||||
mem::free(blocks);
|
||||
*/
|
||||
}
|
||||
|
||||
#endif // defined(HAVE_SQUISH)
|
||||
@ -516,62 +434,64 @@ void SquishCompressorDXT1::compress(nvtt::InputFormat inputFormat, nvtt::AlphaMo
|
||||
|
||||
#if defined(HAVE_D3DX)
|
||||
|
||||
void D3DXCompressorDXT1::compress(nvtt::InputFormat inputFormat, nvtt::AlphaMode alphaMode, uint w, uint h, void * data, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions)
|
||||
void D3DXCompressorDXT1::compress(nvtt::InputFormat inputFormat, nvtt::AlphaMode alphaMode, uint w, uint h, uint d, void * data, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions)
|
||||
{
|
||||
IDirect3D9 * d3d = Direct3DCreate9(D3D_SDK_VERSION);
|
||||
nvDebugCheck(d == 1);
|
||||
|
||||
D3DPRESENT_PARAMETERS presentParams;
|
||||
ZeroMemory(&presentParams, sizeof(presentParams));
|
||||
presentParams.Windowed = TRUE;
|
||||
presentParams.SwapEffect = D3DSWAPEFFECT_COPY;
|
||||
presentParams.BackBufferWidth = 8;
|
||||
presentParams.BackBufferHeight = 8;
|
||||
presentParams.BackBufferFormat = D3DFMT_UNKNOWN;
|
||||
IDirect3D9 * d3d = Direct3DCreate9(D3D_SDK_VERSION);
|
||||
|
||||
HRESULT err;
|
||||
D3DPRESENT_PARAMETERS presentParams;
|
||||
ZeroMemory(&presentParams, sizeof(presentParams));
|
||||
presentParams.Windowed = TRUE;
|
||||
presentParams.SwapEffect = D3DSWAPEFFECT_COPY;
|
||||
presentParams.BackBufferWidth = 8;
|
||||
presentParams.BackBufferHeight = 8;
|
||||
presentParams.BackBufferFormat = D3DFMT_UNKNOWN;
|
||||
|
||||
IDirect3DDevice9 * device = NULL;
|
||||
err = d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, GetDesktopWindow(), D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParams, &device);
|
||||
HRESULT err;
|
||||
|
||||
IDirect3DTexture9 * texture = NULL;
|
||||
err = D3DXCreateTexture(device, w, h, 1, 0, D3DFMT_DXT1, D3DPOOL_SYSTEMMEM, &texture);
|
||||
|
||||
IDirect3DSurface9 * surface = NULL;
|
||||
err = texture->GetSurfaceLevel(0, &surface);
|
||||
IDirect3DDevice9 * device = NULL;
|
||||
err = d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, GetDesktopWindow(), D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParams, &device);
|
||||
|
||||
RECT rect;
|
||||
rect.left = 0;
|
||||
rect.top = 0;
|
||||
rect.bottom = h;
|
||||
rect.right = w;
|
||||
IDirect3DTexture9 * texture = NULL;
|
||||
err = D3DXCreateTexture(device, w, h, 1, 0, D3DFMT_DXT1, D3DPOOL_SYSTEMMEM, &texture);
|
||||
|
||||
if (inputFormat == nvtt::InputFormat_BGRA_8UB)
|
||||
{
|
||||
err = D3DXLoadSurfaceFromMemory(surface, NULL, NULL, data, D3DFMT_A8R8G8B8, w * 4, NULL, &rect, D3DX_DEFAULT, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
err = D3DXLoadSurfaceFromMemory(surface, NULL, NULL, data, D3DFMT_A32B32G32R32F, w * 16, NULL, &rect, D3DX_DEFAULT, 0);
|
||||
IDirect3DSurface9 * surface = NULL;
|
||||
err = texture->GetSurfaceLevel(0, &surface);
|
||||
|
||||
RECT rect;
|
||||
rect.left = 0;
|
||||
rect.top = 0;
|
||||
rect.bottom = h;
|
||||
rect.right = w;
|
||||
|
||||
if (inputFormat == nvtt::InputFormat_BGRA_8UB)
|
||||
{
|
||||
err = D3DXLoadSurfaceFromMemory(surface, NULL, NULL, data, D3DFMT_A8R8G8B8, w * 4, NULL, &rect, D3DX_DEFAULT, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
err = D3DXLoadSurfaceFromMemory(surface, NULL, NULL, data, D3DFMT_A32B32G32R32F, w * 16, NULL, &rect, D3DX_DEFAULT, 0);
|
||||
}
|
||||
|
||||
if (err != D3DERR_INVALIDCALL && err != D3DXERR_INVALIDDATA)
|
||||
{
|
||||
D3DLOCKED_RECT rect;
|
||||
ZeroMemory(&rect, sizeof(rect));
|
||||
|
||||
err = surface->LockRect(&rect, NULL, D3DLOCK_READONLY);
|
||||
|
||||
if (outputOptions.outputHandler != NULL) {
|
||||
int size = rect.Pitch * ((h + 3) / 4);
|
||||
outputOptions.outputHandler->writeData(rect.pBits, size);
|
||||
}
|
||||
|
||||
if (err != D3DERR_INVALIDCALL && err != D3DXERR_INVALIDDATA)
|
||||
{
|
||||
D3DLOCKED_RECT rect;
|
||||
ZeroMemory(&rect, sizeof(rect));
|
||||
err = surface->UnlockRect();
|
||||
}
|
||||
|
||||
err = surface->LockRect(&rect, NULL, D3DLOCK_READONLY);
|
||||
|
||||
if (outputOptions.outputHandler != NULL) {
|
||||
int size = rect.Pitch * ((h + 3) / 4);
|
||||
outputOptions.outputHandler->writeData(rect.pBits, size);
|
||||
}
|
||||
|
||||
err = surface->UnlockRect();
|
||||
}
|
||||
|
||||
surface->Release();
|
||||
device->Release();
|
||||
d3d->Release();
|
||||
surface->Release();
|
||||
device->Release();
|
||||
d3d->Release();
|
||||
}
|
||||
|
||||
#endif // defined(HAVE_D3DX)
|
||||
@ -581,8 +501,8 @@ void D3DXCompressorDXT1::compress(nvtt::InputFormat inputFormat, nvtt::AlphaMode
|
||||
|
||||
void StbCompressorDXT1::compressBlock(ColorBlock & rgba, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output)
|
||||
{
|
||||
rgba.swizzle(2, 1, 0, 3); // Swap R and B
|
||||
stb_compress_dxt_block((unsigned char *)output, (unsigned char *)rgba.colors(), 0, 0);
|
||||
rgba.swizzle(2, 1, 0, 3); // Swap R and B
|
||||
stb_compress_dxt_block((unsigned char *)output, (unsigned char *)rgba.colors(), 0, 0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -107,26 +107,26 @@ namespace nv
|
||||
#if defined(HAVE_ATITC)
|
||||
struct AtiCompressorDXT1 : public CompressorInterface
|
||||
{
|
||||
virtual void compress(nvtt::InputFormat inputFormat, nvtt::AlphaMode alphaMode, uint w, uint h, void * data, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions);
|
||||
virtual void compress(nvtt::InputFormat inputFormat, nvtt::AlphaMode alphaMode, uint w, uint h, uint d, void * data, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions);
|
||||
};
|
||||
|
||||
struct AtiCompressorDXT5 : public CompressorInterface
|
||||
{
|
||||
virtual void compress(nvtt::InputFormat inputFormat, nvtt::AlphaMode alphaMode, uint w, uint h, void * data, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions);
|
||||
virtual void compress(nvtt::InputFormat inputFormat, nvtt::AlphaMode alphaMode, uint w, uint h, uint d, void * data, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions);
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_SQUISH)
|
||||
struct SquishCompressorDXT1 : public CompressorInterface
|
||||
{
|
||||
virtual void compress(nvtt::InputFormat inputFormat, nvtt::AlphaMode alphaMode, uint w, uint h, void * data, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions);
|
||||
virtual void compress(nvtt::InputFormat inputFormat, nvtt::AlphaMode alphaMode, uint w, uint h, uint d, void * data, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions);
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_D3DX)
|
||||
struct D3DXCompressorDXT1 : public CompressorInterface
|
||||
{
|
||||
virtual void compress(nvtt::InputFormat inputFormat, nvtt::AlphaMode alphaMode, uint w, uint h, void * data, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions);
|
||||
virtual void compress(nvtt::InputFormat inputFormat, nvtt::AlphaMode alphaMode, uint w, uint h, uint d, void * data, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions);
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -143,8 +143,10 @@ void CompressorTask(void * data, int i)
|
||||
}
|
||||
}
|
||||
|
||||
void FixedBlockCompressor::compress(nvtt::AlphaMode alphaMode, uint w, uint h, const float * data, nvtt::TaskDispatcher * dispatcher, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions)
|
||||
void FixedBlockCompressor::compress(nvtt::AlphaMode alphaMode, uint w, uint h, uint d, const float * data, nvtt::TaskDispatcher * dispatcher, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions)
|
||||
{
|
||||
nvDebugCheck(d == 1);
|
||||
|
||||
CompressorContext context;
|
||||
context.alphaMode = alphaMode;
|
||||
context.w = w;
|
||||
@ -177,8 +179,10 @@ void FixedBlockCompressor::compress(nvtt::AlphaMode alphaMode, uint w, uint h, c
|
||||
|
||||
|
||||
|
||||
void ColorSetCompressor::compress(AlphaMode alphaMode, uint w, uint h, const float * data, nvtt::TaskDispatcher * dispatcher, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions)
|
||||
void ColorSetCompressor::compress(AlphaMode alphaMode, uint w, uint h, uint d, const float * data, nvtt::TaskDispatcher * dispatcher, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions)
|
||||
{
|
||||
nvDebugCheck(d == 1);
|
||||
|
||||
const uint bs = blockSize();
|
||||
const uint bw = (w + 3) / 4;
|
||||
const uint bh = (h + 3) / 4;
|
||||
|
@ -35,7 +35,7 @@ namespace nv
|
||||
|
||||
struct FixedBlockCompressor : public CompressorInterface
|
||||
{
|
||||
virtual void compress(nvtt::AlphaMode alphaMode, uint w, uint h, const float * rgba, nvtt::TaskDispatcher * dispatcher, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions);
|
||||
virtual void compress(nvtt::AlphaMode alphaMode, uint w, uint h, uint d, const float * rgba, nvtt::TaskDispatcher * dispatcher, 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 uint blockSize() const = 0;
|
||||
@ -43,7 +43,7 @@ namespace nv
|
||||
|
||||
struct ColorSetCompressor : public CompressorInterface
|
||||
{
|
||||
virtual void compress(nvtt::AlphaMode alphaMode, uint w, uint h, const float * rgba, nvtt::TaskDispatcher * dispatcher, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions);
|
||||
virtual void compress(nvtt::AlphaMode alphaMode, uint w, uint h, uint d, const float * rgba, nvtt::TaskDispatcher * dispatcher, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions);
|
||||
|
||||
virtual void compressBlock(ColorSet & set, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output) = 0;
|
||||
virtual uint blockSize() const = 0;
|
||||
|
@ -26,14 +26,14 @@
|
||||
#include "CompressionOptions.h"
|
||||
#include "OutputOptions.h"
|
||||
|
||||
#include <nvimage/Image.h>
|
||||
#include <nvimage/FloatImage.h>
|
||||
#include <nvimage/PixelFormat.h>
|
||||
#include "nvimage/Image.h"
|
||||
#include "nvimage/FloatImage.h"
|
||||
#include "nvimage/PixelFormat.h"
|
||||
|
||||
#include <nvmath/Color.h>
|
||||
#include <nvmath/Half.h>
|
||||
#include "nvmath/Color.h"
|
||||
#include "nvmath/Half.h"
|
||||
|
||||
#include <nvcore/Debug.h>
|
||||
#include "nvcore/Debug.h"
|
||||
|
||||
using namespace nv;
|
||||
using namespace nvtt;
|
||||
@ -125,7 +125,7 @@ namespace
|
||||
|
||||
|
||||
|
||||
void PixelFormatConverter::compress(nvtt::AlphaMode /*alphaMode*/, uint w, uint h, const float * data, nvtt::TaskDispatcher * dispatcher, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions)
|
||||
void PixelFormatConverter::compress(nvtt::AlphaMode /*alphaMode*/, uint w, uint h, uint d, const float * data, nvtt::TaskDispatcher * dispatcher, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions)
|
||||
{
|
||||
nvDebugCheck (compressionOptions.format == nvtt::Format_RGBA);
|
||||
|
||||
@ -189,77 +189,68 @@ void PixelFormatConverter::compress(nvtt::AlphaMode /*alphaMode*/, uint w, uint
|
||||
}
|
||||
|
||||
const uint pitch = computeBytePitch(w, bitCount, compressionOptions.pitchAlignment);
|
||||
const uint wh = w * h;
|
||||
const uint whd = w * h * d;
|
||||
|
||||
// Allocate output scanline.
|
||||
uint8 * const dst = malloc<uint8>(pitch);
|
||||
|
||||
for (uint y = 0; y < h; y++)
|
||||
for (uint z = 0; z < d; z++)
|
||||
{
|
||||
const uint * src = (const uint *)data + y * w;
|
||||
const float * fsrc = (const float *)data + y * w;
|
||||
|
||||
BitStream stream(dst);
|
||||
|
||||
for (uint x = 0; x < w; x++)
|
||||
for (uint y = 0; y < h; y++)
|
||||
{
|
||||
float r = fsrc[x + 0 * wh];
|
||||
float g = fsrc[x + 1 * wh];
|
||||
float b = fsrc[x + 2 * wh];
|
||||
float a = fsrc[x + 3 * wh];
|
||||
const float * src = (const float *)data + y * w;
|
||||
|
||||
if (compressionOptions.pixelType == nvtt::PixelType_Float)
|
||||
BitStream stream(dst);
|
||||
|
||||
for (uint x = 0; x < w; x++)
|
||||
{
|
||||
if (rsize == 32) stream.putFloat(r);
|
||||
else if (rsize == 16) stream.putHalf(r);
|
||||
float r = src[x + 0 * whd];
|
||||
float g = src[x + 1 * whd];
|
||||
float b = src[x + 2 * whd];
|
||||
float a = src[x + 3 * whd];
|
||||
|
||||
if (gsize == 32) stream.putFloat(g);
|
||||
else if (gsize == 16) stream.putHalf(g);
|
||||
|
||||
if (bsize == 32) stream.putFloat(b);
|
||||
else if (bsize == 16) stream.putHalf(b);
|
||||
|
||||
if (asize == 32) stream.putFloat(a);
|
||||
else if (asize == 16) stream.putHalf(a);
|
||||
}
|
||||
else
|
||||
{
|
||||
Color32 c;
|
||||
if (compressionOptions.pixelType == nvtt::PixelType_UnsignedNorm) {
|
||||
c.r = uint8(clamp(r * 255, 0.0f, 255.0f));
|
||||
c.g = uint8(clamp(g * 255, 0.0f, 255.0f));
|
||||
c.b = uint8(clamp(b * 255, 0.0f, 255.0f));
|
||||
c.a = uint8(clamp(a * 255, 0.0f, 255.0f));
|
||||
}
|
||||
// @@ Add support for nvtt::PixelType_SignedInt, nvtt::PixelType_SignedNorm, nvtt::PixelType_UnsignedInt
|
||||
|
||||
uint p = 0;
|
||||
p |= PixelFormat::convert(c.r, 8, rsize) << rshift;
|
||||
p |= PixelFormat::convert(c.g, 8, gsize) << gshift;
|
||||
p |= PixelFormat::convert(c.b, 8, bsize) << bshift;
|
||||
p |= PixelFormat::convert(c.a, 8, asize) << ashift;
|
||||
|
||||
stream.putBits(p, bitCount);
|
||||
|
||||
// Output one byte at a time.
|
||||
/*for (uint i = 0; i < byteCount; i++)
|
||||
if (compressionOptions.pixelType == nvtt::PixelType_Float)
|
||||
{
|
||||
*(dst + x * byteCount + i) = (p >> (i * 8)) & 0xFF;
|
||||
}*/
|
||||
if (rsize == 32) stream.putFloat(r);
|
||||
else if (rsize == 16) stream.putHalf(r);
|
||||
|
||||
if (gsize == 32) stream.putFloat(g);
|
||||
else if (gsize == 16) stream.putHalf(g);
|
||||
|
||||
if (bsize == 32) stream.putFloat(b);
|
||||
else if (bsize == 16) stream.putHalf(b);
|
||||
|
||||
if (asize == 32) stream.putFloat(a);
|
||||
else if (asize == 16) stream.putHalf(a);
|
||||
}
|
||||
else
|
||||
{
|
||||
Color32 c;
|
||||
if (compressionOptions.pixelType == nvtt::PixelType_UnsignedNorm) {
|
||||
c.r = uint8(clamp(r * 255, 0.0f, 255.0f));
|
||||
c.g = uint8(clamp(g * 255, 0.0f, 255.0f));
|
||||
c.b = uint8(clamp(b * 255, 0.0f, 255.0f));
|
||||
c.a = uint8(clamp(a * 255, 0.0f, 255.0f));
|
||||
}
|
||||
// @@ Add support for nvtt::PixelType_SignedInt, nvtt::PixelType_SignedNorm, nvtt::PixelType_UnsignedInt
|
||||
|
||||
uint p = 0;
|
||||
p |= PixelFormat::convert(c.r, 8, rsize) << rshift;
|
||||
p |= PixelFormat::convert(c.g, 8, gsize) << gshift;
|
||||
p |= PixelFormat::convert(c.b, 8, bsize) << bshift;
|
||||
p |= PixelFormat::convert(c.a, 8, asize) << ashift;
|
||||
|
||||
stream.putBits(p, bitCount);
|
||||
}
|
||||
}
|
||||
|
||||
// Zero padding.
|
||||
stream.align(compressionOptions.pitchAlignment);
|
||||
nvDebugCheck(stream.ptr == dst + pitch);
|
||||
|
||||
// Scanlines are always byte-aligned.
|
||||
outputOptions.writeData(dst, pitch);
|
||||
}
|
||||
|
||||
// Zero padding.
|
||||
stream.align(compressionOptions.pitchAlignment);
|
||||
nvDebugCheck(stream.ptr == dst + pitch);
|
||||
|
||||
/*for (uint x = w * byteCount; x < pitch; x++)
|
||||
{
|
||||
*(dst + x) = 0;
|
||||
}*/
|
||||
|
||||
// @@ This code does not truly support less than byte-aligned textures.
|
||||
outputOptions.writeData(dst, pitch);
|
||||
}
|
||||
|
||||
free(dst);
|
||||
|
@ -31,7 +31,7 @@ namespace nv
|
||||
{
|
||||
struct PixelFormatConverter : public CompressorInterface
|
||||
{
|
||||
virtual void compress(nvtt::AlphaMode alphaMode, uint w, uint h, const float * data, nvtt::TaskDispatcher * dispatcher, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions);
|
||||
virtual void compress(nvtt::AlphaMode alphaMode, uint w, uint h, uint d, const float * data, nvtt::TaskDispatcher * dispatcher, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions);
|
||||
};
|
||||
|
||||
} // nv namespace
|
||||
|
@ -56,17 +56,17 @@ static Color32 toRgbe8(float r, float g, float b)
|
||||
}
|
||||
|
||||
|
||||
void CompressorRGBE::compress(nvtt::AlphaMode /*alphaMode*/, uint w, uint h, const float * data, nvtt::TaskDispatcher * dispatcher, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions)
|
||||
void CompressorRGBE::compress(nvtt::AlphaMode /*alphaMode*/, uint w, uint h, uint d, const float * data, nvtt::TaskDispatcher * dispatcher, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions)
|
||||
{
|
||||
nvDebugCheck (compressionOptions.format == nvtt::Format_RGBE);
|
||||
|
||||
uint srcPitch = w;
|
||||
uint srcPlane = w * h;
|
||||
uint srcPlane = w * h * d;
|
||||
|
||||
// Allocate output scanline.
|
||||
Color32 * dst = new Color32[w];
|
||||
|
||||
for (uint y = 0; y < h; y++)
|
||||
for (uint y = 0; y < h*d; y++)
|
||||
{
|
||||
const float * src = (const float *)data + y * srcPitch;
|
||||
|
||||
@ -75,14 +75,14 @@ void CompressorRGBE::compress(nvtt::AlphaMode /*alphaMode*/, uint w, uint h, con
|
||||
float r = src[x + 0 * srcPlane];
|
||||
float g = src[x + 1 * srcPlane];
|
||||
float b = src[x + 2 * srcPlane];
|
||||
|
||||
|
||||
dst[x] = toRgbe8(r, g, b);
|
||||
}
|
||||
|
||||
if (outputOptions.outputHandler != NULL)
|
||||
{
|
||||
outputOptions.outputHandler->writeData(dst, w * 4);
|
||||
}
|
||||
if (outputOptions.outputHandler != NULL)
|
||||
{
|
||||
outputOptions.outputHandler->writeData(dst, w * 4);
|
||||
}
|
||||
}
|
||||
|
||||
delete [] dst;
|
||||
|
@ -29,9 +29,9 @@
|
||||
namespace nv
|
||||
{
|
||||
struct CompressorRGBE : public CompressorInterface
|
||||
{
|
||||
virtual void compress(nvtt::AlphaMode alphaMode, uint w, uint h, const float * data, nvtt::TaskDispatcher * dispatcher, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions);
|
||||
};
|
||||
{
|
||||
virtual void compress(nvtt::AlphaMode alphaMode, uint w, uint h, uint d, const float * data, nvtt::TaskDispatcher * dispatcher, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions);
|
||||
};
|
||||
|
||||
} // nv namespace
|
||||
|
||||
|
@ -122,7 +122,12 @@ int Compressor::estimateSize(const InputOptions & inputOptions, const Compressio
|
||||
int d = inputOptions.m.depth;
|
||||
getTargetExtent(w, h, d, inputOptions.m.maxExtent, inputOptions.m.roundMode, inputOptions.m.textureType);
|
||||
|
||||
int mipmapCount = countMipmaps(w, h, d);
|
||||
int mipmapCount = 1;
|
||||
if (inputOptions.m.generateMipmaps) {
|
||||
mipmapCount = countMipmaps(w, h, d);
|
||||
if (inputOptions.m.maxLevel > 0) mipmapCount = min(mipmapCount, inputOptions.m.maxLevel);
|
||||
}
|
||||
|
||||
return inputOptions.m.faceCount * estimateSize(w, h, d, mipmapCount, compressionOptions);
|
||||
}
|
||||
|
||||
@ -130,7 +135,7 @@ int Compressor::estimateSize(const InputOptions & inputOptions, const Compressio
|
||||
// TexImage API.
|
||||
bool Compressor::outputHeader(const TexImage & tex, int mipmapCount, const CompressionOptions & compressionOptions, const OutputOptions & outputOptions) const
|
||||
{
|
||||
return m.outputHeader(TextureType_2D, tex.width(), tex.height(), tex.depth(), mipmapCount, tex.isNormalMap(), compressionOptions.m, outputOptions.m);
|
||||
return m.outputHeader(tex.type(), tex.width(), tex.height(), tex.depth(), mipmapCount, tex.isNormalMap(), compressionOptions.m, outputOptions.m);
|
||||
}
|
||||
|
||||
bool Compressor::compress(const TexImage & tex, int face, int mipmap, const CompressionOptions & compressionOptions, const OutputOptions & outputOptions) const
|
||||
@ -228,7 +233,7 @@ bool Compressor::Private::compress(const InputOptions::Private & inputOptions, c
|
||||
// Output images.
|
||||
for (int f = 0; f < faceCount; f++)
|
||||
{
|
||||
img.setImage2D(inputOptions.inputFormat, inputOptions.width, inputOptions.height, inputOptions.images[f]);
|
||||
img.setImage(inputOptions.inputFormat, inputOptions.width, inputOptions.height, inputOptions.depth, inputOptions.images[f]);
|
||||
|
||||
// To normal map.
|
||||
if (inputOptions.convertToNormalMap) {
|
||||
@ -242,7 +247,7 @@ bool Compressor::Private::compress(const InputOptions::Private & inputOptions, c
|
||||
}
|
||||
|
||||
// Resize input.
|
||||
img.resize(w, h, ResizeFilter_Box);
|
||||
img.resize(w, h, d, ResizeFilter_Box);
|
||||
|
||||
nvtt::TexImage tmp = img;
|
||||
if (!img.isNormalMap()) {
|
||||
@ -269,7 +274,12 @@ bool Compressor::Private::compress(const InputOptions::Private & inputOptions, c
|
||||
}
|
||||
|
||||
if (useSourceImages) {
|
||||
img.setImage2D(inputOptions.inputFormat, w, h, inputOptions.images[idx]);
|
||||
img.setImage(inputOptions.inputFormat, w, h, d, inputOptions.images[idx]);
|
||||
|
||||
// For already generated mipmaps, we need to convert to linear.
|
||||
if (!img.isNormalMap()) {
|
||||
img.toLinear(inputOptions.inputGamma);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (inputOptions.mipmapFilter == MipmapFilter_Kaiser) {
|
||||
@ -282,6 +292,7 @@ bool Compressor::Private::compress(const InputOptions::Private & inputOptions, c
|
||||
}
|
||||
nvDebugCheck(img.width() == w);
|
||||
nvDebugCheck(img.height() == h);
|
||||
nvDebugCheck(img.depth() == d);
|
||||
|
||||
if (img.isNormalMap()) {
|
||||
if (inputOptions.normalizeMipmaps) {
|
||||
@ -313,7 +324,7 @@ bool Compressor::Private::compress(const TexImage & tex, int face, int mipmap, c
|
||||
|
||||
bool Compressor::Private::compress(AlphaMode alphaMode, int w, int h, int d, int face, int mipmap, const float * rgba, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const
|
||||
{
|
||||
int size = computeImageSize(w, h, d, compressionOptions.bitcount, compressionOptions.pitchAlignment, compressionOptions.format);
|
||||
int size = computeImageSize(w, h, d, compressionOptions.getBitCount(), compressionOptions.pitchAlignment, compressionOptions.format);
|
||||
outputOptions.beginImage(size, w, h, d, face, mipmap);
|
||||
|
||||
// Decide what compressor to use.
|
||||
@ -335,7 +346,7 @@ bool Compressor::Private::compress(AlphaMode alphaMode, int w, int h, int d, int
|
||||
}
|
||||
else
|
||||
{
|
||||
compressor->compress(alphaMode, w, h, rgba, dispatcher, compressionOptions, outputOptions);
|
||||
compressor->compress(alphaMode, w, h, d, rgba, dispatcher, compressionOptions, outputOptions);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -393,10 +404,10 @@ bool Compressor::Private::outputHeader(nvtt::TextureType textureType, int w, int
|
||||
else if (textureType == TextureType_Cube) {
|
||||
header.setTextureCube();
|
||||
}
|
||||
/*else if (textureType == TextureType_3D) {
|
||||
else if (textureType == TextureType_3D) {
|
||||
header.setTexture3D();
|
||||
header.setDepth(d);
|
||||
}*/
|
||||
}
|
||||
|
||||
header.setWidth(w);
|
||||
header.setHeight(h);
|
||||
@ -408,10 +419,7 @@ bool Compressor::Private::outputHeader(nvtt::TextureType textureType, int w, int
|
||||
{
|
||||
if (compressionOptions.format == Format_RGBA)
|
||||
{
|
||||
int bitcount = compressionOptions.bitcount;
|
||||
if (bitcount == 0) {
|
||||
bitcount = compressionOptions.rsize + compressionOptions.gsize + compressionOptions.bsize + compressionOptions.asize;
|
||||
}
|
||||
const uint bitcount = compressionOptions.getBitCount();
|
||||
|
||||
if (bitcount == 16)
|
||||
{
|
||||
|
@ -176,9 +176,6 @@ void InputOptions::resetTextureLayout()
|
||||
// Copies the data to our internal structures.
|
||||
bool InputOptions::setMipmapData(const void * data, int width, int height, int depth /*= 1*/, int face /*= 0*/, int mipLevel /*= 0*/)
|
||||
{
|
||||
if (depth != 1) {
|
||||
return false;
|
||||
}
|
||||
if (uint(face) >= m.faceCount) {
|
||||
return false;
|
||||
}
|
||||
|
@ -115,6 +115,7 @@ uint nv::computeImageSize(uint w, uint h, uint d, uint bitCount, uint pitchAlign
|
||||
return d * h * computeBytePitch(w, bitCount, pitchAlignmentInBytes);
|
||||
}
|
||||
else {
|
||||
nvDebugCheck(d == 1);
|
||||
// @@ Handle 3D textures. DXT and VTC have different behaviors.
|
||||
return ((w + 3) / 4) * ((h + 3) / 4) * blockSize(format);
|
||||
}
|
||||
@ -253,7 +254,7 @@ int TexImage::height() const
|
||||
|
||||
int TexImage::depth() const
|
||||
{
|
||||
if (m->image != NULL) return 1;
|
||||
if (m->image != NULL) return m->image->depth();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -272,6 +273,11 @@ bool TexImage::isNormalMap() const
|
||||
return m->isNormalMap;
|
||||
}
|
||||
|
||||
TextureType TexImage::type() const
|
||||
{
|
||||
return m->type;
|
||||
}
|
||||
|
||||
int TexImage::countMipmaps() const
|
||||
{
|
||||
if (m->image == NULL) return 0;
|
||||
@ -338,7 +344,7 @@ void TexImage::histogram(int channel, float rangeMin, float rangeMax, int binCou
|
||||
float scale = float(binCount) / rangeMax;
|
||||
float bias = - scale * rangeMin;
|
||||
|
||||
const uint count = m->image->width() * m->image->height();
|
||||
const uint count = m->image->pixelCount();
|
||||
for (uint i = 0; i < count; i++) {
|
||||
float f = c[i] * scale + bias;
|
||||
int idx = ifloor(f);
|
||||
@ -355,7 +361,7 @@ void TexImage::range(int channel, float * rangeMin, float * rangeMax)
|
||||
FloatImage * img = m->image;
|
||||
float * c = img->channel(channel);
|
||||
|
||||
const uint count = img->width() * img->height();
|
||||
const uint count = img->pixelCount();
|
||||
for (uint p = 0; p < count; p++) {
|
||||
float f = c[p];
|
||||
if (f < range.x) range.x = f;
|
||||
@ -378,7 +384,7 @@ bool TexImage::load(const char * fileName, bool * hasAlpha/*= NULL*/)
|
||||
detach();
|
||||
|
||||
if (hasAlpha != NULL) {
|
||||
*hasAlpha = (img->componentNum() == 4);
|
||||
*hasAlpha = (img->componentCount() == 4);
|
||||
}
|
||||
|
||||
// @@ Have loadFloat allocate the image with the desired number of channels.
|
||||
@ -400,16 +406,17 @@ bool TexImage::save(const char * fileName) const
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TexImage::setImage2D(nvtt::InputFormat format, int w, int h, const void * data)
|
||||
bool TexImage::setImage(nvtt::InputFormat format, int w, int h, int d, const void * data)
|
||||
{
|
||||
detach();
|
||||
|
||||
if (m->image == NULL) {
|
||||
m->image = new FloatImage();
|
||||
}
|
||||
m->image->allocate(4, w, h);
|
||||
m->image->allocate(4, w, h, d);
|
||||
m->type = (d == 1) ? TextureType_2D : TextureType_3D;
|
||||
|
||||
const int count = w * h;
|
||||
const int count = m->image->pixelCount();
|
||||
|
||||
float * rdst = m->image->channel(0);
|
||||
float * gdst = m->image->channel(1);
|
||||
@ -471,16 +478,17 @@ bool TexImage::setImage2D(nvtt::InputFormat format, int w, int h, const void * d
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TexImage::setImage2D(InputFormat format, int w, int h, const void * r, const void * g, const void * b, const void * a)
|
||||
bool TexImage::setImage(InputFormat format, int w, int h, int d, const void * r, const void * g, const void * b, const void * a)
|
||||
{
|
||||
detach();
|
||||
|
||||
if (m->image == NULL) {
|
||||
m->image = new FloatImage();
|
||||
}
|
||||
m->image->allocate(4, w, h);
|
||||
m->image->allocate(4, w, h, d);
|
||||
m->type = (d == 1) ? TextureType_2D : TextureType_3D;
|
||||
|
||||
const int count = w * h;
|
||||
const int count = m->image->pixelCount();
|
||||
|
||||
float * rdst = m->image->channel(0);
|
||||
float * gdst = m->image->channel(1);
|
||||
@ -542,6 +550,7 @@ bool TexImage::setImage2D(InputFormat format, int w, int h, const void * r, cons
|
||||
return true;
|
||||
}
|
||||
|
||||
// @@ Add support for compressed 3D textures.
|
||||
bool TexImage::setImage2D(Format format, Decoder decoder, int w, int h, const void * data)
|
||||
{
|
||||
if (format != nvtt::Format_BC1 && format != nvtt::Format_BC2 && format != nvtt::Format_BC3 && format != nvtt::Format_BC4 && format != nvtt::Format_BC5)
|
||||
@ -554,7 +563,8 @@ bool TexImage::setImage2D(Format format, Decoder decoder, int w, int h, const vo
|
||||
if (m->image == NULL) {
|
||||
m->image = new FloatImage();
|
||||
}
|
||||
m->image->allocate(4, w, h);
|
||||
m->image->allocate(4, w, h, 1);
|
||||
m->type = TextureType_2D;
|
||||
|
||||
const int bw = (w + 3) / 4;
|
||||
const int bh = (h + 3) / 4;
|
||||
@ -570,50 +580,50 @@ bool TexImage::setImage2D(Format format, Decoder decoder, int w, int h, const vo
|
||||
{
|
||||
ColorBlock colors;
|
||||
|
||||
if (format == nvtt::Format_BC1)
|
||||
{
|
||||
const BlockDXT1 * block = (const BlockDXT1 *)ptr;
|
||||
if (format == nvtt::Format_BC1)
|
||||
{
|
||||
const BlockDXT1 * block = (const BlockDXT1 *)ptr;
|
||||
|
||||
if (decoder == Decoder_D3D10) {
|
||||
block->decodeBlock(&colors, false);
|
||||
}
|
||||
else if (decoder == Decoder_D3D9) {
|
||||
block->decodeBlock(&colors, false);
|
||||
}
|
||||
else if (decoder == Decoder_NV5x) {
|
||||
block->decodeBlockNV5x(&colors);
|
||||
}
|
||||
}
|
||||
else if (format == nvtt::Format_BC2)
|
||||
{
|
||||
const BlockDXT3 * block = (const BlockDXT3 *)ptr;
|
||||
if (decoder == Decoder_D3D10) {
|
||||
block->decodeBlock(&colors, false);
|
||||
}
|
||||
else if (decoder == Decoder_D3D9) {
|
||||
block->decodeBlock(&colors, false);
|
||||
}
|
||||
else if (decoder == Decoder_NV5x) {
|
||||
block->decodeBlockNV5x(&colors);
|
||||
}
|
||||
}
|
||||
else if (format == nvtt::Format_BC2)
|
||||
{
|
||||
const BlockDXT3 * block = (const BlockDXT3 *)ptr;
|
||||
|
||||
if (decoder == Decoder_D3D10) {
|
||||
block->decodeBlock(&colors, false);
|
||||
}
|
||||
else if (decoder == Decoder_D3D9) {
|
||||
block->decodeBlock(&colors, false);
|
||||
}
|
||||
else if (decoder == Decoder_NV5x) {
|
||||
block->decodeBlockNV5x(&colors);
|
||||
}
|
||||
}
|
||||
else if (format == nvtt::Format_BC3)
|
||||
{
|
||||
const BlockDXT5 * block = (const BlockDXT5 *)ptr;
|
||||
if (decoder == Decoder_D3D10) {
|
||||
block->decodeBlock(&colors, false);
|
||||
}
|
||||
else if (decoder == Decoder_D3D9) {
|
||||
block->decodeBlock(&colors, false);
|
||||
}
|
||||
else if (decoder == Decoder_NV5x) {
|
||||
block->decodeBlockNV5x(&colors);
|
||||
}
|
||||
}
|
||||
else if (format == nvtt::Format_BC3)
|
||||
{
|
||||
const BlockDXT5 * block = (const BlockDXT5 *)ptr;
|
||||
|
||||
if (decoder == Decoder_D3D10) {
|
||||
block->decodeBlock(&colors, false);
|
||||
}
|
||||
else if (decoder == Decoder_D3D9) {
|
||||
block->decodeBlock(&colors, false);
|
||||
}
|
||||
else if (decoder == Decoder_NV5x) {
|
||||
block->decodeBlockNV5x(&colors);
|
||||
}
|
||||
}
|
||||
else if (format == nvtt::Format_BC4)
|
||||
{
|
||||
if (decoder == Decoder_D3D10) {
|
||||
block->decodeBlock(&colors, false);
|
||||
}
|
||||
else if (decoder == Decoder_D3D9) {
|
||||
block->decodeBlock(&colors, false);
|
||||
}
|
||||
else if (decoder == Decoder_NV5x) {
|
||||
block->decodeBlockNV5x(&colors);
|
||||
}
|
||||
}
|
||||
else if (format == nvtt::Format_BC4)
|
||||
{
|
||||
const BlockATI1 * block = (const BlockATI1 *)ptr;
|
||||
block->decodeBlock(&colors, decoder == Decoder_D3D9);
|
||||
}
|
||||
@ -623,25 +633,25 @@ bool TexImage::setImage2D(Format format, Decoder decoder, int w, int h, const vo
|
||||
block->decodeBlock(&colors, decoder == Decoder_D3D9);
|
||||
}
|
||||
|
||||
for (int yy = 0; yy < 4; yy++)
|
||||
{
|
||||
for (int xx = 0; xx < 4; xx++)
|
||||
{
|
||||
Color32 c = colors.color(xx, yy);
|
||||
for (int yy = 0; yy < 4; yy++)
|
||||
{
|
||||
for (int xx = 0; xx < 4; xx++)
|
||||
{
|
||||
Color32 c = colors.color(xx, yy);
|
||||
|
||||
if (x * 4 + xx < w && y * 4 + yy < h)
|
||||
{
|
||||
m->image->pixel(x*4 + xx, y*4 + yy, 0) = float(c.r) * 1.0f/255.0f;
|
||||
m->image->pixel(x*4 + xx, y*4 + yy, 1) = float(c.g) * 1.0f/255.0f;
|
||||
m->image->pixel(x*4 + xx, y*4 + yy, 2) = float(c.b) * 1.0f/255.0f;
|
||||
m->image->pixel(x*4 + xx, y*4 + yy, 3) = float(c.a) * 1.0f/255.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (x * 4 + xx < w && y * 4 + yy < h)
|
||||
{
|
||||
m->image->pixel(0, x*4 + xx, y*4 + yy, 0) = float(c.r) * 1.0f/255.0f;
|
||||
m->image->pixel(1, x*4 + xx, y*4 + yy, 0) = float(c.g) * 1.0f/255.0f;
|
||||
m->image->pixel(2, x*4 + xx, y*4 + yy, 0) = float(c.b) * 1.0f/255.0f;
|
||||
m->image->pixel(3, x*4 + xx, y*4 + yy, 0) = float(c.a) * 1.0f/255.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ptr += bs;
|
||||
}
|
||||
ptr += bs;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(...) {
|
||||
return false;
|
||||
@ -673,19 +683,19 @@ static void getDefaultFilterWidthAndParams(int filter, float * filterWidth, floa
|
||||
}
|
||||
}
|
||||
|
||||
void TexImage::resize(int w, int h, ResizeFilter filter)
|
||||
void TexImage::resize(int w, int h, int d, ResizeFilter filter)
|
||||
{
|
||||
float filterWidth;
|
||||
float params[2];
|
||||
getDefaultFilterWidthAndParams(filter, &filterWidth, params);
|
||||
|
||||
resize(w, h, filter, filterWidth, params);
|
||||
resize(w, h, d, filter, filterWidth, params);
|
||||
}
|
||||
|
||||
void TexImage::resize(int w, int h, ResizeFilter filter, float filterWidth, const float * params)
|
||||
void TexImage::resize(int w, int h, int d, ResizeFilter filter, float filterWidth, const float * params)
|
||||
{
|
||||
FloatImage * img = m->image;
|
||||
if (img == NULL || (w == img->width() && h == img->height())) {
|
||||
if (img == NULL || (w == img->width() && h == img->height() && d == img->depth())) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -698,25 +708,25 @@ void TexImage::resize(int w, int h, ResizeFilter filter, float filterWidth, cons
|
||||
if (filter == ResizeFilter_Box)
|
||||
{
|
||||
BoxFilter filter(filterWidth);
|
||||
img = img->resize(filter, w, h, wrapMode, 3);
|
||||
img = img->resize(filter, w, h, d, wrapMode, 3);
|
||||
}
|
||||
else if (filter == ResizeFilter_Triangle)
|
||||
{
|
||||
TriangleFilter filter(filterWidth);
|
||||
img = img->resize(filter, w, h, wrapMode, 3);
|
||||
img = img->resize(filter, w, h, d, wrapMode, 3);
|
||||
}
|
||||
else if (filter == ResizeFilter_Kaiser)
|
||||
{
|
||||
KaiserFilter filter(filterWidth);
|
||||
if (params != NULL) filter.setParameters(params[0], params[1]);
|
||||
img = img->resize(filter, w, h, wrapMode, 3);
|
||||
img = img->resize(filter, w, h, d, wrapMode, 3);
|
||||
}
|
||||
else //if (filter == ResizeFilter_Mitchell)
|
||||
{
|
||||
nvDebugCheck(filter == ResizeFilter_Mitchell);
|
||||
MitchellFilter filter;
|
||||
if (params != NULL) filter.setParameters(params[0], params[1]);
|
||||
img = img->resize(filter, w, h, wrapMode, 3);
|
||||
img = img->resize(filter, w, h, d, wrapMode, 3);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -724,25 +734,25 @@ void TexImage::resize(int w, int h, ResizeFilter filter, float filterWidth, cons
|
||||
if (filter == ResizeFilter_Box)
|
||||
{
|
||||
BoxFilter filter(filterWidth);
|
||||
img = img->resize(filter, w, h, wrapMode);
|
||||
img = img->resize(filter, w, h, d, wrapMode);
|
||||
}
|
||||
else if (filter == ResizeFilter_Triangle)
|
||||
{
|
||||
TriangleFilter filter(filterWidth);
|
||||
img = img->resize(filter, w, h, wrapMode);
|
||||
img = img->resize(filter, w, h, d, wrapMode);
|
||||
}
|
||||
else if (filter == ResizeFilter_Kaiser)
|
||||
{
|
||||
KaiserFilter filter(filterWidth);
|
||||
if (params != NULL) filter.setParameters(params[0], params[1]);
|
||||
img = img->resize(filter, w, h, wrapMode);
|
||||
img = img->resize(filter, w, h, d, wrapMode);
|
||||
}
|
||||
else //if (filter == ResizeFilter_Mitchell)
|
||||
{
|
||||
nvDebugCheck(filter == ResizeFilter_Mitchell);
|
||||
MitchellFilter filter;
|
||||
if (params != NULL) filter.setParameters(params[0], params[1]);
|
||||
img = img->resize(filter, w, h, wrapMode);
|
||||
img = img->resize(filter, w, h, d, wrapMode);
|
||||
}
|
||||
}
|
||||
|
||||
@ -765,11 +775,11 @@ void TexImage::resize(int maxExtent, RoundMode roundMode, ResizeFilter filter, f
|
||||
|
||||
int w = m->image->width();
|
||||
int h = m->image->height();
|
||||
int d = 1;
|
||||
int d = m->image->depth();
|
||||
|
||||
getTargetExtent(w, h, d, maxExtent, roundMode, nvtt::TextureType_2D);
|
||||
getTargetExtent(w, h, d, maxExtent, roundMode, m->type);
|
||||
|
||||
resize(w, h, filter, filterWidth, params);
|
||||
resize(w, h, d, filter, filterWidth, params);
|
||||
}
|
||||
|
||||
bool TexImage::buildNextMipmap(MipmapFilter filter)
|
||||
@ -784,7 +794,7 @@ bool TexImage::buildNextMipmap(MipmapFilter filter)
|
||||
bool TexImage::buildNextMipmap(MipmapFilter filter, float filterWidth, const float * params)
|
||||
{
|
||||
FloatImage * img = m->image;
|
||||
if (img == NULL || (img->width() == 1 && img->height() == 1)) {
|
||||
if (img == NULL || (img->width() == 1 && img->height() == 1 && img->depth() == 1)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -816,7 +826,7 @@ bool TexImage::buildNextMipmap(MipmapFilter filter, float filterWidth, const flo
|
||||
{
|
||||
if (filter == MipmapFilter_Box)
|
||||
{
|
||||
if (filterWidth == 0.5f) {
|
||||
if (filterWidth == 0.5f && img->depth() == 1) {
|
||||
img = img->fastDownSample();
|
||||
}
|
||||
else {
|
||||
@ -939,8 +949,8 @@ void TexImage::blend(float red, float green, float blue, float alpha, float t)
|
||||
float * b = img->channel(2);
|
||||
float * a = img->channel(3);
|
||||
|
||||
const int count = img->width() * img->height();
|
||||
for (int i = 0; i < count; i++)
|
||||
const uint count = img->pixelCount();
|
||||
for (uint i = 0; i < count; i++)
|
||||
{
|
||||
r[i] = lerp(r[i], red, t);
|
||||
g[i] = lerp(g[i], green, t);
|
||||
@ -961,8 +971,8 @@ void TexImage::premultiplyAlpha()
|
||||
float * b = img->channel(2);
|
||||
float * a = img->channel(3);
|
||||
|
||||
const int count = img->width() * img->height();
|
||||
for (int i = 0; i < count; i++)
|
||||
const uint count = img->pixelCount();
|
||||
for (uint i = 0; i < count; i++)
|
||||
{
|
||||
r[i] *= a[i];
|
||||
g[i] *= a[i];
|
||||
@ -989,8 +999,8 @@ void TexImage::toGreyScale(float redScale, float greenScale, float blueScale, fl
|
||||
float * b = img->channel(2);
|
||||
float * a = img->channel(3);
|
||||
|
||||
const int count = img->width() * img->height();
|
||||
for (int i = 0; i < count; i++)
|
||||
const uint count = img->pixelCount();
|
||||
for (uint i = 0; i < count; i++)
|
||||
{
|
||||
float grey = r[i] * redScale + g[i] * greenScale + b[i] * blueScale + a[i] * alphaScale;
|
||||
a[i] = b[i] = g[i] = r[i] = grey;
|
||||
@ -1005,33 +1015,37 @@ void TexImage::setBorder(float r, float g, float b, float a)
|
||||
detach();
|
||||
|
||||
FloatImage * img = m->image;
|
||||
const int w = img->width();
|
||||
const int h = img->height();
|
||||
const uint w = img->width();
|
||||
const uint h = img->height();
|
||||
const uint d = img->depth();
|
||||
|
||||
for (int i = 0; i < w; i++)
|
||||
for (int z = 0; z < d; z++)
|
||||
{
|
||||
img->pixel(i, 0, 0) = r;
|
||||
img->pixel(i, 0, 1) = g;
|
||||
img->pixel(i, 0, 2) = b;
|
||||
img->pixel(i, 0, 3) = a;
|
||||
for (int i = 0; i < w; i++)
|
||||
{
|
||||
img->pixel(0, i, 0, z) = r;
|
||||
img->pixel(1, i, 0, z) = g;
|
||||
img->pixel(2, i, 0, z) = b;
|
||||
img->pixel(3, i, 0, z) = a;
|
||||
|
||||
img->pixel(i, h-1, 0) = r;
|
||||
img->pixel(i, h-1, 1) = g;
|
||||
img->pixel(i, h-1, 2) = b;
|
||||
img->pixel(i, h-1, 3) = a;
|
||||
}
|
||||
img->pixel(0, i, h-1, z) = r;
|
||||
img->pixel(1, i, h-1, z) = g;
|
||||
img->pixel(2, i, h-1, z) = b;
|
||||
img->pixel(3, i, h-1, z) = a;
|
||||
}
|
||||
|
||||
for (int i = 0; i < h; i++)
|
||||
{
|
||||
img->pixel(0, i, 0) = r;
|
||||
img->pixel(0, i, 1) = g;
|
||||
img->pixel(0, i, 2) = b;
|
||||
img->pixel(0, i, 3) = a;
|
||||
for (int i = 0; i < h; i++)
|
||||
{
|
||||
img->pixel(0, 0, i, z) = r;
|
||||
img->pixel(1, 0, i, z) = g;
|
||||
img->pixel(2, 0, i, z) = b;
|
||||
img->pixel(3, 0, i, z) = a;
|
||||
|
||||
img->pixel(w-1, i, 0) = r;
|
||||
img->pixel(w-1, i, 1) = g;
|
||||
img->pixel(w-1, i, 2) = b;
|
||||
img->pixel(w-1, i, 3) = a;
|
||||
img->pixel(0, w-1, i, z) = r;
|
||||
img->pixel(1, w-1, i, z) = g;
|
||||
img->pixel(2, w-1, i, z) = b;
|
||||
img->pixel(3, w-1, i, z) = a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1048,8 +1062,8 @@ void TexImage::fill(float red, float green, float blue, float alpha)
|
||||
float * b = img->channel(2);
|
||||
float * a = img->channel(3);
|
||||
|
||||
const int count = img->width() * img->height();
|
||||
for (int i = 0; i < count; i++)
|
||||
const uint count = img->pixelCount();
|
||||
for (uint i = 0; i < count; i++)
|
||||
{
|
||||
r[i] = red;
|
||||
g[i] = green;
|
||||
@ -1112,7 +1126,7 @@ void TexImage::toRGBM(float range/*= 1*/, float threshold/*= 0.25*/)
|
||||
float * b = img->channel(2);
|
||||
float * a = img->channel(3);
|
||||
|
||||
const uint count = img->width() * img->height();
|
||||
const uint count = img->pixelCount();
|
||||
for (uint i = 0; i < count; i++) {
|
||||
float R = nv::clamp(r[i] * irange, 0.0f, 1.0f);
|
||||
float G = nv::clamp(g[i] * irange, 0.0f, 1.0f);
|
||||
@ -1139,7 +1153,7 @@ void TexImage::fromRGBM(float range/*= 1*/)
|
||||
float * b = img->channel(2);
|
||||
float * a = img->channel(3);
|
||||
|
||||
const uint count = img->width() * img->height();
|
||||
const uint count = img->pixelCount();
|
||||
for (uint i = 0; i < count; i++) {
|
||||
float M = a[i] * range;
|
||||
|
||||
@ -1164,7 +1178,7 @@ void TexImage::toYCoCg()
|
||||
float * b = img->channel(2);
|
||||
float * a = img->channel(3);
|
||||
|
||||
const uint count = img->width() * img->height();
|
||||
const uint count = img->pixelCount();
|
||||
for (uint i = 0; i < count; i++) {
|
||||
float R = r[i];
|
||||
float G = g[i];
|
||||
@ -1191,7 +1205,7 @@ void TexImage::toYCoCg()
|
||||
// and minimize bilinear interpolation artifacts.
|
||||
void TexImage::blockScaleCoCg(int bits/*= 5*/, float threshold/*= 0.0*/)
|
||||
{
|
||||
if (m->image == NULL) return;
|
||||
if (m->image == NULL || m->image->depth() != 1) return;
|
||||
|
||||
detach();
|
||||
|
||||
@ -1214,8 +1228,8 @@ void TexImage::blockScaleCoCg(int bits/*= 5*/, float threshold/*= 0.0*/)
|
||||
const uint x = bi*4 + i;
|
||||
if (x >= w) continue;
|
||||
|
||||
float Co = img->pixel(x, y, 0);
|
||||
float Cg = img->pixel(x, y, 1);
|
||||
float Co = img->pixel(0, x, y, 0);
|
||||
float Cg = img->pixel(1, x, y, 0);
|
||||
|
||||
m = max(m, fabsf(Co));
|
||||
m = max(m, fabsf(Cg));
|
||||
@ -1231,8 +1245,8 @@ void TexImage::blockScaleCoCg(int bits/*= 5*/, float threshold/*= 0.0*/)
|
||||
uint x = min(bi*4 + i, w);
|
||||
uint y = min(bj*4 + j, h);
|
||||
|
||||
float & Co = img->pixel(x, y, 0);
|
||||
float & Cg = img->pixel(x, y, 1);
|
||||
float & Co = img->pixel(0, x, y, 0);
|
||||
float & Cg = img->pixel(1, x, y, 0);
|
||||
|
||||
Co /= scale;
|
||||
nvDebugCheck(fabsf(Co) <= 1.0f);
|
||||
@ -1240,7 +1254,7 @@ void TexImage::blockScaleCoCg(int bits/*= 5*/, float threshold/*= 0.0*/)
|
||||
Cg /= scale;
|
||||
nvDebugCheck(fabsf(Cg) <= 1.0f);
|
||||
|
||||
img->pixel(x, y, 2) = scale;
|
||||
img->pixel(2, x, y, 0) = scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1259,7 +1273,7 @@ void TexImage::fromYCoCg()
|
||||
float * b = img->channel(2);
|
||||
float * a = img->channel(3);
|
||||
|
||||
const uint count = img->width() * img->height();
|
||||
const uint count = img->pixelCount();
|
||||
for (uint i = 0; i < count; i++) {
|
||||
float Co = r[i];
|
||||
float Cg = g[i];
|
||||
@ -1294,7 +1308,7 @@ void TexImage::toLUVW(float range/*= 1.0f*/)
|
||||
float * b = img->channel(2);
|
||||
float * a = img->channel(3);
|
||||
|
||||
const uint count = img->width() * img->height();
|
||||
const uint count = img->pixelCount();
|
||||
for (uint i = 0; i < count; i++) {
|
||||
float R = nv::clamp(r[i] * irange, 0.0f, 1.0f);
|
||||
float G = nv::clamp(g[i] * irange, 0.0f, 1.0f);
|
||||
@ -1324,7 +1338,7 @@ void TexImage::abs(int channel)
|
||||
FloatImage * img = m->image;
|
||||
float * c = img->channel(channel);
|
||||
|
||||
const uint count = img->width() * img->height();
|
||||
const uint count = img->pixelCount();
|
||||
for (uint i = 0; i < count; i++) {
|
||||
c[i] = fabsf(c[i]);
|
||||
}
|
||||
@ -1454,6 +1468,7 @@ void TexImage::fromJPEGLS()
|
||||
*/
|
||||
|
||||
|
||||
// If dither is true, this uses Floyd-Steinberg dithering method.
|
||||
void TexImage::binarize(int channel, float threshold, bool dither)
|
||||
{
|
||||
if (m->image == NULL) return;
|
||||
@ -1461,45 +1476,51 @@ void TexImage::binarize(int channel, float threshold, bool dither)
|
||||
detach();
|
||||
|
||||
FloatImage * img = m->image;
|
||||
const uint w = img->width();
|
||||
const uint h = img->height();
|
||||
|
||||
if (!dither) {
|
||||
float * c = img->channel(channel);
|
||||
const uint count = w * h;
|
||||
const uint count = img->pixelCount();
|
||||
for (uint i = 0; i < count; i++) {
|
||||
c[i] = float(c[i] > threshold);
|
||||
}
|
||||
}
|
||||
else {
|
||||
const uint w = img->width();
|
||||
const uint h = img->height();
|
||||
const uint d = img->depth();
|
||||
|
||||
float * row0 = new float[(w+2)];
|
||||
float * row1 = new float[(w+2)];
|
||||
memset(row0, 0, sizeof(float)*(w+2));
|
||||
memset(row1, 0, sizeof(float)*(w+2));
|
||||
|
||||
for (uint y = 0; y < h; y++) {
|
||||
for (uint x = 0; x < w; x++) {
|
||||
|
||||
float & f = img->pixel(x, y, channel);
|
||||
|
||||
// Add error and quantize.
|
||||
float qf = float(f + row0[1+x] > threshold);
|
||||
|
||||
// Compute new error:
|
||||
float diff = f - qf;
|
||||
|
||||
// Store color.
|
||||
f = qf;
|
||||
|
||||
// Propagate new error.
|
||||
row0[1+x+1] += (7.0f / 16.0f) * diff;
|
||||
row1[1+x-1] += (3.0f / 16.0f) * diff;
|
||||
row1[1+x+0] += (5.0f / 16.0f) * diff;
|
||||
row1[1+x+1] += (1.0f / 16.0f) * diff;
|
||||
}
|
||||
|
||||
swap(row0, row1);
|
||||
// @@ Extend Floyd-Steinberg dithering to 3D properly.
|
||||
for (uint z = 0; z < d; z++) {
|
||||
memset(row0, 0, sizeof(float)*(w+2));
|
||||
memset(row1, 0, sizeof(float)*(w+2));
|
||||
|
||||
for (uint y = 0; y < h; y++) {
|
||||
for (uint x = 0; x < w; x++) {
|
||||
|
||||
float & f = img->pixel(channel, x, y, 0);
|
||||
|
||||
// Add error and quantize.
|
||||
float qf = float(f + row0[1+x] > threshold);
|
||||
|
||||
// Compute new error:
|
||||
float diff = f - qf;
|
||||
|
||||
// Store color.
|
||||
f = qf;
|
||||
|
||||
// Propagate new error.
|
||||
row0[1+x+1] += (7.0f / 16.0f) * diff;
|
||||
row1[1+x-1] += (3.0f / 16.0f) * diff;
|
||||
row1[1+x+0] += (5.0f / 16.0f) * diff;
|
||||
row1[1+x+1] += (1.0f / 16.0f) * diff;
|
||||
}
|
||||
|
||||
swap(row0, row1);
|
||||
memset(row1, 0, sizeof(float)*(w+2));
|
||||
}
|
||||
}
|
||||
|
||||
delete [] row0;
|
||||
@ -1510,6 +1531,7 @@ void TexImage::binarize(int channel, float threshold, bool dither)
|
||||
// Uniform quantizer.
|
||||
// Assumes input is in [0, 1] range. Output is in the [0, 1] range, but rounded to the middle of each bin.
|
||||
// If exactEndPoints is true, [0, 1] are represented exactly, and the correponding bins are half the size, so quantization is not truly uniform.
|
||||
// When dither is true, this uses Floyd-Steinberg dithering.
|
||||
void TexImage::quantize(int channel, int bits, bool exactEndPoints, bool dither)
|
||||
{
|
||||
if (m->image == NULL) return;
|
||||
@ -1517,11 +1539,8 @@ void TexImage::quantize(int channel, int bits, bool exactEndPoints, bool dither)
|
||||
detach();
|
||||
|
||||
FloatImage * img = m->image;
|
||||
const uint w = img->width();
|
||||
const uint h = img->height();
|
||||
|
||||
float scale, offset;
|
||||
|
||||
if (exactEndPoints) {
|
||||
scale = float((1 << bits) - 1);
|
||||
offset = 0.0f;
|
||||
@ -1533,40 +1552,47 @@ void TexImage::quantize(int channel, int bits, bool exactEndPoints, bool dither)
|
||||
|
||||
if (!dither) {
|
||||
float * c = img->channel(channel);
|
||||
const uint count = w * h;
|
||||
const uint count = img->pixelCount();
|
||||
for (uint i = 0; i < count; i++) {
|
||||
c[i] = floorf(c[i] * scale + offset) / scale;
|
||||
}
|
||||
}
|
||||
else {
|
||||
const uint w = img->width();
|
||||
const uint h = img->height();
|
||||
const uint d = img->depth();
|
||||
|
||||
float * row0 = new float[(w+2)];
|
||||
float * row1 = new float[(w+2)];
|
||||
memset(row0, 0, sizeof(float)*(w+2));
|
||||
memset(row1, 0, sizeof(float)*(w+2));
|
||||
|
||||
for (uint y = 0; y < h; y++) {
|
||||
for (uint x = 0; x < w; x++) {
|
||||
|
||||
float & f = img->pixel(x, y, channel);
|
||||
|
||||
// Add error and quantize.
|
||||
float qf = floorf((f + row0[1+x]) * scale + offset) / scale;
|
||||
|
||||
// Compute new error:
|
||||
float diff = f - qf;
|
||||
|
||||
// Store color.
|
||||
f = qf;
|
||||
|
||||
// Propagate new error.
|
||||
row0[1+x+1] += (7.0f / 16.0f) * diff;
|
||||
row1[1+x-1] += (3.0f / 16.0f) * diff;
|
||||
row1[1+x+0] += (5.0f / 16.0f) * diff;
|
||||
row1[1+x+1] += (1.0f / 16.0f) * diff;
|
||||
}
|
||||
|
||||
swap(row0, row1);
|
||||
for (uint z = 0; z < d; z++) {
|
||||
memset(row0, 0, sizeof(float)*(w+2));
|
||||
memset(row1, 0, sizeof(float)*(w+2));
|
||||
|
||||
for (uint y = 0; y < h; y++) {
|
||||
for (uint x = 0; x < w; x++) {
|
||||
|
||||
float & f = img->pixel(channel, x, y, 0);
|
||||
|
||||
// Add error and quantize.
|
||||
float qf = floorf((f + row0[1+x]) * scale + offset) / scale;
|
||||
|
||||
// Compute new error:
|
||||
float diff = f - qf;
|
||||
|
||||
// Store color.
|
||||
f = qf;
|
||||
|
||||
// Propagate new error.
|
||||
row0[1+x+1] += (7.0f / 16.0f) * diff;
|
||||
row1[1+x-1] += (3.0f / 16.0f) * diff;
|
||||
row1[1+x+0] += (5.0f / 16.0f) * diff;
|
||||
row1[1+x+1] += (1.0f / 16.0f) * diff;
|
||||
}
|
||||
|
||||
swap(row0, row1);
|
||||
memset(row1, 0, sizeof(float)*(w+2));
|
||||
}
|
||||
}
|
||||
|
||||
delete [] row0;
|
||||
@ -1612,13 +1638,14 @@ void TexImage::transformNormals(NormalTransform xform)
|
||||
|
||||
detach();
|
||||
|
||||
m->image->expandNormals(0);
|
||||
FloatImage * img = m->image;
|
||||
img->expandNormals(0);
|
||||
|
||||
const uint count = m->image->width() * m->image->height();
|
||||
const uint count = img->pixelCount();
|
||||
for (uint i = 0; i < count; i++) {
|
||||
float & x = m->image->pixel(i, 0);
|
||||
float & y = m->image->pixel(i, 1);
|
||||
float & z = m->image->pixel(i, 2);
|
||||
float & x = img->pixel(0, i);
|
||||
float & y = img->pixel(1, i);
|
||||
float & z = img->pixel(2, i);
|
||||
Vector3 n(x, y, z);
|
||||
|
||||
n = normalizeSafe(n, Vector3(0.0f), 0.0f);
|
||||
@ -1675,7 +1702,7 @@ void TexImage::transformNormals(NormalTransform xform)
|
||||
z = n.z;
|
||||
}
|
||||
|
||||
m->image->packNormals(0);
|
||||
img->packNormals(0);
|
||||
}
|
||||
|
||||
void TexImage::reconstructNormals(NormalTransform xform)
|
||||
@ -1684,13 +1711,14 @@ void TexImage::reconstructNormals(NormalTransform xform)
|
||||
|
||||
detach();
|
||||
|
||||
m->image->expandNormals(0);
|
||||
FloatImage * img = m->image;
|
||||
img->expandNormals(0);
|
||||
|
||||
const uint count = m->image->width() * m->image->height();
|
||||
const uint count = img->pixelCount();
|
||||
for (uint i = 0; i < count; i++) {
|
||||
float & x = m->image->pixel(i, 0);
|
||||
float & y = m->image->pixel(i, 1);
|
||||
float & z = m->image->pixel(i, 2);
|
||||
float & x = img->pixel(0, i);
|
||||
float & y = img->pixel(1, i);
|
||||
float & z = img->pixel(2, i);
|
||||
Vector3 n(x, y, z);
|
||||
|
||||
if (xform == NormalTransform_Orthographic) {
|
||||
@ -1723,16 +1751,68 @@ void TexImage::reconstructNormals(NormalTransform xform)
|
||||
z = n.z;
|
||||
}
|
||||
|
||||
m->image->packNormals(0);
|
||||
img->packNormals(0);
|
||||
}
|
||||
|
||||
void TexImage::flipVertically()
|
||||
void TexImage::toCleanNormalMap()
|
||||
{
|
||||
if (m->image == NULL) return;
|
||||
|
||||
detach();
|
||||
|
||||
m->image->flip();
|
||||
m->image->expandNormals(0);
|
||||
|
||||
const uint count = m->image->pixelCount();
|
||||
for (uint i = 0; i < count; i++) {
|
||||
float x = m->image->pixel(0, i);
|
||||
float y = m->image->pixel(1, i);
|
||||
|
||||
m->image->pixel(2, i) = x*x + y*y;
|
||||
}
|
||||
|
||||
m->image->packNormals(0);
|
||||
}
|
||||
|
||||
// [-1,1] -> [ 0,1]
|
||||
void TexImage::packNormals() {
|
||||
if (m->image == NULL) return;
|
||||
detach();
|
||||
m->image->packNormals(0);
|
||||
}
|
||||
|
||||
// [ 0,1] -> [-1,1]
|
||||
void TexImage::expandNormals() {
|
||||
if (m->image == NULL) return;
|
||||
detach();
|
||||
m->image->expandNormals(0);
|
||||
}
|
||||
|
||||
|
||||
void TexImage::flipX()
|
||||
{
|
||||
if (m->image == NULL) return;
|
||||
|
||||
detach();
|
||||
|
||||
m->image->flipX();
|
||||
}
|
||||
|
||||
void TexImage::flipY()
|
||||
{
|
||||
if (m->image == NULL) return;
|
||||
|
||||
detach();
|
||||
|
||||
m->image->flipY();
|
||||
}
|
||||
|
||||
void TexImage::flipZ()
|
||||
{
|
||||
if (m->image == NULL) return;
|
||||
|
||||
detach();
|
||||
|
||||
m->image->flipZ();
|
||||
}
|
||||
|
||||
bool TexImage::copyChannel(const TexImage & srcImage, int srcChannel)
|
||||
@ -1747,17 +1827,14 @@ bool TexImage::copyChannel(const TexImage & srcImage, int srcChannel, int dstCha
|
||||
FloatImage * dst = m->image;
|
||||
const FloatImage * src = srcImage.m->image;
|
||||
|
||||
if (dst == NULL || src == NULL || dst->width() != src->width() || dst->height() != src->height()) {
|
||||
if (!sameLayout(dst, src)) {
|
||||
return false;
|
||||
}
|
||||
nvDebugCheck(dst->componentNum() == 4 && src->componentNum() == 4);
|
||||
nvDebugCheck(dst->componentCount() == 4 && src->componentCount() == 4);
|
||||
|
||||
detach();
|
||||
|
||||
const uint w = src->width();
|
||||
const uint h = src->height();
|
||||
|
||||
memcpy(dst->channel(dstChannel), src->channel(srcChannel), w*h*sizeof(float));
|
||||
memcpy(dst->channel(dstChannel), src->channel(srcChannel), dst->pixelCount()*sizeof(float));
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1769,10 +1846,10 @@ bool TexImage::addChannel(const TexImage & srcImage, int srcChannel, int dstChan
|
||||
FloatImage * dst = m->image;
|
||||
const FloatImage * src = srcImage.m->image;
|
||||
|
||||
if (dst == NULL || src == NULL || dst->width() != src->width() || dst->height() != src->height()) {
|
||||
if (!sameLayout(dst, src)) {
|
||||
return false;
|
||||
}
|
||||
nvDebugCheck(dst->componentNum() == 4 && src->componentNum() == 4);
|
||||
nvDebugCheck(dst->componentCount() == 4 && src->componentCount() == 4);
|
||||
|
||||
detach();
|
||||
|
||||
@ -1781,7 +1858,9 @@ bool TexImage::addChannel(const TexImage & srcImage, int srcChannel, int dstChan
|
||||
|
||||
float * d = dst->channel(dstChannel);
|
||||
const float * s = src->channel(srcChannel);
|
||||
for (uint i = 0; i < w*h; i++) {
|
||||
|
||||
const uint count = src->pixelCount();
|
||||
for (uint i = 0; i < count; i++) {
|
||||
d[i] += s[i] * scale;
|
||||
}
|
||||
|
||||
@ -1819,27 +1898,28 @@ TexImage nvtt::diff(const TexImage & reference, const TexImage & image, float sc
|
||||
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()) {
|
||||
if (!sameLayout(img, ref)) {
|
||||
return TexImage();
|
||||
}
|
||||
nvDebugCheck(img->componentNum() == 4);
|
||||
nvDebugCheck(ref->componentNum() == 4);
|
||||
|
||||
nvDebugCheck(img->componentCount() == 4);
|
||||
nvDebugCheck(ref->componentCount() == 4);
|
||||
|
||||
nvtt::TexImage diffImage;
|
||||
FloatImage * diff = diffImage.m->image = new FloatImage;
|
||||
diff->allocate(4, img->width(), img->height());
|
||||
diff->allocate(4, img->width(), img->height(), img->depth());
|
||||
|
||||
const uint count = img->width() * img->height();
|
||||
const uint count = img->pixelCount();
|
||||
for (uint i = 0; i < count; i++)
|
||||
{
|
||||
float r0 = img->pixel(i, 0);
|
||||
float g0 = img->pixel(i, 1);
|
||||
float b0 = img->pixel(i, 2);
|
||||
//float a0 = img->pixel(i, 3);
|
||||
float r1 = ref->pixel(i, 0);
|
||||
float g1 = ref->pixel(i, 1);
|
||||
float b1 = ref->pixel(i, 2);
|
||||
float a1 = ref->pixel(i, 3);
|
||||
float r0 = img->pixel(0, i);
|
||||
float g0 = img->pixel(1, i);
|
||||
float b0 = img->pixel(2, i);
|
||||
//float a0 = img->pixel(3, i);
|
||||
float r1 = ref->pixel(0, i);
|
||||
float g1 = ref->pixel(1, i);
|
||||
float b1 = ref->pixel(2, i);
|
||||
float a1 = ref->pixel(3, i);
|
||||
|
||||
float dr = r0 - r1;
|
||||
float dg = g0 - g1;
|
||||
@ -1853,10 +1933,10 @@ TexImage nvtt::diff(const TexImage & reference, const TexImage & image, float sc
|
||||
db *= a1;
|
||||
}
|
||||
|
||||
diff->pixel(i, 0) = dr * scale;
|
||||
diff->pixel(i, 1) = dg * scale;
|
||||
diff->pixel(i, 2) = db * scale;
|
||||
diff->pixel(i, 3) = a1;
|
||||
diff->pixel(0, i) = dr * scale;
|
||||
diff->pixel(1, i) = dg * scale;
|
||||
diff->pixel(2, i) = db * scale;
|
||||
diff->pixel(3, i) = a1;
|
||||
}
|
||||
|
||||
return diffImage;
|
||||
|
@ -125,8 +125,9 @@ CudaCompressor::CudaCompressor(CudaContext & ctx) : m_ctx(ctx)
|
||||
|
||||
}
|
||||
|
||||
void CudaCompressor::compress(nvtt::AlphaMode alphaMode, uint w, uint h, const float * data, nvtt::TaskDispatcher * dispatcher, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions)
|
||||
void CudaCompressor::compress(nvtt::AlphaMode alphaMode, uint w, uint h, uint d, const float * data, nvtt::TaskDispatcher * dispatcher, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions)
|
||||
{
|
||||
nvDebugCheck(d == 1);
|
||||
nvDebugCheck(cuda::isHardwarePresent());
|
||||
|
||||
#if defined HAVE_CUDA
|
||||
|
@ -54,7 +54,7 @@ namespace nv
|
||||
{
|
||||
CudaCompressor(CudaContext & ctx);
|
||||
|
||||
virtual void compress(nvtt::AlphaMode alphaMode, uint w, uint h, const float * data, nvtt::TaskDispatcher * dispatcher, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions);
|
||||
virtual void compress(nvtt::AlphaMode alphaMode, uint w, uint h, uint d, const float * data, nvtt::TaskDispatcher * dispatcher, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions);
|
||||
|
||||
virtual void setup(cudaArray * image, const nvtt::CompressionOptions::Private & compressionOptions) = 0;
|
||||
virtual void compressBlocks(uint first, uint count, uint w, uint h, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output) = 0;
|
||||
|
@ -23,7 +23,7 @@
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#include "nvcore/Debug.h"
|
||||
//#include "nvcore/Library.h"
|
||||
#include "nvcore/Library.h"
|
||||
#include "CudaUtils.h"
|
||||
|
||||
#if defined HAVE_CUDA
|
||||
|
@ -190,7 +190,7 @@ namespace nvtt
|
||||
{
|
||||
TextureType_2D,
|
||||
TextureType_Cube,
|
||||
// TextureType_3D,
|
||||
TextureType_3D,
|
||||
};
|
||||
|
||||
/// Input formats.
|
||||
@ -415,6 +415,7 @@ namespace nvtt
|
||||
NVTT_API int width() const;
|
||||
NVTT_API int height() const;
|
||||
NVTT_API int depth() const;
|
||||
NVTT_API TextureType type() const;
|
||||
NVTT_API WrapMode wrapMode() const;
|
||||
NVTT_API AlphaMode alphaMode() const;
|
||||
NVTT_API bool isNormalMap() const;
|
||||
@ -428,13 +429,13 @@ namespace nvtt
|
||||
// Texture data.
|
||||
NVTT_API bool load(const char * fileName, bool * hasAlpha = 0);
|
||||
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 * r, const void * g, const void * b, const void * a);
|
||||
NVTT_API bool setImage(InputFormat format, int w, int h, int d, const void * data);
|
||||
NVTT_API bool setImage(InputFormat format, int w, int h, int d, const void * r, const void * g, const void * b, const void * a);
|
||||
NVTT_API bool setImage2D(Format format, Decoder decoder, int w, int h, const void * data);
|
||||
|
||||
// Resizing methods.
|
||||
NVTT_API void resize(int w, int h, ResizeFilter filter);
|
||||
NVTT_API void resize(int w, int h, ResizeFilter filter, float filterWidth, const float * params = 0);
|
||||
NVTT_API void resize(int w, int h, int d, ResizeFilter filter);
|
||||
NVTT_API void resize(int w, int h, int d, ResizeFilter filter, float filterWidth, const float * params = 0);
|
||||
NVTT_API void resize(int maxExtent, RoundMode mode, ResizeFilter filter);
|
||||
NVTT_API void resize(int maxExtent, RoundMode mode, ResizeFilter filter, float filterWidth, const float * params = 0);
|
||||
NVTT_API bool buildNextMipmap(MipmapFilter filter);
|
||||
@ -471,14 +472,19 @@ namespace nvtt
|
||||
NVTT_API void binarize(int channel, float threshold, bool dither);
|
||||
NVTT_API void quantize(int channel, int bits, bool exactEndPoints, bool dither);
|
||||
|
||||
// Normal map transforms.
|
||||
// Normal map transforms. @@ All these methods assume packed normals.
|
||||
NVTT_API void toNormalMap(float sm, float medium, float big, float large);
|
||||
NVTT_API void normalizeNormalMap();
|
||||
NVTT_API void transformNormals(NormalTransform xform);
|
||||
NVTT_API void reconstructNormals(NormalTransform xform);
|
||||
NVTT_API void toCleanNormalMap();
|
||||
NVTT_API void packNormals(); // [-1,1] -> [ 0,1]
|
||||
NVTT_API void expandNormals(); // [ 0,1] -> [-1,1]
|
||||
|
||||
// Geometric transforms.
|
||||
NVTT_API void flipVertically();
|
||||
NVTT_API void flipX();
|
||||
NVTT_API void flipY();
|
||||
NVTT_API void flipZ();
|
||||
|
||||
// Copy image data.
|
||||
NVTT_API bool copyChannel(const TexImage & srcImage, int srcChannel);
|
||||
@ -501,6 +507,54 @@ namespace nvtt
|
||||
};
|
||||
|
||||
|
||||
/// A texture mipmap.
|
||||
struct CubeImage
|
||||
{
|
||||
NVTT_API CubeImage();
|
||||
NVTT_API CubeImage(const CubeImage & tex);
|
||||
NVTT_API ~CubeImage();
|
||||
|
||||
NVTT_API void operator=(const CubeImage & tex);
|
||||
|
||||
// Queries.
|
||||
NVTT_API bool isNull() const;
|
||||
NVTT_API int size() const;
|
||||
NVTT_API int countMipmaps() const;
|
||||
NVTT_API float average(int channel, int alpha_channel = -1, float gamma = 2.2f) const;
|
||||
|
||||
// Texture data.
|
||||
NVTT_API bool load(const char * fileName);
|
||||
NVTT_API bool save(const char * fileName) const;
|
||||
NVTT_API bool setImage2D(InputFormat format, int face, int w, int h, const void * data);
|
||||
NVTT_API bool setImage2D(InputFormat format, int face, int w, int h, const void * r, const void * g, const void * b, const void * a);
|
||||
NVTT_API bool setImage2D(Format format, Decoder decoder, int face, int w, int h, const void * data);
|
||||
|
||||
TexImage & face(int face);
|
||||
|
||||
//
|
||||
|
||||
// @@ Add resizing methods.
|
||||
/*
|
||||
NVTT_API void resize(int w, int h, ResizeFilter filter);
|
||||
NVTT_API void resize(int w, int h, ResizeFilter filter, float filterWidth, const float * params = 0);
|
||||
NVTT_API void resize(int maxExtent, RoundMode mode, ResizeFilter filter);
|
||||
NVTT_API void resize(int maxExtent, RoundMode mode, ResizeFilter filter, float filterWidth, const float * params = 0);
|
||||
NVTT_API bool buildNextMipmap(MipmapFilter filter);
|
||||
NVTT_API bool buildNextMipmap(MipmapFilter filter, float filterWidth, const float * params = 0);
|
||||
*/
|
||||
|
||||
// Color transforms.
|
||||
NVTT_API void toLinear(float gamma);
|
||||
NVTT_API void toGamma(float gamma);
|
||||
|
||||
private:
|
||||
void detach();
|
||||
|
||||
struct Private;
|
||||
Private * m;
|
||||
};
|
||||
|
||||
|
||||
// Return string for the given error code.
|
||||
NVTT_API const char * errorString(Error e);
|
||||
|
||||
|
@ -60,7 +60,7 @@ int main(int argc, char *argv[])
|
||||
// Output compressed image.
|
||||
context.outputHeader(image, image.countMipmaps(), compressionOptions, outputOptions);
|
||||
|
||||
image.flipVertically();
|
||||
image.flipY();
|
||||
image.setAlphaMode(nvtt::AlphaMode_Transparency);
|
||||
|
||||
// Output first mipmap.
|
||||
|
@ -95,7 +95,7 @@ int main(int argc, char *argv[])
|
||||
// Output header and first mipmap.
|
||||
context.outputHeader(colorMap, colorMap.countMipmaps(), colorCompressionOptions, colorOutputOptions);
|
||||
|
||||
colorMap.flipVertically();
|
||||
colorMap.flipY();
|
||||
colorMap.setAlphaMode(nvtt::AlphaMode_Transparency);
|
||||
|
||||
context.compress(colorMap, 0, 0, colorCompressionOptions, colorOutputOptions);
|
||||
@ -103,7 +103,7 @@ int main(int argc, char *argv[])
|
||||
if (inputFileNameNormal != NULL) {
|
||||
context.outputHeader(normalMap, normalMap.countMipmaps(), normalCompressionOptions, normalOutputOptions);
|
||||
|
||||
normalMap.flipVertically();
|
||||
normalMap.flipY();
|
||||
normalMap.setAlphaMode(nvtt::AlphaMode_Transparency);
|
||||
normalMap.normalizeNormalMap();
|
||||
normalMap.copyChannel(colorMap, 3); // Copy alpha channel from color to normal map.
|
||||
@ -118,7 +118,7 @@ int main(int argc, char *argv[])
|
||||
const float coverage = colorMap.alphaTestCoverage(alphaRef);
|
||||
|
||||
// Build and output mipmaps.
|
||||
int m = 1;
|
||||
int m = 1;
|
||||
while (colorMap.buildNextMipmap(nvtt::MipmapFilter_Kaiser))
|
||||
{
|
||||
colorMap.scaleAlphaToCoverage(coverage, alphaRef);
|
||||
@ -136,7 +136,7 @@ int main(int argc, char *argv[])
|
||||
context.compress(normalMap, 0, m, normalCompressionOptions, normalOutputOptions);
|
||||
}
|
||||
|
||||
m++;
|
||||
m++;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
|
@ -839,7 +839,7 @@ int main(int argc, char *argv[])
|
||||
outputFileName.format("%s/%s", outPath, set.fileNames[i]);
|
||||
outputFileName.stripExtension();
|
||||
if (set.type == ImageType_HDR) outputFileName.append(".dds");
|
||||
else outputFileName.append(".png");
|
||||
else outputFileName.append(".tga");
|
||||
if (!img.save(outputFileName.str()))
|
||||
{
|
||||
printf("Error saving file '%s'.\n", outputFileName.str());
|
||||
@ -851,7 +851,7 @@ int main(int argc, char *argv[])
|
||||
outputFileName.format("%s/%s", outputFilePath.str(), set.fileNames[i]);
|
||||
outputFileName.stripExtension();
|
||||
if (set.type == ImageType_HDR) outputFileName.append(".dds");
|
||||
else outputFileName.append(".png");
|
||||
else outputFileName.append(".tga");
|
||||
if (!img_out.save(outputFileName.str()))
|
||||
{
|
||||
printf("Error saving file '%s'.\n", outputFileName.str());
|
||||
@ -886,7 +886,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
outputFileName.format("%s/%s", outputFilePath.str(), set.fileNames[i]);
|
||||
outputFileName.stripExtension();
|
||||
outputFileName.append("_diff.png");
|
||||
outputFileName.append("_diff.tga");
|
||||
diff.save(outputFileName.str());
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user