- weighted cuda compressor.
- faster and better BC3n compressor - add normal map flag to DDS files that store normal maps. - stop using RXGB fourcc code. - move tools to tools/ - add temptative config dialog for UI based tool. - add experimental normal map mipmap generation. - start adding support for input dds files in nvcompress. - many other small fixes and cleanup.
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@ -1,176 +1,175 @@
|
||||
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#ifndef NV_TT_BLOCKDXT_H
|
||||
#define NV_TT_BLOCKDXT_H
|
||||
|
||||
#include <nvmath/Color.h>
|
||||
#include "nvtt.h"
|
||||
|
||||
namespace nv
|
||||
{
|
||||
struct ColorBlock;
|
||||
|
||||
/// DXT1 block.
|
||||
struct BlockDXT1
|
||||
{
|
||||
Color16 col0;
|
||||
Color16 col1;
|
||||
union {
|
||||
uint8 row[4];
|
||||
uint indices;
|
||||
};
|
||||
|
||||
bool isFourColorMode() const;
|
||||
|
||||
uint evaluatePalette(Color32 color_array[4]) const;
|
||||
uint evaluatePaletteFast(Color32 color_array[4]) const;
|
||||
void evaluatePalette3(Color32 color_array[4]) const;
|
||||
void evaluatePalette4(Color32 color_array[4]) const;
|
||||
|
||||
void decodeBlock(ColorBlock * block) const;
|
||||
|
||||
void setIndices(int * idx);
|
||||
|
||||
void flip4();
|
||||
void flip2();
|
||||
};
|
||||
|
||||
/// Return true if the block uses four color mode, false otherwise.
|
||||
inline bool BlockDXT1::isFourColorMode() const
|
||||
{
|
||||
return col0.u >= col1.u; // @@ > or >= ?
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// DXT3 alpha block with explicit alpha.
|
||||
struct AlphaBlockDXT3
|
||||
{
|
||||
union {
|
||||
struct {
|
||||
uint alpha0 : 4;
|
||||
uint alpha1 : 4;
|
||||
uint alpha2 : 4;
|
||||
uint alpha3 : 4;
|
||||
uint alpha4 : 4;
|
||||
uint alpha5 : 4;
|
||||
uint alpha6 : 4;
|
||||
uint alpha7 : 4;
|
||||
uint alpha8 : 4;
|
||||
uint alpha9 : 4;
|
||||
uint alphaA : 4;
|
||||
uint alphaB : 4;
|
||||
uint alphaC : 4;
|
||||
uint alphaD : 4;
|
||||
uint alphaE : 4;
|
||||
uint alphaF : 4;
|
||||
};
|
||||
uint16 row[4];
|
||||
};
|
||||
|
||||
void flip4();
|
||||
void flip2();
|
||||
};
|
||||
|
||||
|
||||
/// DXT3 block.
|
||||
struct BlockDXT3
|
||||
{
|
||||
AlphaBlockDXT3 alpha;
|
||||
BlockDXT1 color;
|
||||
|
||||
void decodeBlock(ColorBlock * block) const;
|
||||
|
||||
void flip4();
|
||||
void flip2();
|
||||
};
|
||||
|
||||
|
||||
/// DXT5 alpha block.
|
||||
struct AlphaBlockDXT5
|
||||
{
|
||||
union {
|
||||
struct {
|
||||
uint64 alpha0 : 8; // 8
|
||||
uint64 alpha1 : 8; // 16
|
||||
uint64 bits0 : 3; // 3 - 19
|
||||
uint64 bits1 : 3; // 6 - 22
|
||||
uint64 bits2 : 3; // 9 - 25
|
||||
uint64 bits3 : 3; // 12 - 28
|
||||
uint64 bits4 : 3; // 15 - 31
|
||||
uint64 bits5 : 3; // 18 - 34
|
||||
uint64 bits6 : 3; // 21 - 37
|
||||
uint64 bits7 : 3; // 24 - 40
|
||||
uint64 bits8 : 3; // 27 - 43
|
||||
uint64 bits9 : 3; // 30 - 46
|
||||
uint64 bitsA : 3; // 33 - 49
|
||||
uint64 bitsB : 3; // 36 - 52
|
||||
uint64 bitsC : 3; // 39 - 55
|
||||
uint64 bitsD : 3; // 42 - 58
|
||||
uint64 bitsE : 3; // 45 - 61
|
||||
uint64 bitsF : 3; // 48 - 64
|
||||
};
|
||||
uint64 u;
|
||||
};
|
||||
|
||||
void evaluatePalette(uint8 alpha[8]) const;
|
||||
void evaluatePalette8(uint8 alpha[8]) const;
|
||||
void evaluatePalette6(uint8 alpha[8]) const;
|
||||
void indices(uint8 index_array[16]) const;
|
||||
|
||||
uint index(uint index) const;
|
||||
void setIndex(uint index, uint value);
|
||||
|
||||
void flip4();
|
||||
void flip2();
|
||||
};
|
||||
|
||||
/// DXT5 block.
|
||||
struct BlockDXT5
|
||||
{
|
||||
AlphaBlockDXT5 alpha;
|
||||
BlockDXT1 color;
|
||||
|
||||
void decodeBlock(ColorBlock * block) const;
|
||||
|
||||
void flip4();
|
||||
void flip2();
|
||||
};
|
||||
|
||||
/// 3DC block.
|
||||
struct Block3DC
|
||||
{
|
||||
AlphaBlockDXT5 y;
|
||||
AlphaBlockDXT5 x;
|
||||
|
||||
void decodeBlock(ColorBlock * block) const;
|
||||
|
||||
void flip4();
|
||||
void flip2();
|
||||
};
|
||||
|
||||
} // nv namespace
|
||||
|
||||
#endif // NV_TT_BLOCKDXT_H
|
||||
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#ifndef NV_IMAGE_BLOCKDXT_H
|
||||
#define NV_IMAGE_BLOCKDXT_H
|
||||
|
||||
#include <nvmath/Color.h>
|
||||
|
||||
namespace nv
|
||||
{
|
||||
struct ColorBlock;
|
||||
|
||||
/// DXT1 block.
|
||||
struct BlockDXT1
|
||||
{
|
||||
Color16 col0;
|
||||
Color16 col1;
|
||||
union {
|
||||
uint8 row[4];
|
||||
uint indices;
|
||||
};
|
||||
|
||||
bool isFourColorMode() const;
|
||||
|
||||
uint evaluatePalette(Color32 color_array[4]) const;
|
||||
uint evaluatePaletteFast(Color32 color_array[4]) const;
|
||||
void evaluatePalette3(Color32 color_array[4]) const;
|
||||
void evaluatePalette4(Color32 color_array[4]) const;
|
||||
|
||||
void decodeBlock(ColorBlock * block) const;
|
||||
|
||||
void setIndices(int * idx);
|
||||
|
||||
void flip4();
|
||||
void flip2();
|
||||
};
|
||||
|
||||
/// Return true if the block uses four color mode, false otherwise.
|
||||
inline bool BlockDXT1::isFourColorMode() const
|
||||
{
|
||||
return col0.u >= col1.u; // @@ > or >= ?
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// DXT3 alpha block with explicit alpha.
|
||||
struct AlphaBlockDXT3
|
||||
{
|
||||
union {
|
||||
struct {
|
||||
uint alpha0 : 4;
|
||||
uint alpha1 : 4;
|
||||
uint alpha2 : 4;
|
||||
uint alpha3 : 4;
|
||||
uint alpha4 : 4;
|
||||
uint alpha5 : 4;
|
||||
uint alpha6 : 4;
|
||||
uint alpha7 : 4;
|
||||
uint alpha8 : 4;
|
||||
uint alpha9 : 4;
|
||||
uint alphaA : 4;
|
||||
uint alphaB : 4;
|
||||
uint alphaC : 4;
|
||||
uint alphaD : 4;
|
||||
uint alphaE : 4;
|
||||
uint alphaF : 4;
|
||||
};
|
||||
uint16 row[4];
|
||||
};
|
||||
|
||||
void flip4();
|
||||
void flip2();
|
||||
};
|
||||
|
||||
|
||||
/// DXT3 block.
|
||||
struct BlockDXT3
|
||||
{
|
||||
AlphaBlockDXT3 alpha;
|
||||
BlockDXT1 color;
|
||||
|
||||
void decodeBlock(ColorBlock * block) const;
|
||||
|
||||
void flip4();
|
||||
void flip2();
|
||||
};
|
||||
|
||||
|
||||
/// DXT5 alpha block.
|
||||
struct AlphaBlockDXT5
|
||||
{
|
||||
union {
|
||||
struct {
|
||||
uint64 alpha0 : 8; // 8
|
||||
uint64 alpha1 : 8; // 16
|
||||
uint64 bits0 : 3; // 3 - 19
|
||||
uint64 bits1 : 3; // 6 - 22
|
||||
uint64 bits2 : 3; // 9 - 25
|
||||
uint64 bits3 : 3; // 12 - 28
|
||||
uint64 bits4 : 3; // 15 - 31
|
||||
uint64 bits5 : 3; // 18 - 34
|
||||
uint64 bits6 : 3; // 21 - 37
|
||||
uint64 bits7 : 3; // 24 - 40
|
||||
uint64 bits8 : 3; // 27 - 43
|
||||
uint64 bits9 : 3; // 30 - 46
|
||||
uint64 bitsA : 3; // 33 - 49
|
||||
uint64 bitsB : 3; // 36 - 52
|
||||
uint64 bitsC : 3; // 39 - 55
|
||||
uint64 bitsD : 3; // 42 - 58
|
||||
uint64 bitsE : 3; // 45 - 61
|
||||
uint64 bitsF : 3; // 48 - 64
|
||||
};
|
||||
uint64 u;
|
||||
};
|
||||
|
||||
void evaluatePalette(uint8 alpha[8]) const;
|
||||
void evaluatePalette8(uint8 alpha[8]) const;
|
||||
void evaluatePalette6(uint8 alpha[8]) const;
|
||||
void indices(uint8 index_array[16]) const;
|
||||
|
||||
uint index(uint index) const;
|
||||
void setIndex(uint index, uint value);
|
||||
|
||||
void flip4();
|
||||
void flip2();
|
||||
};
|
||||
|
||||
/// DXT5 block.
|
||||
struct BlockDXT5
|
||||
{
|
||||
AlphaBlockDXT5 alpha;
|
||||
BlockDXT1 color;
|
||||
|
||||
void decodeBlock(ColorBlock * block) const;
|
||||
|
||||
void flip4();
|
||||
void flip2();
|
||||
};
|
||||
|
||||
/// 3DC block.
|
||||
struct Block3DC
|
||||
{
|
||||
AlphaBlockDXT5 y;
|
||||
AlphaBlockDXT5 x;
|
||||
|
||||
void decodeBlock(ColorBlock * block) const;
|
||||
|
||||
void flip4();
|
||||
void flip2();
|
||||
};
|
||||
|
||||
} // nv namespace
|
||||
|
||||
#endif // NV_IMAGE_BLOCKDXT_H
|
@ -14,6 +14,8 @@ SET(IMAGE_SRCS
|
||||
ImageIO.cpp
|
||||
ColorBlock.h
|
||||
ColorBlock.cpp
|
||||
BlockDXT.h
|
||||
BlockDXT.cpp
|
||||
HoleFilling.h
|
||||
HoleFilling.cpp
|
||||
DirectDrawSurface.h
|
||||
@ -21,7 +23,9 @@ SET(IMAGE_SRCS
|
||||
Quantize.h
|
||||
Quantize.cpp
|
||||
NormalMap.h
|
||||
NormalMap.cpp)
|
||||
NormalMap.cpp
|
||||
NormalMipmap.h
|
||||
NormalMipmap.cpp)
|
||||
|
||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
|
@ -53,7 +53,7 @@ void ColorBlock::init(const Image * img, uint x, uint y)
|
||||
nvDebugCheck(bw != 0);
|
||||
nvDebugCheck(bh != 0);
|
||||
|
||||
int remainder[] = {
|
||||
static int remainder[] = {
|
||||
0, 0, 0, 0,
|
||||
0, 1, 0, 1,
|
||||
0, 1, 2, 0,
|
||||
@ -61,7 +61,7 @@ void ColorBlock::init(const Image * img, uint x, uint y)
|
||||
};
|
||||
|
||||
// Blocks that are smaller than 4x4 are handled by repeating the pixels.
|
||||
// @@ Thats only correct when block size is 1, 2 or 4, but not with 3.
|
||||
// @@ Thats only correct when block size is 1, 2 or 4, but not with 3. :(
|
||||
|
||||
for(uint i = 0; i < 4; i++) {
|
||||
//const int by = i % bh;
|
||||
@ -80,7 +80,7 @@ void ColorBlock::swizzleDXT5n()
|
||||
for(int i = 0; i < 16; i++)
|
||||
{
|
||||
Color32 c = m_color[i];
|
||||
m_color[i] = Color32(0, c.r, 0, c.g);
|
||||
m_color[i] = Color32(0, c.g, 0, c.r);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,258 +1,652 @@
|
||||
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#include <nvcore/Debug.h>
|
||||
|
||||
#include <nvimage/DirectDrawSurface.h>
|
||||
|
||||
#include <string.h> // memset
|
||||
|
||||
|
||||
using namespace nv;
|
||||
|
||||
#if !defined(MAKEFOURCC)
|
||||
# define MAKEFOURCC(ch0, ch1, ch2, ch3) \
|
||||
(uint(uint8(ch0)) | (uint(uint8(ch1)) << 8) | \
|
||||
(uint(uint8(ch2)) << 16) | (uint(uint8(ch3)) << 24 ))
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
static const uint FOURCC_DDS = MAKEFOURCC('D', 'D', 'S', ' ');
|
||||
static const uint FOURCC_DXT1 = MAKEFOURCC('D', 'X', 'T', '1');
|
||||
static const uint FOURCC_DXT2 = MAKEFOURCC('D', 'X', 'T', '2');
|
||||
static const uint FOURCC_DXT3 = MAKEFOURCC('D', 'X', 'T', '3');
|
||||
static const uint FOURCC_DXT4 = MAKEFOURCC('D', 'X', 'T', '4');
|
||||
static const uint FOURCC_DXT5 = MAKEFOURCC('D', 'X', 'T', '5');
|
||||
static const uint FOURCC_RXGB = MAKEFOURCC('R', 'X', 'G', 'B');
|
||||
static const uint FOURCC_ATI1 = MAKEFOURCC('A', 'T', 'I', '1');
|
||||
static const uint FOURCC_ATI2 = MAKEFOURCC('A', 'T', 'I', '2');
|
||||
|
||||
static const uint DDSD_CAPS = 0x00000001U;
|
||||
static const uint DDSD_PIXELFORMAT = 0x00001000U;
|
||||
static const uint DDSD_WIDTH = 0x00000004U;
|
||||
static const uint DDSD_HEIGHT = 0x00000002U;
|
||||
static const uint DDSD_PITCH = 0x00000008U;
|
||||
static const uint DDSD_MIPMAPCOUNT = 0x00020000U;
|
||||
static const uint DDSD_LINEARSIZE = 0x00080000U;
|
||||
static const uint DDSD_DEPTH = 0x00800000U;
|
||||
|
||||
static const uint DDSCAPS_COMPLEX = 0x00000008U;
|
||||
static const uint DDSCAPS_TEXTURE = 0x00001000U;
|
||||
static const uint DDSCAPS_MIPMAP = 0x00400000U;
|
||||
static const uint DDSCAPS2_VOLUME = 0x00200000U;
|
||||
static const uint DDSCAPS2_CUBEMAP = 0x00000200U;
|
||||
|
||||
static const uint DDSCAPS2_CUBEMAP_POSITIVEX = 0x00000400U;
|
||||
static const uint DDSCAPS2_CUBEMAP_NEGATIVEX = 0x00000800U;
|
||||
static const uint DDSCAPS2_CUBEMAP_POSITIVEY = 0x00001000U;
|
||||
static const uint DDSCAPS2_CUBEMAP_NEGATIVEY = 0x00002000U;
|
||||
static const uint DDSCAPS2_CUBEMAP_POSITIVEZ = 0x00004000U;
|
||||
static const uint DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x00008000U;
|
||||
static const uint DDSCAPS2_CUBEMAP_ALL_FACES = 0x0000F000U;
|
||||
|
||||
static const uint DDPF_RGB = 0x00000040U;
|
||||
static const uint DDPF_FOURCC = 0x00000004U;
|
||||
static const uint DDPF_ALPHAPIXELS = 0x00000001U;
|
||||
}
|
||||
|
||||
DDSHeader::DDSHeader()
|
||||
{
|
||||
this->fourcc = FOURCC_DDS;
|
||||
this->size = 124;
|
||||
this->flags = (DDSD_CAPS|DDSD_PIXELFORMAT);
|
||||
this->height = 0;
|
||||
this->width = 0;
|
||||
this->pitch = 0;
|
||||
this->depth = 0;
|
||||
this->mipmapcount = 0;
|
||||
memset(this->reserved, 0, sizeof(this->reserved));
|
||||
|
||||
// Store version information on the reserved header attributes.
|
||||
this->reserved[9] = MAKEFOURCC('N', 'V', 'T', 'T');
|
||||
this->reserved[10] = (0 << 16) | (1 << 8) | (0); // major.minor.revision
|
||||
|
||||
this->pf.size = 32;
|
||||
this->pf.flags = 0;
|
||||
this->pf.fourcc = 0;
|
||||
this->pf.bitcount = 0;
|
||||
this->pf.rmask = 0;
|
||||
this->pf.gmask = 0;
|
||||
this->pf.bmask = 0;
|
||||
this->pf.amask = 0;
|
||||
this->caps.caps1 = DDSCAPS_TEXTURE;
|
||||
this->caps.caps2 = 0;
|
||||
this->caps.caps3 = 0;
|
||||
this->caps.caps4 = 0;
|
||||
this->notused = 0;
|
||||
}
|
||||
|
||||
void DDSHeader::setWidth(uint w)
|
||||
{
|
||||
this->flags |= DDSD_WIDTH;
|
||||
this->width = w;
|
||||
}
|
||||
|
||||
void DDSHeader::setHeight(uint h)
|
||||
{
|
||||
this->flags |= DDSD_HEIGHT;
|
||||
this->height = h;
|
||||
}
|
||||
|
||||
void DDSHeader::setDepth(uint d)
|
||||
{
|
||||
this->flags |= DDSD_DEPTH;
|
||||
this->height = d;
|
||||
}
|
||||
|
||||
void DDSHeader::setMipmapCount(uint count)
|
||||
{
|
||||
if (count == 0)
|
||||
{
|
||||
this->flags &= ~DDSD_MIPMAPCOUNT;
|
||||
this->mipmapcount = 0;
|
||||
|
||||
if (this->caps.caps2 == 0) {
|
||||
this->caps.caps1 = DDSCAPS_TEXTURE;
|
||||
}
|
||||
else {
|
||||
this->caps.caps1 = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this->flags |= DDSD_MIPMAPCOUNT;
|
||||
this->mipmapcount = count;
|
||||
|
||||
this->caps.caps1 |= DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
|
||||
}
|
||||
}
|
||||
|
||||
void DDSHeader::setTexture2D()
|
||||
{
|
||||
// nothing to do here.
|
||||
}
|
||||
|
||||
void DDSHeader::setTexture3D()
|
||||
{
|
||||
this->caps.caps2 = DDSCAPS2_VOLUME;
|
||||
}
|
||||
|
||||
void DDSHeader::setTextureCube()
|
||||
{
|
||||
this->caps.caps1 |= DDSCAPS_COMPLEX;
|
||||
this->caps.caps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALL_FACES;
|
||||
}
|
||||
|
||||
void DDSHeader::setLinearSize(uint size)
|
||||
{
|
||||
this->flags &= ~DDSD_PITCH;
|
||||
this->flags |= DDSD_LINEARSIZE;
|
||||
this->pitch = size;
|
||||
}
|
||||
|
||||
void DDSHeader::setPitch(uint pitch)
|
||||
{
|
||||
this->flags &= ~DDSD_LINEARSIZE;
|
||||
this->flags |= DDSD_PITCH;
|
||||
this->pitch = pitch;
|
||||
}
|
||||
|
||||
void DDSHeader::setFourCC(uint8 c0, uint8 c1, uint8 c2, uint8 c3)
|
||||
{
|
||||
// set fourcc pixel format.
|
||||
this->pf.flags = DDPF_FOURCC;
|
||||
this->pf.fourcc = MAKEFOURCC(c0, c1, c2, c3);
|
||||
this->pf.bitcount = 0;
|
||||
this->pf.rmask = 0;
|
||||
this->pf.gmask = 0;
|
||||
this->pf.bmask = 0;
|
||||
this->pf.amask = 0;
|
||||
}
|
||||
|
||||
void DDSHeader::setPixelFormat(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask)
|
||||
{
|
||||
// Make sure the masks are correct.
|
||||
nvCheck((rmask & gmask) == 0);
|
||||
nvCheck((rmask & bmask) == 0);
|
||||
nvCheck((rmask & amask) == 0);
|
||||
nvCheck((gmask & bmask) == 0);
|
||||
nvCheck((gmask & amask) == 0);
|
||||
nvCheck((bmask & amask) == 0);
|
||||
|
||||
this->pf.flags = DDPF_RGB;
|
||||
|
||||
if (amask != 0) {
|
||||
this->pf.flags |= DDPF_ALPHAPIXELS;
|
||||
}
|
||||
|
||||
if (bitcount == 0)
|
||||
{
|
||||
// Compute bit count from the masks.
|
||||
uint total = rmask | gmask | bmask | amask;
|
||||
while(total != 0) {
|
||||
bitcount++;
|
||||
total >>= 1;
|
||||
}
|
||||
// @@ Align to 8?
|
||||
}
|
||||
|
||||
this->pf.fourcc = 0;
|
||||
this->pf.bitcount = bitcount;
|
||||
this->pf.rmask = rmask;
|
||||
this->pf.gmask = gmask;
|
||||
this->pf.bmask = bmask;
|
||||
this->pf.amask = amask;
|
||||
}
|
||||
|
||||
|
||||
void DDSHeader::swapBytes()
|
||||
{
|
||||
this->fourcc = POSH_LittleU32(this->fourcc);
|
||||
this->size = POSH_LittleU32(this->size);
|
||||
this->flags = POSH_LittleU32(this->flags);
|
||||
this->height = POSH_LittleU32(this->height);
|
||||
this->width = POSH_LittleU32(this->width);
|
||||
this->pitch = POSH_LittleU32(this->pitch);
|
||||
this->depth = POSH_LittleU32(this->depth);
|
||||
this->mipmapcount = POSH_LittleU32(this->mipmapcount);
|
||||
|
||||
for(int i = 0; i < 11; i++) {
|
||||
this->reserved[i] = POSH_LittleU32(this->reserved[i]);
|
||||
}
|
||||
|
||||
this->pf.size = POSH_LittleU32(this->pf.size);
|
||||
this->pf.flags = POSH_LittleU32(this->pf.flags);
|
||||
this->pf.fourcc = POSH_LittleU32(this->pf.fourcc);
|
||||
this->pf.bitcount = POSH_LittleU32(this->pf.bitcount);
|
||||
this->pf.rmask = POSH_LittleU32(this->pf.rmask);
|
||||
this->pf.gmask = POSH_LittleU32(this->pf.gmask);
|
||||
this->pf.bmask = POSH_LittleU32(this->pf.bmask);
|
||||
this->pf.amask = POSH_LittleU32(this->pf.amask);
|
||||
this->caps.caps1 = POSH_LittleU32(this->caps.caps1);
|
||||
this->caps.caps2 = POSH_LittleU32(this->caps.caps2);
|
||||
this->caps.caps3 = POSH_LittleU32(this->caps.caps3);
|
||||
this->caps.caps4 = POSH_LittleU32(this->caps.caps4);
|
||||
this->notused = POSH_LittleU32(this->notused);
|
||||
}
|
||||
|
||||
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#include <nvcore/Debug.h>
|
||||
#include <nvcore/Containers.h> // max
|
||||
#include <nvcore/StdStream.h>
|
||||
|
||||
#include <nvimage/DirectDrawSurface.h>
|
||||
#include <nvimage/ColorBlock.h>
|
||||
#include <nvimage/Image.h>
|
||||
#include <nvimage/BlockDXT.h>
|
||||
|
||||
#include <string.h> // memset
|
||||
|
||||
|
||||
using namespace nv;
|
||||
|
||||
#if !defined(MAKEFOURCC)
|
||||
# define MAKEFOURCC(ch0, ch1, ch2, ch3) \
|
||||
(uint(uint8(ch0)) | (uint(uint8(ch1)) << 8) | \
|
||||
(uint(uint8(ch2)) << 16) | (uint(uint8(ch3)) << 24 ))
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
static const uint FOURCC_DDS = MAKEFOURCC('D', 'D', 'S', ' ');
|
||||
static const uint FOURCC_DXT1 = MAKEFOURCC('D', 'X', 'T', '1');
|
||||
static const uint FOURCC_DXT2 = MAKEFOURCC('D', 'X', 'T', '2');
|
||||
static const uint FOURCC_DXT3 = MAKEFOURCC('D', 'X', 'T', '3');
|
||||
static const uint FOURCC_DXT4 = MAKEFOURCC('D', 'X', 'T', '4');
|
||||
static const uint FOURCC_DXT5 = MAKEFOURCC('D', 'X', 'T', '5');
|
||||
static const uint FOURCC_RXGB = MAKEFOURCC('R', 'X', 'G', 'B');
|
||||
static const uint FOURCC_ATI1 = MAKEFOURCC('A', 'T', 'I', '1');
|
||||
static const uint FOURCC_ATI2 = MAKEFOURCC('A', 'T', 'I', '2');
|
||||
static const uint FOURCC_BC3N = MAKEFOURCC('B', 'C', '3', 'N');
|
||||
|
||||
static const uint DDSD_CAPS = 0x00000001U;
|
||||
static const uint DDSD_PIXELFORMAT = 0x00001000U;
|
||||
static const uint DDSD_WIDTH = 0x00000004U;
|
||||
static const uint DDSD_HEIGHT = 0x00000002U;
|
||||
static const uint DDSD_PITCH = 0x00000008U;
|
||||
static const uint DDSD_MIPMAPCOUNT = 0x00020000U;
|
||||
static const uint DDSD_LINEARSIZE = 0x00080000U;
|
||||
static const uint DDSD_DEPTH = 0x00800000U;
|
||||
|
||||
static const uint DDSCAPS_COMPLEX = 0x00000008U;
|
||||
static const uint DDSCAPS_TEXTURE = 0x00001000U;
|
||||
static const uint DDSCAPS_MIPMAP = 0x00400000U;
|
||||
static const uint DDSCAPS2_VOLUME = 0x00200000U;
|
||||
static const uint DDSCAPS2_CUBEMAP = 0x00000200U;
|
||||
|
||||
static const uint DDSCAPS2_CUBEMAP_POSITIVEX = 0x00000400U;
|
||||
static const uint DDSCAPS2_CUBEMAP_NEGATIVEX = 0x00000800U;
|
||||
static const uint DDSCAPS2_CUBEMAP_POSITIVEY = 0x00001000U;
|
||||
static const uint DDSCAPS2_CUBEMAP_NEGATIVEY = 0x00002000U;
|
||||
static const uint DDSCAPS2_CUBEMAP_POSITIVEZ = 0x00004000U;
|
||||
static const uint DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x00008000U;
|
||||
static const uint DDSCAPS2_CUBEMAP_ALL_FACES = 0x0000FC00U;
|
||||
|
||||
static const uint DDPF_RGB = 0x00000040U;
|
||||
static const uint DDPF_FOURCC = 0x00000004U;
|
||||
static const uint DDPF_ALPHAPIXELS = 0x00000001U;
|
||||
static const uint DDPF_NORMAL = 0x80000000U; // @@ Custom flag.
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace nv
|
||||
{
|
||||
static Stream & operator<< (Stream & s, DDSPixelFormat & pf)
|
||||
{
|
||||
s << pf.size;
|
||||
s << pf.flags;
|
||||
s << pf.fourcc;
|
||||
s << pf.bitcount;
|
||||
s << pf.rmask;
|
||||
s << pf.gmask;
|
||||
s << pf.bmask;
|
||||
s << pf.amask;
|
||||
return s;
|
||||
}
|
||||
|
||||
static Stream & operator<< (Stream & s, DDSCaps & caps)
|
||||
{
|
||||
s << caps.caps1;
|
||||
s << caps.caps2;
|
||||
s << caps.caps3;
|
||||
s << caps.caps4;
|
||||
return s;
|
||||
}
|
||||
|
||||
static Stream & operator<< (Stream & s, DDSHeader & header)
|
||||
{
|
||||
nvStaticCheck(sizeof(DDSHeader) == 128);
|
||||
s << header.fourcc;
|
||||
s << header.size;
|
||||
s << header.flags;
|
||||
s << header.height;
|
||||
s << header.width;
|
||||
s << header.pitch;
|
||||
s << header.depth;
|
||||
s << header.mipmapcount;
|
||||
s.serialize(header.reserved, 11 * sizeof(uint));
|
||||
s << header.pf;
|
||||
s << header.caps;
|
||||
s << header.notused;
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
DDSHeader::DDSHeader()
|
||||
{
|
||||
this->fourcc = FOURCC_DDS;
|
||||
this->size = 124;
|
||||
this->flags = (DDSD_CAPS|DDSD_PIXELFORMAT);
|
||||
this->height = 0;
|
||||
this->width = 0;
|
||||
this->pitch = 0;
|
||||
this->depth = 0;
|
||||
this->mipmapcount = 0;
|
||||
memset(this->reserved, 0, sizeof(this->reserved));
|
||||
|
||||
// Store version information on the reserved header attributes.
|
||||
this->reserved[9] = MAKEFOURCC('N', 'V', 'T', 'T');
|
||||
this->reserved[10] = (0 << 16) | (1 << 8) | (0); // major.minor.revision
|
||||
|
||||
this->pf.size = 32;
|
||||
this->pf.flags = 0;
|
||||
this->pf.fourcc = 0;
|
||||
this->pf.bitcount = 0;
|
||||
this->pf.rmask = 0;
|
||||
this->pf.gmask = 0;
|
||||
this->pf.bmask = 0;
|
||||
this->pf.amask = 0;
|
||||
this->caps.caps1 = DDSCAPS_TEXTURE;
|
||||
this->caps.caps2 = 0;
|
||||
this->caps.caps3 = 0;
|
||||
this->caps.caps4 = 0;
|
||||
this->notused = 0;
|
||||
}
|
||||
|
||||
void DDSHeader::setWidth(uint w)
|
||||
{
|
||||
this->flags |= DDSD_WIDTH;
|
||||
this->width = w;
|
||||
}
|
||||
|
||||
void DDSHeader::setHeight(uint h)
|
||||
{
|
||||
this->flags |= DDSD_HEIGHT;
|
||||
this->height = h;
|
||||
}
|
||||
|
||||
void DDSHeader::setDepth(uint d)
|
||||
{
|
||||
this->flags |= DDSD_DEPTH;
|
||||
this->height = d;
|
||||
}
|
||||
|
||||
void DDSHeader::setMipmapCount(uint count)
|
||||
{
|
||||
if (count == 0)
|
||||
{
|
||||
this->flags &= ~DDSD_MIPMAPCOUNT;
|
||||
this->mipmapcount = 0;
|
||||
|
||||
if (this->caps.caps2 == 0) {
|
||||
this->caps.caps1 = DDSCAPS_TEXTURE;
|
||||
}
|
||||
else {
|
||||
this->caps.caps1 = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this->flags |= DDSD_MIPMAPCOUNT;
|
||||
this->mipmapcount = count;
|
||||
|
||||
this->caps.caps1 |= DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
|
||||
}
|
||||
}
|
||||
|
||||
void DDSHeader::setTexture2D()
|
||||
{
|
||||
// nothing to do here.
|
||||
}
|
||||
|
||||
void DDSHeader::setTexture3D()
|
||||
{
|
||||
this->caps.caps2 = DDSCAPS2_VOLUME;
|
||||
}
|
||||
|
||||
void DDSHeader::setTextureCube()
|
||||
{
|
||||
this->caps.caps1 |= DDSCAPS_COMPLEX;
|
||||
this->caps.caps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALL_FACES;
|
||||
}
|
||||
|
||||
void DDSHeader::setLinearSize(uint size)
|
||||
{
|
||||
this->flags &= ~DDSD_PITCH;
|
||||
this->flags |= DDSD_LINEARSIZE;
|
||||
this->pitch = size;
|
||||
}
|
||||
|
||||
void DDSHeader::setPitch(uint pitch)
|
||||
{
|
||||
this->flags &= ~DDSD_LINEARSIZE;
|
||||
this->flags |= DDSD_PITCH;
|
||||
this->pitch = pitch;
|
||||
}
|
||||
|
||||
void DDSHeader::setFourCC(uint8 c0, uint8 c1, uint8 c2, uint8 c3)
|
||||
{
|
||||
// set fourcc pixel format.
|
||||
this->pf.flags = DDPF_FOURCC;
|
||||
this->pf.fourcc = MAKEFOURCC(c0, c1, c2, c3);
|
||||
this->pf.bitcount = 0;
|
||||
this->pf.rmask = 0;
|
||||
this->pf.gmask = 0;
|
||||
this->pf.bmask = 0;
|
||||
this->pf.amask = 0;
|
||||
}
|
||||
|
||||
void DDSHeader::setPixelFormat(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask)
|
||||
{
|
||||
// Make sure the masks are correct.
|
||||
nvCheck((rmask & gmask) == 0);
|
||||
nvCheck((rmask & bmask) == 0);
|
||||
nvCheck((rmask & amask) == 0);
|
||||
nvCheck((gmask & bmask) == 0);
|
||||
nvCheck((gmask & amask) == 0);
|
||||
nvCheck((bmask & amask) == 0);
|
||||
|
||||
this->pf.flags = DDPF_RGB;
|
||||
|
||||
if (amask != 0) {
|
||||
this->pf.flags |= DDPF_ALPHAPIXELS;
|
||||
}
|
||||
|
||||
if (bitcount == 0)
|
||||
{
|
||||
// Compute bit count from the masks.
|
||||
uint total = rmask | gmask | bmask | amask;
|
||||
while(total != 0) {
|
||||
bitcount++;
|
||||
total >>= 1;
|
||||
}
|
||||
// @@ Align to 8?
|
||||
}
|
||||
|
||||
this->pf.fourcc = 0;
|
||||
this->pf.bitcount = bitcount;
|
||||
this->pf.rmask = rmask;
|
||||
this->pf.gmask = gmask;
|
||||
this->pf.bmask = bmask;
|
||||
this->pf.amask = amask;
|
||||
}
|
||||
|
||||
void DDSHeader::setNormalFlag(bool b)
|
||||
{
|
||||
if (b) this->pf.flags |= DDPF_NORMAL;
|
||||
else this->pf.flags &= ~DDPF_NORMAL;
|
||||
}
|
||||
|
||||
void DDSHeader::swapBytes()
|
||||
{
|
||||
this->fourcc = POSH_LittleU32(this->fourcc);
|
||||
this->size = POSH_LittleU32(this->size);
|
||||
this->flags = POSH_LittleU32(this->flags);
|
||||
this->height = POSH_LittleU32(this->height);
|
||||
this->width = POSH_LittleU32(this->width);
|
||||
this->pitch = POSH_LittleU32(this->pitch);
|
||||
this->depth = POSH_LittleU32(this->depth);
|
||||
this->mipmapcount = POSH_LittleU32(this->mipmapcount);
|
||||
|
||||
for(int i = 0; i < 11; i++) {
|
||||
this->reserved[i] = POSH_LittleU32(this->reserved[i]);
|
||||
}
|
||||
|
||||
this->pf.size = POSH_LittleU32(this->pf.size);
|
||||
this->pf.flags = POSH_LittleU32(this->pf.flags);
|
||||
this->pf.fourcc = POSH_LittleU32(this->pf.fourcc);
|
||||
this->pf.bitcount = POSH_LittleU32(this->pf.bitcount);
|
||||
this->pf.rmask = POSH_LittleU32(this->pf.rmask);
|
||||
this->pf.gmask = POSH_LittleU32(this->pf.gmask);
|
||||
this->pf.bmask = POSH_LittleU32(this->pf.bmask);
|
||||
this->pf.amask = POSH_LittleU32(this->pf.amask);
|
||||
this->caps.caps1 = POSH_LittleU32(this->caps.caps1);
|
||||
this->caps.caps2 = POSH_LittleU32(this->caps.caps2);
|
||||
this->caps.caps3 = POSH_LittleU32(this->caps.caps3);
|
||||
this->caps.caps4 = POSH_LittleU32(this->caps.caps4);
|
||||
this->notused = POSH_LittleU32(this->notused);
|
||||
}
|
||||
|
||||
|
||||
|
||||
DirectDrawSurface::DirectDrawSurface(const char * name) : stream(new StdInputStream(name))
|
||||
{
|
||||
if (!stream->isError())
|
||||
{
|
||||
(*stream) << header;
|
||||
}
|
||||
}
|
||||
|
||||
DirectDrawSurface::~DirectDrawSurface()
|
||||
{
|
||||
delete stream;
|
||||
}
|
||||
|
||||
bool DirectDrawSurface::isValid() const
|
||||
{
|
||||
if (stream->isError())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (header.fourcc != FOURCC_DDS || header.size != 124)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const uint required = (DDSD_WIDTH|DDSD_HEIGHT|DDSD_CAPS|DDSD_PIXELFORMAT);
|
||||
if( (header.flags & required) != required ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (header.pf.size != 32) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !(header.caps.caps1 & DDSCAPS_TEXTURE) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DirectDrawSurface::isSupported() const
|
||||
{
|
||||
nvDebugCheck(isValid());
|
||||
|
||||
if (header.pf.flags & DDPF_FOURCC)
|
||||
{
|
||||
if (header.pf.fourcc != FOURCC_DXT1 &&
|
||||
header.pf.fourcc != FOURCC_DXT2 &&
|
||||
header.pf.fourcc != FOURCC_DXT3 &&
|
||||
header.pf.fourcc != FOURCC_DXT4 &&
|
||||
header.pf.fourcc != FOURCC_DXT5 &&
|
||||
header.pf.fourcc != FOURCC_RXGB &&
|
||||
header.pf.fourcc != FOURCC_ATI1 &&
|
||||
header.pf.fourcc != FOURCC_ATI2 &&
|
||||
header.pf.fourcc != FOURCC_BC3N)
|
||||
{
|
||||
// Unknown fourcc code.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (header.pf.flags & DDPF_RGB)
|
||||
{
|
||||
if (header.pf.bitcount == 24)
|
||||
{
|
||||
}
|
||||
else if (header.pf.bitcount == 24)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unsupported pixel format.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isTextureCube() && (header.caps.caps2 & DDSCAPS2_CUBEMAP_ALL_FACES) != DDSCAPS2_CUBEMAP_ALL_FACES)
|
||||
{
|
||||
// Cubemaps must contain all faces.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isTexture3D())
|
||||
{
|
||||
// @@ 3D textures not supported yet.
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
uint DirectDrawSurface::mipmapCount() const
|
||||
{
|
||||
nvDebugCheck(isValid());
|
||||
if (header.flags & DDSD_MIPMAPCOUNT) return header.mipmapcount;
|
||||
else return 0;
|
||||
}
|
||||
|
||||
|
||||
uint DirectDrawSurface::width() const
|
||||
{
|
||||
nvDebugCheck(isValid());
|
||||
if (header.flags & DDSD_WIDTH) return header.width;
|
||||
else return 1;
|
||||
}
|
||||
|
||||
uint DirectDrawSurface::height() const
|
||||
{
|
||||
nvDebugCheck(isValid());
|
||||
if (header.flags & DDSD_HEIGHT) return header.height;
|
||||
else return 1;
|
||||
}
|
||||
|
||||
uint DirectDrawSurface::depth() const
|
||||
{
|
||||
nvDebugCheck(isValid());
|
||||
if (header.flags & DDSD_DEPTH) return header.depth;
|
||||
else return 1;
|
||||
}
|
||||
|
||||
bool DirectDrawSurface::isTexture2D() const
|
||||
{
|
||||
nvDebugCheck(isValid());
|
||||
return !isTexture3D() && !isTextureCube();
|
||||
}
|
||||
|
||||
bool DirectDrawSurface::isTexture3D() const
|
||||
{
|
||||
nvDebugCheck(isValid());
|
||||
return (header.caps.caps2 & DDSCAPS2_VOLUME) != 0;
|
||||
}
|
||||
|
||||
bool DirectDrawSurface::isTextureCube() const
|
||||
{
|
||||
nvDebugCheck(isValid());
|
||||
return (header.caps.caps2 & DDSCAPS2_CUBEMAP) != 0;
|
||||
}
|
||||
|
||||
void DirectDrawSurface::mipmap(Image * img, uint face, uint mipmap)
|
||||
{
|
||||
nvDebugCheck(isValid());
|
||||
|
||||
stream->seek(offset(face, mipmap));
|
||||
|
||||
uint w = width();
|
||||
uint h = height();
|
||||
|
||||
// Compute width and height.
|
||||
for (uint m = 0; m < mipmap; m++)
|
||||
{
|
||||
w = max(1U, w / 2);
|
||||
h = max(1U, h / 2);
|
||||
}
|
||||
|
||||
img->allocate(w, h);
|
||||
|
||||
// readLinearImage(stream, img);
|
||||
// readBlockImage(stream, img);
|
||||
}
|
||||
|
||||
|
||||
void DirectDrawSurface::readLinearImage(Stream * stream, Image * img)
|
||||
{
|
||||
nvDebugCheck(stream != NULL);
|
||||
nvDebugCheck(img != NULL);
|
||||
|
||||
}
|
||||
|
||||
void DirectDrawSurface::readBlockImage(Stream * stream, Image * img)
|
||||
{
|
||||
nvDebugCheck(stream != NULL);
|
||||
nvDebugCheck(img != NULL);
|
||||
|
||||
const uint bw = (img->width() + 3) / 4;
|
||||
const uint bh = (img->height() + 3) / 4;
|
||||
|
||||
for (uint by = 0; by < bh; by++)
|
||||
{
|
||||
for (uint bx = 0; bx < bw; bx++)
|
||||
{
|
||||
ColorBlock block;
|
||||
|
||||
// Read color block.
|
||||
readBlock(stream, &block);
|
||||
|
||||
// Write color block.
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DirectDrawSurface::readBlock(Stream * stream, ColorBlock * rgba)
|
||||
{
|
||||
nvDebugCheck(stream != NULL);
|
||||
nvDebugCheck(rgba != NULL);
|
||||
|
||||
if (header.pf.fourcc == FOURCC_DXT1 ||
|
||||
header.pf.fourcc == FOURCC_DXT2 ||
|
||||
header.pf.fourcc == FOURCC_DXT3 ||
|
||||
header.pf.fourcc == FOURCC_DXT4 ||
|
||||
header.pf.fourcc == FOURCC_DXT5 ||
|
||||
header.pf.fourcc == FOURCC_RXGB ||
|
||||
header.pf.fourcc != FOURCC_BC3N)
|
||||
{
|
||||
// Read DXT1 block.
|
||||
BlockDXT1 block;
|
||||
|
||||
if (header.pf.fourcc == FOURCC_BC3N)
|
||||
{
|
||||
// Write G only
|
||||
}
|
||||
else
|
||||
{
|
||||
// Write RGB.
|
||||
}
|
||||
}
|
||||
|
||||
if (header.pf.fourcc == FOURCC_ATI2)
|
||||
{
|
||||
// Read DXT5 alpha block.
|
||||
// Write R.
|
||||
}
|
||||
|
||||
if (header.pf.fourcc == FOURCC_DXT2 ||
|
||||
header.pf.fourcc == FOURCC_DXT3)
|
||||
{
|
||||
// Read DXT3 alpha block.
|
||||
}
|
||||
|
||||
if (header.pf.fourcc == FOURCC_DXT4 ||
|
||||
header.pf.fourcc == FOURCC_DXT5 ||
|
||||
header.pf.fourcc == FOURCC_RXGB)
|
||||
{
|
||||
// Read DXT5 alpha block.
|
||||
}
|
||||
|
||||
if (header.pf.fourcc == FOURCC_RXGB)
|
||||
{
|
||||
// swap G & A
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint DirectDrawSurface::blockSize() const
|
||||
{
|
||||
switch(header.pf.fourcc)
|
||||
{
|
||||
case FOURCC_DXT1:
|
||||
case FOURCC_ATI1:
|
||||
return 8;
|
||||
case FOURCC_DXT2:
|
||||
case FOURCC_DXT3:
|
||||
case FOURCC_DXT4:
|
||||
case FOURCC_DXT5:
|
||||
case FOURCC_RXGB:
|
||||
case FOURCC_ATI2:
|
||||
case FOURCC_BC3N:
|
||||
return 16;
|
||||
};
|
||||
|
||||
// This should never happen.
|
||||
nvDebugCheck(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint DirectDrawSurface::mipmapSize(uint mipmap) const
|
||||
{
|
||||
uint w = width();
|
||||
uint h = height();
|
||||
uint d = depth();
|
||||
|
||||
for (uint m = 0; m < mipmap; m++)
|
||||
{
|
||||
w = max(1U, w / 2);
|
||||
h = max(1U, h / 2);
|
||||
d = max(1U, d / 2);
|
||||
}
|
||||
|
||||
if (header.pf.flags & DDPF_FOURCC)
|
||||
{
|
||||
// @@ How are 3D textures aligned?
|
||||
w = (w + 3) / 4;
|
||||
h = (h + 3) / 4;
|
||||
return blockSize() * w * h;
|
||||
}
|
||||
else
|
||||
{
|
||||
nvDebugCheck(header.pf.flags & DDPF_RGB);
|
||||
|
||||
// Align pixels to bytes.
|
||||
uint byteCount = (header.pf.bitcount + 7) / 8;
|
||||
|
||||
// Align pitch to 4 bytes.
|
||||
uint pitch = 4 * ((w * byteCount + 3) / 4);
|
||||
|
||||
return pitch * h * d;
|
||||
}
|
||||
}
|
||||
|
||||
uint DirectDrawSurface::faceSize() const
|
||||
{
|
||||
const uint count = mipmapCount();
|
||||
uint size = 0;
|
||||
|
||||
for (uint m = 0; m < count; m++)
|
||||
{
|
||||
size += mipmapSize(m);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
uint DirectDrawSurface::offset(const uint face, const uint mipmap)
|
||||
{
|
||||
uint size = sizeof(DDSHeader);
|
||||
|
||||
if (face != 0)
|
||||
{
|
||||
size += face * faceSize();
|
||||
}
|
||||
|
||||
for (uint m = 0; m < mipmap; m++)
|
||||
{
|
||||
size += mipmapSize(m);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -1,85 +1,127 @@
|
||||
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#ifndef NV_IMAGE_DIRECTDRAWSURFACE_H
|
||||
#define NV_IMAGE_DIRECTDRAWSURFACE_H
|
||||
|
||||
#include <nvcore/nvcore.h>
|
||||
|
||||
namespace nv
|
||||
{
|
||||
|
||||
struct DDSPixelFormat {
|
||||
uint size;
|
||||
uint flags;
|
||||
uint fourcc;
|
||||
uint bitcount;
|
||||
uint rmask;
|
||||
uint gmask;
|
||||
uint bmask;
|
||||
uint amask;
|
||||
};
|
||||
|
||||
struct DDSCaps {
|
||||
uint caps1;
|
||||
uint caps2;
|
||||
uint caps3;
|
||||
uint caps4;
|
||||
};
|
||||
|
||||
/// DDS file header.
|
||||
struct DDSHeader {
|
||||
uint fourcc;
|
||||
uint size;
|
||||
uint flags;
|
||||
uint height;
|
||||
uint width;
|
||||
uint pitch;
|
||||
uint depth;
|
||||
uint mipmapcount;
|
||||
uint reserved[11];
|
||||
DDSPixelFormat pf;
|
||||
DDSCaps caps;
|
||||
uint notused;
|
||||
|
||||
// Helper methods.
|
||||
DDSHeader();
|
||||
void setWidth(uint w);
|
||||
void setHeight(uint h);
|
||||
void setDepth(uint d);
|
||||
void setMipmapCount(uint count);
|
||||
void setLinearSize(uint size);
|
||||
void setPitch(uint pitch);
|
||||
void setFourCC(uint8 c0, uint8 c1, uint8 c2, uint8 c3);
|
||||
void setPixelFormat(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask);
|
||||
void setTexture2D();
|
||||
void setTexture3D();
|
||||
void setTextureCube();
|
||||
|
||||
void swapBytes();
|
||||
};
|
||||
|
||||
|
||||
} // nv namespace
|
||||
|
||||
#endif // NV_IMAGE_DIRECTDRAWSURFACE_H
|
||||
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#ifndef NV_IMAGE_DIRECTDRAWSURFACE_H
|
||||
#define NV_IMAGE_DIRECTDRAWSURFACE_H
|
||||
|
||||
#include <nvcore/nvcore.h>
|
||||
|
||||
namespace nv
|
||||
{
|
||||
class Image;
|
||||
class Stream;
|
||||
struct ColorBlock;
|
||||
|
||||
struct DDSPixelFormat {
|
||||
uint size;
|
||||
uint flags;
|
||||
uint fourcc;
|
||||
uint bitcount;
|
||||
uint rmask;
|
||||
uint gmask;
|
||||
uint bmask;
|
||||
uint amask;
|
||||
};
|
||||
|
||||
struct DDSCaps {
|
||||
uint caps1;
|
||||
uint caps2;
|
||||
uint caps3;
|
||||
uint caps4;
|
||||
};
|
||||
|
||||
/// DDS file header.
|
||||
struct DDSHeader {
|
||||
uint fourcc;
|
||||
uint size;
|
||||
uint flags;
|
||||
uint height;
|
||||
uint width;
|
||||
uint pitch;
|
||||
uint depth;
|
||||
uint mipmapcount;
|
||||
uint reserved[11];
|
||||
DDSPixelFormat pf;
|
||||
DDSCaps caps;
|
||||
uint notused;
|
||||
|
||||
// Helper methods.
|
||||
DDSHeader();
|
||||
|
||||
void setWidth(uint w);
|
||||
void setHeight(uint h);
|
||||
void setDepth(uint d);
|
||||
void setMipmapCount(uint count);
|
||||
void setTexture2D();
|
||||
void setTexture3D();
|
||||
void setTextureCube();
|
||||
void setLinearSize(uint size);
|
||||
void setPitch(uint pitch);
|
||||
void setFourCC(uint8 c0, uint8 c1, uint8 c2, uint8 c3);
|
||||
void setPixelFormat(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask);
|
||||
void setNormalFlag(bool b);
|
||||
|
||||
void swapBytes();
|
||||
};
|
||||
|
||||
/// DirectDraw Surface. (DDS)
|
||||
class DirectDrawSurface
|
||||
{
|
||||
public:
|
||||
DirectDrawSurface(const char * file);
|
||||
~DirectDrawSurface();
|
||||
|
||||
bool isValid() const;
|
||||
bool isSupported() const;
|
||||
|
||||
uint mipmapCount() const;
|
||||
uint width() const;
|
||||
uint height() const;
|
||||
uint depth() const;
|
||||
bool isTexture2D() const;
|
||||
bool isTexture3D() const;
|
||||
bool isTextureCube() const;
|
||||
|
||||
void mipmap(Image * img, uint f, uint m);
|
||||
|
||||
private:
|
||||
|
||||
uint blockSize() const;
|
||||
uint faceSize() const;
|
||||
uint mipmapSize(uint m) const;
|
||||
|
||||
uint offset(uint f, uint m);
|
||||
|
||||
void readLinearImage(Stream * stream, Image * img);
|
||||
void readBlockImage(Stream * stream, Image * img);
|
||||
void readBlock(Stream * stream, ColorBlock * rgba);
|
||||
|
||||
|
||||
private:
|
||||
Stream * const stream;
|
||||
DDSHeader header;
|
||||
};
|
||||
|
||||
} // nv namespace
|
||||
|
||||
#endif // NV_IMAGE_DIRECTDRAWSURFACE_H
|
||||
|
@ -22,7 +22,7 @@ namespace nv
|
||||
Spline,
|
||||
Lanczos,
|
||||
Mitchell,
|
||||
Kaiser,
|
||||
Kaiser, // Kaiser-windowed sinc filter
|
||||
Num
|
||||
};
|
||||
|
||||
|
@ -1,125 +1,124 @@
|
||||
// This code is in the public domain -- castanyo@yahoo.es
|
||||
|
||||
#include <nvcore/Debug.h>
|
||||
#include <nvcore/Ptr.h>
|
||||
|
||||
#include <nvmath/Color.h>
|
||||
|
||||
#include <nvimage/Image.h>
|
||||
#include <nvimage/ImageIO.h>
|
||||
|
||||
|
||||
using namespace nv;
|
||||
|
||||
Image::Image() : m_width(0), m_height(0), m_format(Format_RGB), m_data(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
Image::~Image()
|
||||
{
|
||||
free();
|
||||
}
|
||||
|
||||
void Image::allocate(uint w, uint h)
|
||||
{
|
||||
free();
|
||||
m_width = w;
|
||||
m_height = h;
|
||||
m_data = new Color32[w*h];
|
||||
}
|
||||
|
||||
bool Image::load(const char * name)
|
||||
{
|
||||
free();
|
||||
|
||||
AutoPtr<Image> img(ImageIO::load(name));
|
||||
if (img == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
swap(m_width, img->m_width);
|
||||
swap(m_height, img->m_height);
|
||||
swap(m_format, img->m_format);
|
||||
swap(m_data, img->m_data);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Image::wrap(void * data, uint w, uint h)
|
||||
{
|
||||
free();
|
||||
m_data = (Color32 *)data;
|
||||
m_width = w;
|
||||
m_height = h;
|
||||
}
|
||||
|
||||
void Image::unwrap()
|
||||
{
|
||||
m_data = NULL;
|
||||
m_width = 0;
|
||||
m_height = 0;
|
||||
}
|
||||
|
||||
|
||||
void Image::free()
|
||||
{
|
||||
delete m_data;
|
||||
m_data = NULL;
|
||||
}
|
||||
|
||||
|
||||
uint Image::width() const
|
||||
{
|
||||
return m_width;
|
||||
}
|
||||
|
||||
uint Image::height() const
|
||||
{
|
||||
return m_height;
|
||||
}
|
||||
|
||||
const Color32 * Image::scanline(uint h) const
|
||||
{
|
||||
nvDebugCheck(h < m_height);
|
||||
return m_data + h * m_width;
|
||||
}
|
||||
|
||||
Color32 * Image::scanline(uint h)
|
||||
{
|
||||
nvDebugCheck(h < m_height);
|
||||
return m_data + h * m_width;
|
||||
}
|
||||
|
||||
const Color32 * Image::pixels() const
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
Color32 * Image::pixels()
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
const Color32 & Image::pixel(uint idx) const
|
||||
{
|
||||
nvDebugCheck(idx < m_width * m_height);
|
||||
return m_data[idx];
|
||||
}
|
||||
|
||||
Color32 & Image::pixel(uint idx)
|
||||
{
|
||||
nvDebugCheck(idx < m_width * m_height);
|
||||
return m_data[idx];
|
||||
}
|
||||
|
||||
|
||||
Image::Format Image::format() const
|
||||
{
|
||||
return m_format;
|
||||
}
|
||||
|
||||
void Image::setFormat(Image::Format f)
|
||||
{
|
||||
m_format = f;
|
||||
}
|
||||
|
||||
// This code is in the public domain -- castanyo@yahoo.es
|
||||
|
||||
#include <nvcore/Debug.h>
|
||||
#include <nvcore/Ptr.h>
|
||||
|
||||
#include <nvmath/Color.h>
|
||||
|
||||
#include <nvimage/Image.h>
|
||||
#include <nvimage/ImageIO.h>
|
||||
|
||||
|
||||
using namespace nv;
|
||||
|
||||
Image::Image() : m_width(0), m_height(0), m_format(Format_RGB), m_data(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
Image::~Image()
|
||||
{
|
||||
free();
|
||||
}
|
||||
|
||||
void Image::allocate(uint w, uint h)
|
||||
{
|
||||
m_width = w;
|
||||
m_height = h;
|
||||
m_data = (Color32 *)realloc(m_data, w * h * sizeof(Color32));
|
||||
}
|
||||
|
||||
bool Image::load(const char * name)
|
||||
{
|
||||
free();
|
||||
|
||||
AutoPtr<Image> img(ImageIO::load(name));
|
||||
if (img == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
swap(m_width, img->m_width);
|
||||
swap(m_height, img->m_height);
|
||||
swap(m_format, img->m_format);
|
||||
swap(m_data, img->m_data);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Image::wrap(void * data, uint w, uint h)
|
||||
{
|
||||
free();
|
||||
m_data = (Color32 *)data;
|
||||
m_width = w;
|
||||
m_height = h;
|
||||
}
|
||||
|
||||
void Image::unwrap()
|
||||
{
|
||||
m_data = NULL;
|
||||
m_width = 0;
|
||||
m_height = 0;
|
||||
}
|
||||
|
||||
|
||||
void Image::free()
|
||||
{
|
||||
::free(m_data);
|
||||
m_data = NULL;
|
||||
}
|
||||
|
||||
|
||||
uint Image::width() const
|
||||
{
|
||||
return m_width;
|
||||
}
|
||||
|
||||
uint Image::height() const
|
||||
{
|
||||
return m_height;
|
||||
}
|
||||
|
||||
const Color32 * Image::scanline(uint h) const
|
||||
{
|
||||
nvDebugCheck(h < m_height);
|
||||
return m_data + h * m_width;
|
||||
}
|
||||
|
||||
Color32 * Image::scanline(uint h)
|
||||
{
|
||||
nvDebugCheck(h < m_height);
|
||||
return m_data + h * m_width;
|
||||
}
|
||||
|
||||
const Color32 * Image::pixels() const
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
Color32 * Image::pixels()
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
const Color32 & Image::pixel(uint idx) const
|
||||
{
|
||||
nvDebugCheck(idx < m_width * m_height);
|
||||
return m_data[idx];
|
||||
}
|
||||
|
||||
Color32 & Image::pixel(uint idx)
|
||||
{
|
||||
nvDebugCheck(idx < m_width * m_height);
|
||||
return m_data[idx];
|
||||
}
|
||||
|
||||
|
||||
Image::Format Image::format() const
|
||||
{
|
||||
return m_format;
|
||||
}
|
||||
|
||||
void Image::setFormat(Image::Format f)
|
||||
{
|
||||
m_format = f;
|
||||
}
|
||||
|
||||
|
@ -1,138 +1,138 @@
|
||||
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#include <nvcore/Ptr.h>
|
||||
|
||||
#include <nvmath/Color.h>
|
||||
|
||||
#include <nvimage/NormalMap.h>
|
||||
#include <nvimage/Filter.h>
|
||||
#include <nvimage/FloatImage.h>
|
||||
#include <nvimage/Image.h>
|
||||
|
||||
using namespace nv;
|
||||
|
||||
// Create normal map using the given kernels.
|
||||
static FloatImage * createNormalMap(const Image * img, FloatImage::WrapMode wm, Vector4::Arg heightWeights, const Kernel2 * kdu, const Kernel2 * kdv)
|
||||
{
|
||||
nvCheck(kdu != NULL);
|
||||
nvCheck(kdv != NULL);
|
||||
nvCheck(img != NULL);
|
||||
|
||||
const uint w = img->width();
|
||||
const uint h = img->height();
|
||||
|
||||
AutoPtr<FloatImage> fimage(new FloatImage());
|
||||
fimage->allocate(4, w, h);
|
||||
|
||||
// Compute height and store in alpha channel:
|
||||
float * alphaChannel = fimage->channel(3);
|
||||
for(uint i = 0; i < w*h; i++)
|
||||
{
|
||||
Vector4 color = toVector4(img->pixel(i));
|
||||
alphaChannel[i] = dot(color, heightWeights);
|
||||
}
|
||||
|
||||
float heightScale = 1.0f / 16.0f; // @@ Use a user defined factor.
|
||||
|
||||
for(uint y = 0; y < h; y++)
|
||||
{
|
||||
for(uint x = 0; x < w; x++)
|
||||
{
|
||||
const float du = fimage->applyKernel(kdu, x, y, 3, wm);
|
||||
const float dv = fimage->applyKernel(kdv, x, y, 3, wm);
|
||||
|
||||
Vector3 n = normalize(Vector3(du, dv, heightScale));
|
||||
|
||||
fimage->setPixel(0.5f * n.x() + 0.5f, x, y, 0);
|
||||
fimage->setPixel(0.5f * n.y() + 0.5f, x, y, 1);
|
||||
fimage->setPixel(0.5f * n.z() + 0.5f, x, y, 2);
|
||||
}
|
||||
}
|
||||
|
||||
return fimage.release();
|
||||
}
|
||||
|
||||
|
||||
/// Create normal map using the given filter.
|
||||
FloatImage * nv::createNormalMap(const Image * img, FloatImage::WrapMode wm, Vector4::Arg heightWeights, NormalMapFilter filter /*= Sobel3x3*/)
|
||||
{
|
||||
nvCheck(img != NULL);
|
||||
|
||||
// Init the kernels.
|
||||
Kernel2 * kdu = NULL;
|
||||
Kernel2 * kdv = NULL;
|
||||
|
||||
switch(filter)
|
||||
{
|
||||
case NormalMapFilter_Sobel3x3:
|
||||
kdu = new Kernel2(3);
|
||||
break;
|
||||
case NormalMapFilter_Sobel5x5:
|
||||
kdu = new Kernel2(5);
|
||||
break;
|
||||
case NormalMapFilter_Sobel7x7:
|
||||
kdu = new Kernel2(7);
|
||||
break;
|
||||
case NormalMapFilter_Sobel9x9:
|
||||
kdu = new Kernel2(9);
|
||||
break;
|
||||
default:
|
||||
nvDebugCheck(false);
|
||||
};
|
||||
|
||||
kdu->initSobel();
|
||||
kdu->normalize();
|
||||
|
||||
kdv = new Kernel2(*kdu);
|
||||
kdv->transpose();
|
||||
|
||||
return ::createNormalMap(img, wm, heightWeights, kdu, kdv);
|
||||
}
|
||||
|
||||
|
||||
/// Create normal map combining multiple sobel filters.
|
||||
FloatImage * nv::createNormalMap(const Image * img, FloatImage::WrapMode wm, Vector4::Arg heightWeights, Vector4::Arg filterWeights)
|
||||
{
|
||||
nvCheck(img != NULL);
|
||||
|
||||
Kernel2 * kdu = NULL;
|
||||
Kernel2 * kdv = NULL;
|
||||
|
||||
kdu = new Kernel2(9);
|
||||
kdu->initBlendedSobel(filterWeights);
|
||||
kdu->normalize();
|
||||
|
||||
kdv = new Kernel2(*kdu);
|
||||
kdv->transpose();
|
||||
|
||||
return ::createNormalMap(img, wm, heightWeights, kdu, kdv);
|
||||
}
|
||||
|
||||
/// Normalize the given image in place.
|
||||
void nv::normalize(FloatImage * img)
|
||||
{
|
||||
nvCheck(img != NULL);
|
||||
img->normalize(0);
|
||||
}
|
||||
|
||||
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#include <nvcore/Ptr.h>
|
||||
|
||||
#include <nvmath/Color.h>
|
||||
|
||||
#include <nvimage/NormalMap.h>
|
||||
#include <nvimage/Filter.h>
|
||||
#include <nvimage/FloatImage.h>
|
||||
#include <nvimage/Image.h>
|
||||
|
||||
using namespace nv;
|
||||
|
||||
// Create normal map using the given kernels.
|
||||
static FloatImage * createNormalMap(const Image * img, FloatImage::WrapMode wm, Vector4::Arg heightWeights, const Kernel2 * kdu, const Kernel2 * kdv)
|
||||
{
|
||||
nvCheck(kdu != NULL);
|
||||
nvCheck(kdv != NULL);
|
||||
nvCheck(img != NULL);
|
||||
|
||||
const uint w = img->width();
|
||||
const uint h = img->height();
|
||||
|
||||
AutoPtr<FloatImage> fimage(new FloatImage());
|
||||
fimage->allocate(4, w, h);
|
||||
|
||||
// Compute height and store in alpha channel:
|
||||
float * alphaChannel = fimage->channel(3);
|
||||
for(uint i = 0; i < w*h; i++)
|
||||
{
|
||||
Vector4 color = toVector4(img->pixel(i));
|
||||
alphaChannel[i] = dot(color, heightWeights);
|
||||
}
|
||||
|
||||
float heightScale = 1.0f / 16.0f; // @@ Use a user defined factor.
|
||||
|
||||
for(uint y = 0; y < h; y++)
|
||||
{
|
||||
for(uint x = 0; x < w; x++)
|
||||
{
|
||||
const float du = fimage->applyKernel(kdu, x, y, 3, wm);
|
||||
const float dv = fimage->applyKernel(kdv, x, y, 3, wm);
|
||||
|
||||
Vector3 n = normalize(Vector3(du, dv, heightScale));
|
||||
|
||||
fimage->setPixel(0.5f * n.x() + 0.5f, x, y, 0);
|
||||
fimage->setPixel(0.5f * n.y() + 0.5f, x, y, 1);
|
||||
fimage->setPixel(0.5f * n.z() + 0.5f, x, y, 2);
|
||||
}
|
||||
}
|
||||
|
||||
return fimage.release();
|
||||
}
|
||||
|
||||
|
||||
/// Create normal map using the given filter.
|
||||
FloatImage * nv::createNormalMap(const Image * img, FloatImage::WrapMode wm, Vector4::Arg heightWeights, NormalMapFilter filter /*= Sobel3x3*/)
|
||||
{
|
||||
nvCheck(img != NULL);
|
||||
|
||||
// Init the kernels.
|
||||
Kernel2 * kdu = NULL;
|
||||
Kernel2 * kdv = NULL;
|
||||
|
||||
switch(filter)
|
||||
{
|
||||
case NormalMapFilter_Sobel3x3:
|
||||
kdu = new Kernel2(3);
|
||||
break;
|
||||
case NormalMapFilter_Sobel5x5:
|
||||
kdu = new Kernel2(5);
|
||||
break;
|
||||
case NormalMapFilter_Sobel7x7:
|
||||
kdu = new Kernel2(7);
|
||||
break;
|
||||
case NormalMapFilter_Sobel9x9:
|
||||
kdu = new Kernel2(9);
|
||||
break;
|
||||
default:
|
||||
nvDebugCheck(false);
|
||||
};
|
||||
|
||||
kdu->initSobel();
|
||||
kdu->normalize();
|
||||
|
||||
kdv = new Kernel2(*kdu);
|
||||
kdv->transpose();
|
||||
|
||||
return ::createNormalMap(img, wm, heightWeights, kdu, kdv);
|
||||
}
|
||||
|
||||
|
||||
/// Create normal map combining multiple sobel filters.
|
||||
FloatImage * nv::createNormalMap(const Image * img, FloatImage::WrapMode wm, Vector4::Arg heightWeights, Vector4::Arg filterWeights)
|
||||
{
|
||||
nvCheck(img != NULL);
|
||||
|
||||
Kernel2 * kdu = NULL;
|
||||
Kernel2 * kdv = NULL;
|
||||
|
||||
kdu = new Kernel2(9);
|
||||
kdu->initBlendedSobel(filterWeights);
|
||||
kdu->normalize();
|
||||
|
||||
kdv = new Kernel2(*kdu);
|
||||
kdv->transpose();
|
||||
|
||||
return ::createNormalMap(img, wm, heightWeights, kdu, kdv);
|
||||
}
|
||||
|
||||
/// Normalize the given image in place.
|
||||
void nv::normalize(FloatImage * img)
|
||||
{
|
||||
nvCheck(img != NULL);
|
||||
img->normalize(0);
|
||||
}
|
||||
|
||||
|
@ -1,24 +1,24 @@
|
||||
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#ifndef NV_IMAGE_NORMALMAP_H
|
||||
|
98
src/nvimage/NormalMipmap.cpp
Normal file
98
src/nvimage/NormalMipmap.cpp
Normal file
@ -0,0 +1,98 @@
|
||||
// This code is in the public domain -- castanyo@yahoo.es
|
||||
|
||||
#include <nvcore/Ptr.h>
|
||||
|
||||
#include <nvmath/Montecarlo.h>
|
||||
#include <nvmath/SphericalHarmonic.h>
|
||||
|
||||
#include <nvimage/NormalMipmap.h>
|
||||
#include <nvimage/FloatImage.h>
|
||||
|
||||
using namespace nv;
|
||||
|
||||
FloatImage * nv::createNormalMipmapMap(const FloatImage * img)
|
||||
{
|
||||
nvDebugCheck(img != NULL);
|
||||
|
||||
uint w = img->width();
|
||||
uint h = img->height();
|
||||
|
||||
uint hw = w / 2;
|
||||
uint hh = h / 2;
|
||||
|
||||
FloatImage dotImg;
|
||||
dotImg.allocate(1, w, h);
|
||||
|
||||
FloatImage shImg;
|
||||
shImg.allocate(9, hw, hh);
|
||||
|
||||
SampleDistribution distribution(256);
|
||||
const uint sampleCount = distribution.sampleCount();
|
||||
|
||||
for (uint d = 0; d < sampleCount; d++)
|
||||
{
|
||||
const float * xChannel = img->channel(0);
|
||||
const float * yChannel = img->channel(1);
|
||||
const float * zChannel = img->channel(2);
|
||||
|
||||
Vector3 dir = distribution.sampleDir(d);
|
||||
|
||||
Sh2 basis;
|
||||
basis.eval(dir);
|
||||
|
||||
for(uint i = 0; i < w*h; i++)
|
||||
{
|
||||
Vector3 normal(xChannel[i], yChannel[i], zChannel[i]);
|
||||
normal = normalizeSafe(normal, Vector3(zero), 0.0f);
|
||||
|
||||
dotImg.setPixel(dot(dir, normal), d);
|
||||
}
|
||||
|
||||
// @@ It would be nice to have a fastDownSample that took an existing image as an argument, to avoid allocations.
|
||||
AutoPtr<FloatImage> dotMip(dotImg.fastDownSample());
|
||||
|
||||
for(uint p = 0; p < hw*hh; p++)
|
||||
{
|
||||
float f = dotMip->pixel(p);
|
||||
|
||||
// Project irradiance to sh basis and accumulate.
|
||||
for (uint i = 0; i < 9; i++)
|
||||
{
|
||||
float & sum = shImg.channel(i)[p];
|
||||
sum += f * basis.elemAt(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
FloatImage * normalMipmap = new FloatImage;
|
||||
normalMipmap->allocate(4, hw, hh);
|
||||
|
||||
// Precompute the clamped cosine radiance transfer.
|
||||
Sh2 prt;
|
||||
prt.cosineTransfer();
|
||||
|
||||
// Allocate outside the loop.
|
||||
Sh2 sh;
|
||||
|
||||
for(uint p = 0; p < hw*hh; p++)
|
||||
{
|
||||
for (uint i = 0; i < 9; i++)
|
||||
{
|
||||
sh.elemAt(i) = shImg.channel(i)[p];
|
||||
}
|
||||
|
||||
// Convolve sh irradiance by radiance transfer.
|
||||
sh *= prt;
|
||||
|
||||
// Now sh(0) is the ambient occlusion.
|
||||
// and sh(1) is the normal direction.
|
||||
|
||||
// Should we use SVD to fit only the normals to the SH?
|
||||
|
||||
}
|
||||
|
||||
return normalMipmap;
|
||||
}
|
||||
|
17
src/nvimage/NormalMipmap.h
Normal file
17
src/nvimage/NormalMipmap.h
Normal file
@ -0,0 +1,17 @@
|
||||
// This code is in the public domain -- castanyo@yahoo.es
|
||||
|
||||
#ifndef NV_IMAGE_NORMALMIPMAP_H
|
||||
#define NV_IMAGE_NORMALMIPMAP_H
|
||||
|
||||
#include <nvimage/nvimage.h>
|
||||
|
||||
|
||||
namespace nv
|
||||
{
|
||||
class FloatImage;
|
||||
|
||||
FloatImage * createNormalMipmapMap(const FloatImage * img);
|
||||
|
||||
} // nv namespace
|
||||
|
||||
#endif // NV_IMAGE_NORMALMIPMAP_H
|
@ -10,8 +10,6 @@ SET(NVTT_SRCS
|
||||
CompressRGB.cpp
|
||||
FastCompressDXT.h
|
||||
FastCompressDXT.cpp
|
||||
BlockDXT.h
|
||||
BlockDXT.cpp
|
||||
dxtlib.cpp
|
||||
dxtlib_compat.h
|
||||
CompressionOptions.h
|
||||
@ -28,7 +26,7 @@ IF(CUDA_FOUND)
|
||||
ADD_DEFINITIONS(-DHAVE_CUDA)
|
||||
WRAP_CUDA(CUDA_SRCS cuda/CompressKernel.cu)
|
||||
SET(NVTT_SRCS ${NVTT_SRCS} ${CUDA_SRCS})
|
||||
SET(LIBS ${LIBS} ${CUDA_LIBRARY})
|
||||
SET(LIBS ${LIBS} ${CUDA_LIBRARIES})
|
||||
INCLUDE_DIRECTORIES(${CUDA_INCLUDE_PATH})
|
||||
ENDIF(CUDA_FOUND)
|
||||
|
||||
@ -46,7 +44,7 @@ TARGET_LINK_LIBRARIES(nvtt ${LIBS} nvcore nvmath nvimage squish)
|
||||
|
||||
|
||||
# test executables
|
||||
ADD_EXECUTABLE(nvcompress compress.cpp)
|
||||
ADD_EXECUTABLE(nvcompress tools/compress.cpp)
|
||||
TARGET_LINK_LIBRARIES(nvcompress nvcore nvmath nvimage nvtt)
|
||||
|
||||
INSTALL(TARGETS nvcompress DESTINATION bin)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,65 +1,65 @@
|
||||
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#ifndef NV_TT_COMPRESSDXT_H
|
||||
#define NV_TT_COMPRESSDXT_H
|
||||
|
||||
#include <nvimage/nvimage.h>
|
||||
#include "nvtt.h"
|
||||
|
||||
namespace nv
|
||||
{
|
||||
class Image;
|
||||
class FloatImage;
|
||||
|
||||
void doPrecomputation();
|
||||
|
||||
// Fast compressors.
|
||||
void fastCompressDXT1(const Image * image, const nvtt::OutputOptions & outputOptions);
|
||||
void fastCompressDXT3(const Image * image, const nvtt::OutputOptions & outputOptions);
|
||||
void fastCompressDXT5(const Image * image, const nvtt::OutputOptions & outputOptions);
|
||||
void fastCompressDXT5n(const Image * image, const nvtt::OutputOptions & outputOptions);
|
||||
void fastCompressBC4(const Image * image, const nvtt::OutputOptions & outputOptions);
|
||||
void fastCompressBC5(const Image * image, const nvtt::OutputOptions & outputOptions);
|
||||
|
||||
// Normal compressors.
|
||||
void compressDXT1(const Image * image, const nvtt::OutputOptions & outputOptions, const nvtt::CompressionOptions::Private & compressionOptions);
|
||||
void compressDXT3(const Image * image, const nvtt::OutputOptions & outputOptions, const nvtt::CompressionOptions::Private & compressionOptions);
|
||||
void compressDXT5(const Image * image, const nvtt::OutputOptions & outputOptions, const nvtt::CompressionOptions::Private & compressionOptions);
|
||||
void compressDXT5n(const Image * image, const nvtt::OutputOptions & outputOptions, const nvtt::CompressionOptions::Private & compressionOptions);
|
||||
void compressBC4(const Image * image, const nvtt::OutputOptions & outputOptions, const nvtt::CompressionOptions::Private & compressionOptions);
|
||||
void compressBC5(const Image * image, const nvtt::OutputOptions & outputOptions, const nvtt::CompressionOptions::Private & compressionOptions);
|
||||
|
||||
// External compressors.
|
||||
#if defined(HAVE_S3QUANT)
|
||||
void s3CompressDXT1(const Image * image, const nvtt::OutputOptions & outputOptions);
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_ATITC)
|
||||
void atiCompressDXT1(const Image * image, const nvtt::OutputOptions & outputOptions);
|
||||
#endif
|
||||
|
||||
} // nv namespace
|
||||
|
||||
|
||||
#endif // NV_TT_COMPRESSDXT_H
|
||||
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#ifndef NV_TT_COMPRESSDXT_H
|
||||
#define NV_TT_COMPRESSDXT_H
|
||||
|
||||
#include <nvimage/nvimage.h>
|
||||
#include "nvtt.h"
|
||||
|
||||
namespace nv
|
||||
{
|
||||
class Image;
|
||||
class FloatImage;
|
||||
|
||||
void doPrecomputation();
|
||||
|
||||
// Fast compressors.
|
||||
void fastCompressDXT1(const Image * image, const nvtt::OutputOptions & outputOptions);
|
||||
void fastCompressDXT3(const Image * image, const nvtt::OutputOptions & outputOptions);
|
||||
void fastCompressDXT5(const Image * image, const nvtt::OutputOptions & outputOptions);
|
||||
void fastCompressDXT5n(const Image * image, const nvtt::OutputOptions & outputOptions);
|
||||
void fastCompressBC4(const Image * image, const nvtt::OutputOptions & outputOptions);
|
||||
void fastCompressBC5(const Image * image, const nvtt::OutputOptions & outputOptions);
|
||||
|
||||
// Normal compressors.
|
||||
void compressDXT1(const Image * image, const nvtt::OutputOptions & outputOptions, const nvtt::CompressionOptions::Private & compressionOptions);
|
||||
void compressDXT3(const Image * image, const nvtt::OutputOptions & outputOptions, const nvtt::CompressionOptions::Private & compressionOptions);
|
||||
void compressDXT5(const Image * image, const nvtt::OutputOptions & outputOptions, const nvtt::CompressionOptions::Private & compressionOptions);
|
||||
void compressDXT5n(const Image * image, const nvtt::OutputOptions & outputOptions, const nvtt::CompressionOptions::Private & compressionOptions);
|
||||
void compressBC4(const Image * image, const nvtt::OutputOptions & outputOptions, const nvtt::CompressionOptions::Private & compressionOptions);
|
||||
void compressBC5(const Image * image, const nvtt::OutputOptions & outputOptions, const nvtt::CompressionOptions::Private & compressionOptions);
|
||||
|
||||
// External compressors.
|
||||
#if defined(HAVE_S3QUANT)
|
||||
void s3CompressDXT1(const Image * image, const nvtt::OutputOptions & outputOptions);
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_ATITC)
|
||||
void atiCompressDXT1(const Image * image, const nvtt::OutputOptions & outputOptions);
|
||||
#endif
|
||||
|
||||
} // nv namespace
|
||||
|
||||
|
||||
#endif // NV_TT_COMPRESSDXT_H
|
||||
|
@ -1,153 +1,153 @@
|
||||
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#include <string.h>
|
||||
#include <nvcore/Debug.h>
|
||||
#include <nvimage/Image.h>
|
||||
|
||||
#include "CompressRGB.h"
|
||||
#include "CompressionOptions.h"
|
||||
|
||||
|
||||
using namespace nv;
|
||||
using namespace nvtt;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
inline uint computePitch(uint w, uint bitsize)
|
||||
{
|
||||
uint p = w * ((bitsize + 7) / 8);
|
||||
|
||||
// Align to 32 bits.
|
||||
return ((p + 3) / 4) * 4;
|
||||
}
|
||||
|
||||
static void convert_to_rgba8888(void * src, void * dst, uint w)
|
||||
{
|
||||
// @@ TODO
|
||||
}
|
||||
|
||||
static void convert_to_bgra8888(const void * src, void * dst, uint w)
|
||||
{
|
||||
memcpy(dst, src, 4 * w);
|
||||
}
|
||||
|
||||
static void convert_to_rgb888(const void * src, void * dst, uint w)
|
||||
{
|
||||
// @@ TODO
|
||||
}
|
||||
|
||||
static uint truncate(uint c, uint inbits, uint outbits)
|
||||
{
|
||||
nvDebugCheck(inbits > outbits);
|
||||
c >>= inbits - outbits;
|
||||
}
|
||||
|
||||
static uint bitexpand(uint c, uint inbits, uint outbits)
|
||||
{
|
||||
// @@ TODO
|
||||
}
|
||||
|
||||
static void maskShiftAndSize(uint mask, uint & shift, uint & size)
|
||||
{
|
||||
shift = 0;
|
||||
while((mask & 1) == 0) {
|
||||
shift++;
|
||||
mask >>= 1;
|
||||
}
|
||||
|
||||
while((mask & 1) == 1) {
|
||||
size++;
|
||||
mask >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
// Pixel format converter.
|
||||
void nv::compressRGB(const Image * image, const OutputOptions & outputOptions, const CompressionOptions::Private & compressionOptions)
|
||||
{
|
||||
nvCheck(image != NULL);
|
||||
|
||||
const uint w = image->width();
|
||||
const uint h = image->height();
|
||||
|
||||
uint rshift, rsize;
|
||||
maskShiftAndSize(compressionOptions.rmask, rshift, rsize);
|
||||
|
||||
uint gshift, gsize;
|
||||
maskShiftAndSize(compressionOptions.gmask, gshift, gsize);
|
||||
|
||||
uint bshift, bsize;
|
||||
maskShiftAndSize(compressionOptions.bmask, bshift, bsize);
|
||||
|
||||
uint ashift, asize;
|
||||
maskShiftAndSize(compressionOptions.amask, ashift, asize);
|
||||
|
||||
|
||||
// Determine pitch.
|
||||
uint pitch = computePitch(w, compressionOptions.bitcount);
|
||||
|
||||
void * dst = malloc(pitch);
|
||||
|
||||
for (uint y = 0; y < h; y++)
|
||||
{
|
||||
const Color32 * src = image->scanline(y);
|
||||
|
||||
convert_to_bgra8888(src, dst, w);
|
||||
|
||||
if (false)
|
||||
{
|
||||
// uint c = 0;
|
||||
// c |= (src[i].r >> (8 - rsize)) << rshift;
|
||||
// c |= (src[i].g >> (8 - gsize)) << gshift;
|
||||
// c |= (src[i].b >> (8 - bsize)) << bshift;
|
||||
}
|
||||
|
||||
/*
|
||||
if (rmask == 0xFF000000 && gmask == 0xFF0000 && bmask == 0xFF00 && amask == 0xFF)
|
||||
{
|
||||
convert_to_rgba8888(src, dst, w);
|
||||
}
|
||||
else if (rmask == 0xFF0000 && gmask == 0xFF00 && bmask == 0xFF && amask == 0)
|
||||
{
|
||||
convert_to_rgb888(src, dst, w);
|
||||
}
|
||||
else
|
||||
{
|
||||
// @@ Not supported.
|
||||
}
|
||||
*/
|
||||
|
||||
if (outputOptions.outputHandler != NULL)
|
||||
{
|
||||
outputOptions.outputHandler->writeData(dst, pitch);
|
||||
}
|
||||
}
|
||||
|
||||
free(dst);
|
||||
}
|
||||
|
||||
|
||||
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#include <string.h>
|
||||
#include <nvcore/Debug.h>
|
||||
#include <nvimage/Image.h>
|
||||
|
||||
#include "CompressRGB.h"
|
||||
#include "CompressionOptions.h"
|
||||
|
||||
|
||||
using namespace nv;
|
||||
using namespace nvtt;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
inline uint computePitch(uint w, uint bitsize)
|
||||
{
|
||||
uint p = w * ((bitsize + 7) / 8);
|
||||
|
||||
// Align to 32 bits.
|
||||
return ((p + 3) / 4) * 4;
|
||||
}
|
||||
|
||||
static void convert_to_rgba8888(void * src, void * dst, uint w)
|
||||
{
|
||||
// @@ TODO
|
||||
}
|
||||
|
||||
static void convert_to_bgra8888(const void * src, void * dst, uint w)
|
||||
{
|
||||
memcpy(dst, src, 4 * w);
|
||||
}
|
||||
|
||||
static void convert_to_rgb888(const void * src, void * dst, uint w)
|
||||
{
|
||||
// @@ TODO
|
||||
}
|
||||
|
||||
static uint truncate(uint c, uint inbits, uint outbits)
|
||||
{
|
||||
nvDebugCheck(inbits > outbits);
|
||||
c >>= inbits - outbits;
|
||||
}
|
||||
|
||||
static uint bitexpand(uint c, uint inbits, uint outbits)
|
||||
{
|
||||
// @@ TODO
|
||||
}
|
||||
|
||||
static void maskShiftAndSize(uint mask, uint & shift, uint & size)
|
||||
{
|
||||
shift = 0;
|
||||
while((mask & 1) == 0) {
|
||||
shift++;
|
||||
mask >>= 1;
|
||||
}
|
||||
|
||||
while((mask & 1) == 1) {
|
||||
size++;
|
||||
mask >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
// Pixel format converter.
|
||||
void nv::compressRGB(const Image * image, const OutputOptions & outputOptions, const CompressionOptions::Private & compressionOptions)
|
||||
{
|
||||
nvCheck(image != NULL);
|
||||
|
||||
const uint w = image->width();
|
||||
const uint h = image->height();
|
||||
|
||||
uint rshift, rsize;
|
||||
maskShiftAndSize(compressionOptions.rmask, rshift, rsize);
|
||||
|
||||
uint gshift, gsize;
|
||||
maskShiftAndSize(compressionOptions.gmask, gshift, gsize);
|
||||
|
||||
uint bshift, bsize;
|
||||
maskShiftAndSize(compressionOptions.bmask, bshift, bsize);
|
||||
|
||||
uint ashift, asize;
|
||||
maskShiftAndSize(compressionOptions.amask, ashift, asize);
|
||||
|
||||
|
||||
// Determine pitch.
|
||||
uint pitch = computePitch(w, compressionOptions.bitcount);
|
||||
|
||||
void * dst = malloc(pitch);
|
||||
|
||||
for (uint y = 0; y < h; y++)
|
||||
{
|
||||
const Color32 * src = image->scanline(y);
|
||||
|
||||
convert_to_bgra8888(src, dst, w);
|
||||
|
||||
if (false)
|
||||
{
|
||||
// uint c = 0;
|
||||
// c |= (src[i].r >> (8 - rsize)) << rshift;
|
||||
// c |= (src[i].g >> (8 - gsize)) << gshift;
|
||||
// c |= (src[i].b >> (8 - bsize)) << bshift;
|
||||
}
|
||||
|
||||
/*
|
||||
if (rmask == 0xFF000000 && gmask == 0xFF0000 && bmask == 0xFF00 && amask == 0xFF)
|
||||
{
|
||||
convert_to_rgba8888(src, dst, w);
|
||||
}
|
||||
else if (rmask == 0xFF0000 && gmask == 0xFF00 && bmask == 0xFF && amask == 0)
|
||||
{
|
||||
convert_to_rgb888(src, dst, w);
|
||||
}
|
||||
else
|
||||
{
|
||||
// @@ Not supported.
|
||||
}
|
||||
*/
|
||||
|
||||
if (outputOptions.outputHandler != NULL)
|
||||
{
|
||||
outputOptions.outputHandler->writeData(dst, pitch);
|
||||
}
|
||||
}
|
||||
|
||||
free(dst);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,24 +1,24 @@
|
||||
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#ifndef NV_TT_COMPRESSRGB_H
|
||||
|
@ -1,113 +1,114 @@
|
||||
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#include "nvtt.h"
|
||||
#include "CompressionOptions.h"
|
||||
|
||||
using namespace nv;
|
||||
using namespace nvtt;
|
||||
|
||||
|
||||
/// Constructor. Sets compression options to the default values.
|
||||
CompressionOptions::CompressionOptions() : m(*new CompressionOptions::Private())
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
|
||||
/// Destructor.
|
||||
CompressionOptions::~CompressionOptions()
|
||||
{
|
||||
delete &m;
|
||||
}
|
||||
|
||||
|
||||
/// Set default compression options.
|
||||
void CompressionOptions::reset()
|
||||
{
|
||||
m.format = Format_DXT1;
|
||||
m.quality = Quality_Normal;
|
||||
m.colorWeight.set(1.0f, 1.0f, 1.0f);
|
||||
m.useCuda = true;
|
||||
m.bitcount = 32;
|
||||
m.bmask = 0x000000FF;
|
||||
m.gmask = 0x0000FF00;
|
||||
m.rmask = 0x00FF0000;
|
||||
m.amask = 0xFF000000;
|
||||
}
|
||||
|
||||
|
||||
/// Set desired compression format.
|
||||
void CompressionOptions::setFormat(Format format)
|
||||
{
|
||||
m.format = format;
|
||||
}
|
||||
|
||||
|
||||
/// Set compression quality settings.
|
||||
void CompressionOptions::setQuality(Quality quality, float errorThreshold /*= 0.5f*/)
|
||||
{
|
||||
m.quality = quality;
|
||||
m.errorThreshold = errorThreshold;
|
||||
}
|
||||
|
||||
|
||||
/// Set the weights of each color channel.
|
||||
/// The choice for these values is subjective. In many case uniform color weights
|
||||
/// (1.0, 1.0, 1.0) work very well. A popular choice is to use the NTSC luma encoding
|
||||
/// weights (0.2126, 0.7152, 0.0722), but I think that blue contributes to our
|
||||
/// perception more than a 7%. A better choice in my opinion is (3, 4, 2). Ideally
|
||||
/// the compressor should use a non linear colour metric as described here:
|
||||
/// http://www.compuphase.com/cmetric.htm
|
||||
void CompressionOptions::setColorWeights(float red, float green, float blue)
|
||||
{
|
||||
float total = red + green + blue;
|
||||
float x = blue / total;
|
||||
float y = green / total;
|
||||
|
||||
m.colorWeight.set(x, y, 1.0f - x - y);
|
||||
}
|
||||
|
||||
|
||||
/// Enable or disable hardware compression.
|
||||
void CompressionOptions::enableHardwareCompression(bool enable)
|
||||
{
|
||||
m.useCuda = enable;
|
||||
}
|
||||
|
||||
|
||||
/// Set color mask to describe the RGB/RGBA format.
|
||||
void CompressionOptions::setPixelFormat(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask)
|
||||
{
|
||||
m.bitcount = bitcount;
|
||||
m.rmask = rmask;
|
||||
m.gmask = gmask;
|
||||
m.bmask = bmask;
|
||||
m.amask = amask;
|
||||
}
|
||||
|
||||
/// Use external compressor.
|
||||
void CompressionOptions::setExternalCompressor(const char * name)
|
||||
{
|
||||
m.externalCompressor = name;
|
||||
}
|
||||
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#include "nvtt.h"
|
||||
#include "CompressionOptions.h"
|
||||
|
||||
using namespace nv;
|
||||
using namespace nvtt;
|
||||
|
||||
|
||||
/// Constructor. Sets compression options to the default values.
|
||||
CompressionOptions::CompressionOptions() : m(*new CompressionOptions::Private())
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
|
||||
/// Destructor.
|
||||
CompressionOptions::~CompressionOptions()
|
||||
{
|
||||
delete &m;
|
||||
}
|
||||
|
||||
|
||||
/// Set default compression options.
|
||||
void CompressionOptions::reset()
|
||||
{
|
||||
m.format = Format_DXT1;
|
||||
m.quality = Quality_Normal;
|
||||
m.colorWeight.set(1.0f, 1.0f, 1.0f);
|
||||
m.useCuda = true;
|
||||
m.bitcount = 32;
|
||||
m.bmask = 0x000000FF;
|
||||
m.gmask = 0x0000FF00;
|
||||
m.rmask = 0x00FF0000;
|
||||
m.amask = 0xFF000000;
|
||||
}
|
||||
|
||||
|
||||
/// Set desired compression format.
|
||||
void CompressionOptions::setFormat(Format format)
|
||||
{
|
||||
m.format = format;
|
||||
}
|
||||
|
||||
|
||||
/// Set compression quality settings.
|
||||
void CompressionOptions::setQuality(Quality quality, float errorThreshold /*= 0.5f*/)
|
||||
{
|
||||
m.quality = quality;
|
||||
m.errorThreshold = errorThreshold;
|
||||
}
|
||||
|
||||
|
||||
/// Set the weights of each color channel.
|
||||
/// The choice for these values is subjective. In many case uniform color weights
|
||||
/// (1.0, 1.0, 1.0) work very well. A popular choice is to use the NTSC luma encoding
|
||||
/// weights (0.2126, 0.7152, 0.0722), but I think that blue contributes to our
|
||||
/// perception more than a 7%. A better choice in my opinion is (3, 4, 2). Ideally
|
||||
/// the compressor should use a non linear colour metric as described here:
|
||||
/// http://www.compuphase.com/cmetric.htm
|
||||
void CompressionOptions::setColorWeights(float red, float green, float blue)
|
||||
{
|
||||
float total = red + green + blue;
|
||||
float x = blue / total;
|
||||
float y = green / total;
|
||||
|
||||
m.colorWeight.set(x, y, 1.0f - x - y);
|
||||
}
|
||||
|
||||
|
||||
/// Enable or disable hardware compression.
|
||||
void CompressionOptions::enableHardwareCompression(bool enable)
|
||||
{
|
||||
m.useCuda = enable;
|
||||
}
|
||||
|
||||
|
||||
/// Set color mask to describe the RGB/RGBA format.
|
||||
void CompressionOptions::setPixelFormat(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask)
|
||||
{
|
||||
m.bitcount = bitcount;
|
||||
m.rmask = rmask;
|
||||
m.gmask = gmask;
|
||||
m.bmask = bmask;
|
||||
m.amask = amask;
|
||||
}
|
||||
|
||||
/// Use external compressor.
|
||||
void CompressionOptions::setExternalCompressor(const char * name)
|
||||
{
|
||||
m.externalCompressor = name;
|
||||
}
|
||||
|
||||
|
@ -1,57 +1,57 @@
|
||||
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#ifndef NV_TT_COMPRESSIONOPTIONS_H
|
||||
#define NV_TT_COMPRESSIONOPTIONS_H
|
||||
|
||||
#include <nvcore/StrLib.h>
|
||||
#include <nvmath/Vector.h>
|
||||
#include "nvtt.h"
|
||||
|
||||
namespace nvtt
|
||||
{
|
||||
|
||||
struct CompressionOptions::Private
|
||||
{
|
||||
Format format;
|
||||
|
||||
Quality quality;
|
||||
float errorThreshold;
|
||||
|
||||
nv::Vector3 colorWeight;
|
||||
|
||||
uint bitcount;
|
||||
uint rmask;
|
||||
uint gmask;
|
||||
uint bmask;
|
||||
uint amask;
|
||||
|
||||
bool useCuda;
|
||||
|
||||
nv::String externalCompressor;
|
||||
};
|
||||
|
||||
} // nvtt namespace
|
||||
|
||||
|
||||
#endif // NV_TT_COMPRESSIONOPTIONS_H
|
||||
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#ifndef NV_TT_COMPRESSIONOPTIONS_H
|
||||
#define NV_TT_COMPRESSIONOPTIONS_H
|
||||
|
||||
#include <nvcore/StrLib.h>
|
||||
#include <nvmath/Vector.h>
|
||||
#include "nvtt.h"
|
||||
|
||||
namespace nvtt
|
||||
{
|
||||
|
||||
struct CompressionOptions::Private
|
||||
{
|
||||
Format format;
|
||||
|
||||
Quality quality;
|
||||
float errorThreshold;
|
||||
|
||||
nv::Vector3 colorWeight;
|
||||
|
||||
uint bitcount;
|
||||
uint rmask;
|
||||
uint gmask;
|
||||
uint bmask;
|
||||
uint amask;
|
||||
|
||||
bool useCuda;
|
||||
|
||||
nv::String externalCompressor;
|
||||
};
|
||||
|
||||
} // nvtt namespace
|
||||
|
||||
|
||||
#endif // NV_TT_COMPRESSIONOPTIONS_H
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,81 +1,84 @@
|
||||
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#ifndef NV_TT_FASTCOMPRESSDXT_H
|
||||
#define NV_TT_FASTCOMPRESSDXT_H
|
||||
|
||||
#include <nvimage/nvimage.h>
|
||||
|
||||
namespace nv
|
||||
{
|
||||
struct ColorBlock;
|
||||
struct BlockDXT1;
|
||||
struct BlockDXT3;
|
||||
struct BlockDXT5;
|
||||
struct AlphaBlockDXT3;
|
||||
struct AlphaBlockDXT5;
|
||||
|
||||
// Color compression:
|
||||
|
||||
// Compressor that uses the extremes of the luminance axis.
|
||||
void compressBlock_DiameterAxis(const ColorBlock & rgba, BlockDXT1 * block);
|
||||
|
||||
// Compressor that uses the extremes of the luminance axis.
|
||||
void compressBlock_LuminanceAxis(const ColorBlock & rgba, BlockDXT1 * block);
|
||||
|
||||
// Compressor that uses bounding box.
|
||||
void compressBlock_BoundsRange(const ColorBlock & rgba, BlockDXT1 * block);
|
||||
|
||||
// Compressor that uses the best fit axis.
|
||||
void compressBlock_BestFitAxis(const ColorBlock & rgba, BlockDXT1 * block);
|
||||
|
||||
|
||||
// Simple, but slow compressor that tests all color pairs.
|
||||
void compressBlock_TestAllPairs(const ColorBlock & rgba, BlockDXT1 * block);
|
||||
|
||||
// Brute force 6d search along the best fit axis.
|
||||
void compressBlock_AnalyzeBestFitAxis(const ColorBlock & rgba, BlockDXT1 * block);
|
||||
|
||||
// Spatial greedy search.
|
||||
void refineSolution_1dSearch(const ColorBlock & rgba, BlockDXT1 * block);
|
||||
void refineSolution_3dSearch(const ColorBlock & rgba, BlockDXT1 * block);
|
||||
void refineSolution_6dSearch(const ColorBlock & rgba, BlockDXT1 * block);
|
||||
|
||||
// Minimize error of the endpoints.
|
||||
void optimizeEndPoints(const ColorBlock & rgba, BlockDXT1 * block);
|
||||
|
||||
uint blockError(const ColorBlock & rgba, const BlockDXT1 & block);
|
||||
uint blockError(const ColorBlock & rgba, const AlphaBlockDXT5 & block);
|
||||
|
||||
// Alpha compression:
|
||||
void compressBlock(const ColorBlock & rgba, AlphaBlockDXT3 * block);
|
||||
void compressBlock_BoundsRange(const ColorBlock & rgba, BlockDXT3 * block);
|
||||
void compressBlock_BoundsRange(const ColorBlock & rgba, BlockDXT5 * block);
|
||||
|
||||
uint compressBlock_BoundsRange(const ColorBlock & rgba, AlphaBlockDXT5 * block);
|
||||
uint compressBlock_BruteForce(const ColorBlock & rgba, AlphaBlockDXT5 * block);
|
||||
uint compressBlock_Iterative(const ColorBlock & rgba, AlphaBlockDXT5 * block);
|
||||
|
||||
} // nv namespace
|
||||
|
||||
#endif // NV_TT_FASTCOMPRESSDXT_H
|
||||
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#ifndef NV_TT_FASTCOMPRESSDXT_H
|
||||
#define NV_TT_FASTCOMPRESSDXT_H
|
||||
|
||||
#include <nvimage/nvimage.h>
|
||||
|
||||
namespace nv
|
||||
{
|
||||
struct ColorBlock;
|
||||
struct BlockDXT1;
|
||||
struct BlockDXT3;
|
||||
struct BlockDXT5;
|
||||
struct AlphaBlockDXT3;
|
||||
struct AlphaBlockDXT5;
|
||||
|
||||
// Color compression:
|
||||
|
||||
// Compressor that uses the extremes of the luminance axis.
|
||||
void compressBlock_DiameterAxis(const ColorBlock & rgba, BlockDXT1 * block);
|
||||
|
||||
// Compressor that uses the extremes of the luminance axis.
|
||||
void compressBlock_LuminanceAxis(const ColorBlock & rgba, BlockDXT1 * block);
|
||||
|
||||
// Compressor that uses bounding box.
|
||||
void compressBlock_BoundsRange(const ColorBlock & rgba, BlockDXT1 * block);
|
||||
|
||||
// Compressor that uses the best fit axis.
|
||||
void compressBlock_BestFitAxis(const ColorBlock & rgba, BlockDXT1 * block);
|
||||
|
||||
|
||||
// Simple, but slow compressor that tests all color pairs.
|
||||
void compressBlock_TestAllPairs(const ColorBlock & rgba, BlockDXT1 * block);
|
||||
|
||||
// Brute force 6d search along the best fit axis.
|
||||
void compressBlock_AnalyzeBestFitAxis(const ColorBlock & rgba, BlockDXT1 * block);
|
||||
|
||||
// Spatial greedy search.
|
||||
void refineSolution_1dSearch(const ColorBlock & rgba, BlockDXT1 * block);
|
||||
void refineSolution_3dSearch(const ColorBlock & rgba, BlockDXT1 * block);
|
||||
void refineSolution_6dSearch(const ColorBlock & rgba, BlockDXT1 * block);
|
||||
|
||||
// Brute force compressor for DXT5n
|
||||
void compressGreenBlock_BruteForce(const ColorBlock & rgba, BlockDXT1 * block);
|
||||
|
||||
// Minimize error of the endpoints.
|
||||
void optimizeEndPoints(const ColorBlock & rgba, BlockDXT1 * block);
|
||||
|
||||
uint blockError(const ColorBlock & rgba, const BlockDXT1 & block);
|
||||
uint blockError(const ColorBlock & rgba, const AlphaBlockDXT5 & block);
|
||||
|
||||
// Alpha compression:
|
||||
void compressBlock(const ColorBlock & rgba, AlphaBlockDXT3 * block);
|
||||
void compressBlock_BoundsRange(const ColorBlock & rgba, BlockDXT3 * block);
|
||||
void compressBlock_BoundsRange(const ColorBlock & rgba, BlockDXT5 * block);
|
||||
|
||||
uint compressBlock_BoundsRange(const ColorBlock & rgba, AlphaBlockDXT5 * block);
|
||||
uint compressBlock_BruteForce(const ColorBlock & rgba, AlphaBlockDXT5 * block);
|
||||
uint compressBlock_Iterative(const ColorBlock & rgba, AlphaBlockDXT5 * block);
|
||||
|
||||
} // nv namespace
|
||||
|
||||
#endif // NV_TT_FASTCOMPRESSDXT_H
|
||||
|
@ -1,250 +1,254 @@
|
||||
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#include <string.h> // memcpy
|
||||
|
||||
#include <nvcore/Memory.h>
|
||||
|
||||
#include "nvtt.h"
|
||||
#include "InputOptions.h"
|
||||
|
||||
using namespace nv;
|
||||
using namespace nvtt;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
static int countMipmaps(int w, int h, int d)
|
||||
{
|
||||
int mipmap = 0;
|
||||
|
||||
while (w != 1 && h != 1) {
|
||||
w = max(1, w / 2);
|
||||
h = max(1, h / 2);
|
||||
d = max(1, d / 2);
|
||||
mipmap++;
|
||||
}
|
||||
|
||||
return mipmap + 1;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
/// Constructor.
|
||||
InputOptions::InputOptions() : m(*new InputOptions::Private())
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
// Delete images.
|
||||
InputOptions::~InputOptions()
|
||||
{
|
||||
resetTextureLayout();
|
||||
|
||||
delete &m;
|
||||
}
|
||||
|
||||
|
||||
// Reset input options.
|
||||
void InputOptions::reset()
|
||||
{
|
||||
m.wrapMode = WrapMode_Repeat;
|
||||
m.textureType = TextureType_2D;
|
||||
m.inputFormat = InputFormat_BGRA_8UB;
|
||||
|
||||
m.enableColorDithering = false;
|
||||
m.enableAlphaDithering = false;
|
||||
m.binaryAlpha = false;
|
||||
m.alphaThreshold = 127;
|
||||
|
||||
m.alphaTransparency = true;
|
||||
|
||||
m.inputGamma = 2.2f;
|
||||
m.outputGamma = 2.2f;
|
||||
|
||||
m.generateMipmaps = false;
|
||||
m.maxLevel = -1;
|
||||
m.mipmapFilter = MipmapFilter_Box;
|
||||
|
||||
m.normalizeMipmaps = false;
|
||||
m.convertToNormalMap = false;
|
||||
m.heightFactors.set(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
m.bumpFrequencyScale = Vector4(1.0f, 0.5f, 0.25f, 0.125f) / (1.0f + 0.5f + 0.25f + 0.125f);
|
||||
}
|
||||
|
||||
|
||||
// Setup the input image.
|
||||
void InputOptions::setTextureLayout(TextureType type, int w, int h, int d /*= 1*/)
|
||||
{
|
||||
// Validate arguments.
|
||||
nvCheck(w >= 0);
|
||||
nvCheck(h >= 0);
|
||||
nvCheck(d >= 0);
|
||||
|
||||
// Correct arguments.
|
||||
if (w == 0) w = 1;
|
||||
if (h == 0) h = 1;
|
||||
if (d == 0) d = 1;
|
||||
|
||||
// Delete previous images.
|
||||
resetTextureLayout();
|
||||
|
||||
m.textureType = type;
|
||||
|
||||
// Allocate images.
|
||||
m.mipmapCount = countMipmaps(w, h, d);
|
||||
m.faceCount = (type == TextureType_Cube) ? 6 : 1;
|
||||
m.imageCount = m.mipmapCount * m.faceCount;
|
||||
|
||||
m.images = new Private::Image[m.imageCount];
|
||||
|
||||
for(int f = 0; f < m.faceCount; f++)
|
||||
{
|
||||
for (int mipLevel = 0; mipLevel < m.mipmapCount; mipLevel++)
|
||||
{
|
||||
Private::Image & img = m.images[f * m.mipmapCount + mipLevel];
|
||||
img.width = w;
|
||||
img.height = h;
|
||||
img.depth = d;
|
||||
img.mipLevel = mipLevel;
|
||||
img.face = f;
|
||||
|
||||
img.data = NULL;
|
||||
|
||||
w = max(1, w / 2);
|
||||
h = max(1, h / 2);
|
||||
d = max(1, d / 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void InputOptions::resetTextureLayout()
|
||||
{
|
||||
if (m.images != NULL)
|
||||
{
|
||||
// Delete image array.
|
||||
delete [] m.images;
|
||||
m.images = NULL;
|
||||
|
||||
m.faceCount = 0;
|
||||
m.mipmapCount = 0;
|
||||
m.imageCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 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*/)
|
||||
{
|
||||
nvCheck(depth == 1);
|
||||
|
||||
const int idx = face * m.mipmapCount + mipLevel;
|
||||
|
||||
if (m.images[idx].width != width || m.images[idx].height != height || m.images[idx].depth != depth || m.images[idx].mipLevel != mipLevel || m.images[idx].face != face)
|
||||
{
|
||||
// Invalid dimension or index.
|
||||
return false;
|
||||
}
|
||||
|
||||
m.images[idx].data = new nv::Image();
|
||||
m.images[idx].data->allocate(width, height);
|
||||
memcpy(m.images[idx].data->pixels(), data, width * height * 4);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/// Describe the format of the input.
|
||||
void InputOptions::setFormat(InputFormat format, bool alphaTransparency)
|
||||
{
|
||||
m.inputFormat = format;
|
||||
m.alphaTransparency = alphaTransparency;
|
||||
}
|
||||
|
||||
|
||||
/// Set gamma settings.
|
||||
void InputOptions::setGamma(float inputGamma, float outputGamma)
|
||||
{
|
||||
m.inputGamma = inputGamma;
|
||||
m.outputGamma = outputGamma;
|
||||
}
|
||||
|
||||
|
||||
/// Set texture wrappign mode.
|
||||
void InputOptions::setWrapMode(WrapMode mode)
|
||||
{
|
||||
m.wrapMode = mode;
|
||||
}
|
||||
|
||||
|
||||
/// Set mipmapping options.
|
||||
void InputOptions::setMipmapping(bool generateMipmaps, MipmapFilter filter/*= MipmapFilter_Kaiser*/, int maxLevel/*= -1*/)
|
||||
{
|
||||
m.generateMipmaps = generateMipmaps;
|
||||
m.mipmapFilter = filter;
|
||||
m.maxLevel = maxLevel;
|
||||
}
|
||||
|
||||
|
||||
/// Set quantization options.
|
||||
/// @warning Do not enable dithering unless you know what you are doing. Quantization
|
||||
/// introduces errors. It's better to let the compressor quantize the result to
|
||||
/// minimize the error, instead of quantizing the data before handling it to
|
||||
/// the compressor.
|
||||
void InputOptions::setQuantization(bool colorDithering, bool alphaDithering, bool binaryAlpha, int alphaThreshold/*= 127*/)
|
||||
{
|
||||
m.enableColorDithering = colorDithering;
|
||||
m.enableAlphaDithering = alphaDithering;
|
||||
m.binaryAlpha = binaryAlpha;
|
||||
m.alphaThreshold = alphaThreshold;
|
||||
}
|
||||
|
||||
|
||||
/// Enable normal map conversion.
|
||||
void InputOptions::setConvertToNormalMap(bool convert)
|
||||
{
|
||||
m.convertToNormalMap = convert;
|
||||
}
|
||||
|
||||
/// Set height evaluation factors.
|
||||
void InputOptions::setHeightEvaluation(float redScale, float greenScale, float blueScale, float alphaScale)
|
||||
{
|
||||
// Do not normalize height factors.
|
||||
// float total = redScale + greenScale + blueScale + alphaScale;
|
||||
m.heightFactors = Vector4(redScale, greenScale, blueScale, alphaScale);
|
||||
}
|
||||
|
||||
/// Set normal map conversion filter.
|
||||
void InputOptions::setNormalFilter(float small, float medium, float big, float large)
|
||||
{
|
||||
float total = small + medium + big + large;
|
||||
m.bumpFrequencyScale = Vector4(small, medium, big, large) / total;
|
||||
}
|
||||
|
||||
/// Enable mipmap normalization.
|
||||
void InputOptions::setNormalizeMipmaps(bool normalize)
|
||||
{
|
||||
m.normalizeMipmaps = normalize;
|
||||
}
|
||||
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#include <string.h> // memcpy
|
||||
|
||||
#include <nvcore/Memory.h>
|
||||
|
||||
#include "nvtt.h"
|
||||
#include "InputOptions.h"
|
||||
|
||||
using namespace nv;
|
||||
using namespace nvtt;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
static int countMipmaps(int w, int h, int d)
|
||||
{
|
||||
int mipmap = 0;
|
||||
|
||||
while (w != 1 && h != 1) {
|
||||
w = max(1, w / 2);
|
||||
h = max(1, h / 2);
|
||||
d = max(1, d / 2);
|
||||
mipmap++;
|
||||
}
|
||||
|
||||
return mipmap + 1;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
/// Constructor.
|
||||
InputOptions::InputOptions() : m(*new InputOptions::Private())
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
// Delete images.
|
||||
InputOptions::~InputOptions()
|
||||
{
|
||||
resetTextureLayout();
|
||||
|
||||
delete &m;
|
||||
}
|
||||
|
||||
|
||||
// Reset input options.
|
||||
void InputOptions::reset()
|
||||
{
|
||||
m.wrapMode = WrapMode_Repeat;
|
||||
m.textureType = TextureType_2D;
|
||||
m.inputFormat = InputFormat_BGRA_8UB;
|
||||
|
||||
m.enableColorDithering = false;
|
||||
m.enableAlphaDithering = false;
|
||||
m.binaryAlpha = false;
|
||||
m.alphaThreshold = 127;
|
||||
|
||||
m.alphaTransparency = true;
|
||||
|
||||
m.inputGamma = 2.2f;
|
||||
m.outputGamma = 2.2f;
|
||||
|
||||
m.generateMipmaps = false;
|
||||
m.maxLevel = -1;
|
||||
m.mipmapFilter = MipmapFilter_Box;
|
||||
|
||||
m.normalizeMipmaps = false;
|
||||
m.convertToNormalMap = false;
|
||||
m.heightFactors.set(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
m.bumpFrequencyScale = Vector4(1.0f, 0.5f, 0.25f, 0.125f) / (1.0f + 0.5f + 0.25f + 0.125f);
|
||||
}
|
||||
|
||||
|
||||
// Setup the input image.
|
||||
void InputOptions::setTextureLayout(TextureType type, int width, int height, int depth /*= 1*/)
|
||||
{
|
||||
// Validate arguments.
|
||||
nvCheck(width >= 0);
|
||||
nvCheck(height >= 0);
|
||||
nvCheck(depth >= 0);
|
||||
|
||||
// Correct arguments.
|
||||
if (width == 0) width = 1;
|
||||
if (height == 0) height = 1;
|
||||
if (depth == 0) depth = 1;
|
||||
|
||||
// Delete previous images.
|
||||
resetTextureLayout();
|
||||
|
||||
m.textureType = type;
|
||||
|
||||
// Allocate images.
|
||||
m.mipmapCount = countMipmaps(width, height, depth);
|
||||
m.faceCount = (type == TextureType_Cube) ? 6 : 1;
|
||||
m.imageCount = m.mipmapCount * m.faceCount;
|
||||
|
||||
m.images = new Private::Image[m.imageCount];
|
||||
|
||||
for(int f = 0; f < m.faceCount; f++)
|
||||
{
|
||||
int w = width;
|
||||
int h = height;
|
||||
int d = depth;
|
||||
|
||||
for (int mipLevel = 0; mipLevel < m.mipmapCount; mipLevel++)
|
||||
{
|
||||
Private::Image & img = m.images[f * m.mipmapCount + mipLevel];
|
||||
img.width = w;
|
||||
img.height = h;
|
||||
img.depth = d;
|
||||
img.mipLevel = mipLevel;
|
||||
img.face = f;
|
||||
|
||||
img.data = NULL;
|
||||
|
||||
w = max(1, w / 2);
|
||||
h = max(1, h / 2);
|
||||
d = max(1, d / 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void InputOptions::resetTextureLayout()
|
||||
{
|
||||
if (m.images != NULL)
|
||||
{
|
||||
// Delete image array.
|
||||
delete [] m.images;
|
||||
m.images = NULL;
|
||||
|
||||
m.faceCount = 0;
|
||||
m.mipmapCount = 0;
|
||||
m.imageCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 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*/)
|
||||
{
|
||||
nvCheck(depth == 1);
|
||||
|
||||
const int idx = face * m.mipmapCount + mipLevel;
|
||||
|
||||
if (m.images[idx].width != width || m.images[idx].height != height || m.images[idx].depth != depth || m.images[idx].mipLevel != mipLevel || m.images[idx].face != face)
|
||||
{
|
||||
// Invalid dimension or index.
|
||||
return false;
|
||||
}
|
||||
|
||||
m.images[idx].data = new nv::Image();
|
||||
m.images[idx].data->allocate(width, height);
|
||||
memcpy(m.images[idx].data->pixels(), data, width * height * 4);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/// Describe the format of the input.
|
||||
void InputOptions::setFormat(InputFormat format, bool alphaTransparency)
|
||||
{
|
||||
m.inputFormat = format;
|
||||
m.alphaTransparency = alphaTransparency;
|
||||
}
|
||||
|
||||
|
||||
/// Set gamma settings.
|
||||
void InputOptions::setGamma(float inputGamma, float outputGamma)
|
||||
{
|
||||
m.inputGamma = inputGamma;
|
||||
m.outputGamma = outputGamma;
|
||||
}
|
||||
|
||||
|
||||
/// Set texture wrappign mode.
|
||||
void InputOptions::setWrapMode(WrapMode mode)
|
||||
{
|
||||
m.wrapMode = mode;
|
||||
}
|
||||
|
||||
|
||||
/// Set mipmapping options.
|
||||
void InputOptions::setMipmapping(bool generateMipmaps, MipmapFilter filter/*= MipmapFilter_Kaiser*/, int maxLevel/*= -1*/)
|
||||
{
|
||||
m.generateMipmaps = generateMipmaps;
|
||||
m.mipmapFilter = filter;
|
||||
m.maxLevel = maxLevel;
|
||||
}
|
||||
|
||||
|
||||
/// Set quantization options.
|
||||
/// @warning Do not enable dithering unless you know what you are doing. Quantization
|
||||
/// introduces errors. It's better to let the compressor quantize the result to
|
||||
/// minimize the error, instead of quantizing the data before handling it to
|
||||
/// the compressor.
|
||||
void InputOptions::setQuantization(bool colorDithering, bool alphaDithering, bool binaryAlpha, int alphaThreshold/*= 127*/)
|
||||
{
|
||||
m.enableColorDithering = colorDithering;
|
||||
m.enableAlphaDithering = alphaDithering;
|
||||
m.binaryAlpha = binaryAlpha;
|
||||
m.alphaThreshold = alphaThreshold;
|
||||
}
|
||||
|
||||
|
||||
/// Enable normal map conversion.
|
||||
void InputOptions::setConvertToNormalMap(bool convert)
|
||||
{
|
||||
m.convertToNormalMap = convert;
|
||||
}
|
||||
|
||||
/// Set height evaluation factors.
|
||||
void InputOptions::setHeightEvaluation(float redScale, float greenScale, float blueScale, float alphaScale)
|
||||
{
|
||||
// Do not normalize height factors.
|
||||
// float total = redScale + greenScale + blueScale + alphaScale;
|
||||
m.heightFactors = Vector4(redScale, greenScale, blueScale, alphaScale);
|
||||
}
|
||||
|
||||
/// Set normal map conversion filter.
|
||||
void InputOptions::setNormalFilter(float small, float medium, float big, float large)
|
||||
{
|
||||
float total = small + medium + big + large;
|
||||
m.bumpFrequencyScale = Vector4(small, medium, big, large) / total;
|
||||
}
|
||||
|
||||
/// Enable mipmap normalization.
|
||||
void InputOptions::setNormalizeMipmaps(bool normalize)
|
||||
{
|
||||
m.normalizeMipmaps = normalize;
|
||||
}
|
||||
|
@ -1,24 +1,24 @@
|
||||
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#ifndef NV_TT_INPUTOPTIONS_H
|
||||
|
@ -1,32 +1,32 @@
|
||||
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#include "nvtt.h"
|
||||
|
||||
using namespace nvtt;
|
||||
|
||||
/// Set default output options.
|
||||
void OutputOptions::reset()
|
||||
{
|
||||
// endiannes = native...
|
||||
}
|
||||
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#include "nvtt.h"
|
||||
|
||||
using namespace nvtt;
|
||||
|
||||
/// Set default output options.
|
||||
void OutputOptions::reset()
|
||||
{
|
||||
// endiannes = native...
|
||||
}
|
||||
|
@ -1,44 +0,0 @@
|
||||
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
|
||||
|
||||
#ifndef CMDLINE_H
|
||||
#define CMDLINE_H
|
||||
|
||||
#include <nvcore/Debug.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
struct MyMessageHandler : public nv::MessageHandler {
|
||||
MyMessageHandler() {
|
||||
nv::debug::setMessageHandler( this );
|
||||
}
|
||||
~MyMessageHandler() {
|
||||
nv::debug::resetMessageHandler();
|
||||
}
|
||||
|
||||
virtual void log( const char * str, va_list arg ) {
|
||||
va_list val;
|
||||
va_copy(val, arg);
|
||||
vfprintf(stderr, str, arg);
|
||||
va_end(val);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct MyAssertHandler : public nv::AssertHandler {
|
||||
MyAssertHandler() {
|
||||
nv::debug::setAssertHandler( this );
|
||||
}
|
||||
~MyAssertHandler() {
|
||||
nv::debug::resetAssertHandler();
|
||||
}
|
||||
|
||||
// Handler method, note that func might be NULL!
|
||||
virtual int assert( const char *exp, const char *file, int line, const char *func ) {
|
||||
fprintf(stderr, "Assertion failed: %s\nIn %s:%d\n", exp, file, line);
|
||||
nv::debug::dumpInfo();
|
||||
exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif // CMDLINE_H
|
@ -28,7 +28,7 @@
|
||||
|
||||
#include "CudaMath.h"
|
||||
|
||||
#define THREAD_NUM 64 // Number of threads per block.
|
||||
#define NUM_THREADS 64 // Number of threads per block.
|
||||
|
||||
#if __DEVICE_EMULATION__
|
||||
#define __debugsync() __syncthreads()
|
||||
@ -94,7 +94,6 @@ static __device__ float evalPermutation4(const float3 * colors, uint permutation
|
||||
betax_sum += beta * colors[i];
|
||||
}
|
||||
|
||||
// alpha2, beta2, alphabeta and factor could be precomputed for each permutation, but it's faster to recompute them.
|
||||
const float factor = 1.0f / (alpha2_sum * beta2_sum - alphabeta_sum * alphabeta_sum);
|
||||
|
||||
float3 a = (alphax_sum * beta2_sum - betax_sum * alphabeta_sum) * factor;
|
||||
@ -151,89 +150,92 @@ static __device__ float evalPermutation3(const float3 * colors, uint permutation
|
||||
return dot(e, kColorMetric);
|
||||
}
|
||||
|
||||
static __device__ float evalPermutation4(const float3 * colors, const float * weights, uint permutation, ushort * start, ushort * end)
|
||||
{
|
||||
// Compute endpoints using least squares.
|
||||
float alpha2_sum = 0.0f;
|
||||
float beta2_sum = 0.0f;
|
||||
float alphabeta_sum = 0.0f;
|
||||
float3 alphax_sum = make_float3(0.0f, 0.0f, 0.0f);
|
||||
float3 betax_sum = make_float3(0.0f, 0.0f, 0.0f);
|
||||
|
||||
// Compute alpha & beta for this permutation.
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
const uint bits = permutation >> (2*i);
|
||||
|
||||
float beta = (bits & 1);
|
||||
if (bits & 2) beta = (1 + beta) / 3.0f;
|
||||
float alpha = 1.0f - beta;
|
||||
|
||||
alpha2_sum += alpha * alpha * weights[i];
|
||||
beta2_sum += beta * beta * weights[i];
|
||||
alphabeta_sum += alpha * beta * weights[i];
|
||||
alphax_sum += alpha * colors[i] * weights[i];
|
||||
betax_sum += beta * colors[i] * weights[i];
|
||||
}
|
||||
|
||||
const float factor = 1.0f / (alpha2_sum * beta2_sum - alphabeta_sum * alphabeta_sum);
|
||||
|
||||
float3 a = (alphax_sum * beta2_sum - betax_sum * alphabeta_sum) * factor;
|
||||
float3 b = (betax_sum * alpha2_sum - alphax_sum * alphabeta_sum) * factor;
|
||||
|
||||
// Round a, b to the closest 5-6-5 color and expand...
|
||||
a = roundAndExpand(a, start);
|
||||
b = roundAndExpand(b, end);
|
||||
|
||||
// compute the error
|
||||
float3 e = a * a * alpha2_sum + b * b * beta2_sum + 2.0f * (a * b * alphabeta_sum - a * alphax_sum - b * betax_sum);
|
||||
|
||||
return dot(e, kColorMetric);
|
||||
}
|
||||
|
||||
|
||||
static __device__ float evalPermutation3(const float3 * colors, const float * weights, uint permutation, ushort * start, ushort * end)
|
||||
{
|
||||
// Compute endpoints using least squares.
|
||||
float alpha2_sum = 0.0f;
|
||||
float beta2_sum = 0.0f;
|
||||
float alphabeta_sum = 0.0f;
|
||||
float3 alphax_sum = make_float3(0.0f, 0.0f, 0.0f);
|
||||
float3 betax_sum = make_float3(0.0f, 0.0f, 0.0f);
|
||||
|
||||
// Compute alpha & beta for this permutation.
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
const uint bits = permutation >> (2*i);
|
||||
|
||||
float beta = (bits & 1);
|
||||
if (bits & 2) beta = 0.5f;
|
||||
float alpha = 1.0f - beta;
|
||||
|
||||
alpha2_sum += alpha * alpha * weights[i];
|
||||
beta2_sum += beta * beta * weights[i];
|
||||
alphabeta_sum += alpha * beta * weights[i];
|
||||
alphax_sum += alpha * colors[i] * weights[i];
|
||||
betax_sum += beta * colors[i] * weights[i];
|
||||
}
|
||||
|
||||
const float factor = 1.0f / (alpha2_sum * beta2_sum - alphabeta_sum * alphabeta_sum);
|
||||
|
||||
float3 a = (alphax_sum * beta2_sum - betax_sum * alphabeta_sum) * factor;
|
||||
float3 b = (betax_sum * alpha2_sum - alphax_sum * alphabeta_sum) * factor;
|
||||
|
||||
// Round a, b to the closest 5-6-5 color and expand...
|
||||
a = roundAndExpand(a, start);
|
||||
b = roundAndExpand(b, end);
|
||||
|
||||
// compute the error
|
||||
float3 e = a * a * alpha2_sum + b * b * beta2_sum + 2.0f * (a * b * alphabeta_sum - a * alphax_sum - b * betax_sum);
|
||||
|
||||
return dot(e, kColorMetric);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Sort colors
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
__device__ void sortColors(float * values, float3 * colors, int * xrefs)
|
||||
{
|
||||
#if __DEVICE_EMULATION__
|
||||
|
||||
if (threadIdx.x == 0)
|
||||
{
|
||||
for( int i = 0; i < 16; ++i )
|
||||
{
|
||||
xrefs[i] = i;
|
||||
}
|
||||
|
||||
// Use a sequential sort on emulation.
|
||||
for( int i = 0; i < 16; ++i )
|
||||
{
|
||||
for( int j = i; j > 0 && values[j] < values[j - 1]; --j )
|
||||
{
|
||||
swap( values[j], values[j - 1] );
|
||||
swap( xrefs[j], xrefs[j - 1] );
|
||||
// swap( colors[j], colors[j - 1] );
|
||||
}
|
||||
}
|
||||
|
||||
float3 tmp[16];
|
||||
for( int i = 0; i < 16; ++i )
|
||||
{
|
||||
tmp[i] = colors[i];
|
||||
}
|
||||
|
||||
for( int i = 0; i < 16; ++i )
|
||||
{
|
||||
int xid = xrefs[i];
|
||||
colors[i] = tmp[xid];
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
int tid = threadIdx.x;
|
||||
|
||||
xrefs[tid] = tid;
|
||||
|
||||
// Parallel bitonic sort.
|
||||
for (int k = 2; k <= 16; k *= 2)
|
||||
{
|
||||
// bitonic merge:
|
||||
for (int j = k / 2; j>0; j /= 2)
|
||||
{
|
||||
int ixj = tid ^ j;
|
||||
|
||||
if (ixj > tid) {
|
||||
// @@ Optimize these branches.
|
||||
if ((tid & k) == 0) {
|
||||
if (values[xrefs[tid]] > values[xrefs[ixj]]) {
|
||||
// swap(values[tid], values[ixj]);
|
||||
swap(colors[tid], colors[ixj]);
|
||||
swap(xrefs[tid], xrefs[ixj]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (values[xrefs[tid]] < values[xrefs[ixj]]) {
|
||||
// swap(values[tid], values[ixj]);
|
||||
swap(colors[tid], colors[ixj]);
|
||||
swap(xrefs[tid], xrefs[ixj]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// It would be faster to avoid color swaps during the sort, but there
|
||||
// are compiler bugs preventing that.
|
||||
#if 0
|
||||
float3 tmp = colors[xrefs[tid]];
|
||||
colors[tid] = tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
// This sort is faster, but does not sort correctly elements with the same value.
|
||||
__device__ void sortColors2(float * values, float3 * colors, int * cmp)
|
||||
__device__ void sortColors(float * values, float3 * colors, int * cmp)
|
||||
{
|
||||
int tid = threadIdx.x;
|
||||
|
||||
@ -254,10 +256,70 @@ __device__ void sortColors2(float * values, float3 * colors, int * cmp)
|
||||
cmp[tid] += (values[14] < values[tid]);
|
||||
cmp[tid] += (values[15] < values[tid]);
|
||||
|
||||
// Resolve elements with the same index.
|
||||
if (tid > 0 && cmp[tid] == cmp[0]) ++cmp[tid];
|
||||
if (tid > 1 && cmp[tid] == cmp[1]) ++cmp[tid];
|
||||
if (tid > 2 && cmp[tid] == cmp[2]) ++cmp[tid];
|
||||
if (tid > 3 && cmp[tid] == cmp[3]) ++cmp[tid];
|
||||
if (tid > 4 && cmp[tid] == cmp[4]) ++cmp[tid];
|
||||
if (tid > 5 && cmp[tid] == cmp[5]) ++cmp[tid];
|
||||
if (tid > 6 && cmp[tid] == cmp[6]) ++cmp[tid];
|
||||
if (tid > 7 && cmp[tid] == cmp[7]) ++cmp[tid];
|
||||
if (tid > 8 && cmp[tid] == cmp[8]) ++cmp[tid];
|
||||
if (tid > 9 && cmp[tid] == cmp[9]) ++cmp[tid];
|
||||
if (tid > 10 && cmp[tid] == cmp[10]) ++cmp[tid];
|
||||
if (tid > 11 && cmp[tid] == cmp[11]) ++cmp[tid];
|
||||
if (tid > 12 && cmp[tid] == cmp[12]) ++cmp[tid];
|
||||
if (tid > 13 && cmp[tid] == cmp[13]) ++cmp[tid];
|
||||
if (tid > 14 && cmp[tid] == cmp[14]) ++cmp[tid];
|
||||
|
||||
float3 tmp = colors[tid];
|
||||
colors[cmp[tid]] = tmp;
|
||||
}
|
||||
|
||||
__device__ void sortColors(float * values, float3 * colors, float * weights, int * cmp)
|
||||
{
|
||||
int tid = threadIdx.x;
|
||||
|
||||
cmp[tid] = (values[0] < values[tid]);
|
||||
cmp[tid] += (values[1] < values[tid]);
|
||||
cmp[tid] += (values[2] < values[tid]);
|
||||
cmp[tid] += (values[3] < values[tid]);
|
||||
cmp[tid] += (values[4] < values[tid]);
|
||||
cmp[tid] += (values[5] < values[tid]);
|
||||
cmp[tid] += (values[6] < values[tid]);
|
||||
cmp[tid] += (values[7] < values[tid]);
|
||||
cmp[tid] += (values[8] < values[tid]);
|
||||
cmp[tid] += (values[9] < values[tid]);
|
||||
cmp[tid] += (values[10] < values[tid]);
|
||||
cmp[tid] += (values[11] < values[tid]);
|
||||
cmp[tid] += (values[12] < values[tid]);
|
||||
cmp[tid] += (values[13] < values[tid]);
|
||||
cmp[tid] += (values[14] < values[tid]);
|
||||
cmp[tid] += (values[15] < values[tid]);
|
||||
|
||||
// Resolve elements with the same index.
|
||||
if (tid > 0 && cmp[tid] == cmp[0]) ++cmp[tid];
|
||||
if (tid > 1 && cmp[tid] == cmp[1]) ++cmp[tid];
|
||||
if (tid > 2 && cmp[tid] == cmp[2]) ++cmp[tid];
|
||||
if (tid > 3 && cmp[tid] == cmp[3]) ++cmp[tid];
|
||||
if (tid > 4 && cmp[tid] == cmp[4]) ++cmp[tid];
|
||||
if (tid > 5 && cmp[tid] == cmp[5]) ++cmp[tid];
|
||||
if (tid > 6 && cmp[tid] == cmp[6]) ++cmp[tid];
|
||||
if (tid > 7 && cmp[tid] == cmp[7]) ++cmp[tid];
|
||||
if (tid > 8 && cmp[tid] == cmp[8]) ++cmp[tid];
|
||||
if (tid > 9 && cmp[tid] == cmp[9]) ++cmp[tid];
|
||||
if (tid > 10 && cmp[tid] == cmp[10]) ++cmp[tid];
|
||||
if (tid > 11 && cmp[tid] == cmp[11]) ++cmp[tid];
|
||||
if (tid > 12 && cmp[tid] == cmp[12]) ++cmp[tid];
|
||||
if (tid > 13 && cmp[tid] == cmp[13]) ++cmp[tid];
|
||||
if (tid > 14 && cmp[tid] == cmp[14]) ++cmp[tid];
|
||||
|
||||
float3 tmp = colors[tid];
|
||||
colors[cmp[tid]] = tmp;
|
||||
|
||||
weights[cmp[tid]] = weights[tid];
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -269,7 +331,7 @@ __device__ void minimizeError(float * errors, int * indices)
|
||||
|
||||
#if __DEVICE_EMULATION__
|
||||
|
||||
for(int d = THREAD_NUM/2; d > 0; d >>= 1)
|
||||
for(int d = NUM_THREADS/2; d > 0; d >>= 1)
|
||||
{
|
||||
__syncthreads();
|
||||
|
||||
@ -287,7 +349,7 @@ __device__ void minimizeError(float * errors, int * indices)
|
||||
|
||||
#else
|
||||
|
||||
for(int d = THREAD_NUM/2; d > 32; d >>= 1)
|
||||
for(int d = NUM_THREADS/2; d > 32; d >>= 1)
|
||||
{
|
||||
__syncthreads();
|
||||
|
||||
@ -295,7 +357,7 @@ __device__ void minimizeError(float * errors, int * indices)
|
||||
{
|
||||
float err0 = errors[idx];
|
||||
float err1 = errors[idx + d];
|
||||
|
||||
|
||||
if (err1 < err0) {
|
||||
errors[idx] = err1;
|
||||
indices[idx] = indices[idx + d];
|
||||
@ -338,7 +400,7 @@ __device__ void minimizeError(float * errors, int * indices)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Compress color block
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
__global__ void compress(const uint * permutations, const uint * image, uint * result)
|
||||
__global__ void compress(const uint * permutations, const uint * image, uint2 * result)
|
||||
{
|
||||
const int bid = blockIdx.x;
|
||||
const int idx = threadIdx.x;
|
||||
@ -349,19 +411,14 @@ __global__ void compress(const uint * permutations, const uint * image, uint * r
|
||||
|
||||
if (idx < 16)
|
||||
{
|
||||
// Read color.
|
||||
// Read color and copy to shared mem.
|
||||
uint c = image[(bid) * 16 + idx];
|
||||
|
||||
// No need to synchronize, 16 < warp size.
|
||||
#if __DEVICE_EMULATION__
|
||||
} __debugsync(); if (idx < 16) {
|
||||
#endif
|
||||
|
||||
// Copy color to shared mem.
|
||||
colors[idx].z = ((c >> 0) & 0xFF) * (1.0f / 255.0f);
|
||||
colors[idx].y = ((c >> 8) & 0xFF) * (1.0f / 255.0f);
|
||||
colors[idx].x = ((c >> 16) & 0xFF) * (1.0f / 255.0f);
|
||||
|
||||
// No need to synchronize, 16 < warp size.
|
||||
#if __DEVICE_EMULATION__
|
||||
} __debugsync(); if (idx < 16) {
|
||||
#endif
|
||||
@ -383,15 +440,66 @@ __global__ void compress(const uint * permutations, const uint * image, uint * r
|
||||
float bestError = FLT_MAX;
|
||||
|
||||
__syncthreads();
|
||||
|
||||
for(int i = 0; i < 16; i++)
|
||||
|
||||
#if 0
|
||||
// This version is more clear, but slightly slower.
|
||||
for(int i = 0; i < 16; i++)
|
||||
{
|
||||
if (i == 15 && idx >= 32) break;
|
||||
|
||||
ushort start, end;
|
||||
uint permutation = permutations[idx + NUM_THREADS * i];
|
||||
float error = evalPermutation4(colors, permutation, &start, &end);
|
||||
|
||||
if (error < bestError)
|
||||
{
|
||||
bestError = error;
|
||||
bestPermutation = permutation;
|
||||
bestStart = start;
|
||||
bestEnd = end;
|
||||
}
|
||||
}
|
||||
|
||||
if (bestStart < bestEnd)
|
||||
{
|
||||
swap(bestEnd, bestStart);
|
||||
bestPermutation ^= 0x55555555; // Flip indices.
|
||||
}
|
||||
|
||||
for(int i = 0; i < 3; i++)
|
||||
{
|
||||
if (i == 2 && idx >= 32) break;
|
||||
|
||||
ushort start, end;
|
||||
uint permutation = permutations[idx + NUM_THREADS * i];
|
||||
float error = evalPermutation3(colors, permutation, &start, &end);
|
||||
|
||||
if (error < bestError)
|
||||
{
|
||||
bestError = error;
|
||||
bestPermutation = permutation;
|
||||
bestStart = start;
|
||||
bestEnd = end;
|
||||
|
||||
if (bestStart > bestEnd)
|
||||
{
|
||||
swap(bestEnd, bestStart);
|
||||
bestPermutation ^= (~bestPermutation >> 1) & 0x55555555; // Flip indices.
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
{
|
||||
if (i == 15 && idx >= 32) break;
|
||||
|
||||
int pidx = idx + NUM_THREADS * 15;
|
||||
if (idx >= 32)
|
||||
{
|
||||
pidx = idx + NUM_THREADS * 2;
|
||||
}
|
||||
|
||||
ushort start, end;
|
||||
uint permutation = permutations[idx + THREAD_NUM * i];
|
||||
uint permutation = permutations[pidx];
|
||||
float error = evalPermutation4(colors, permutation, &start, &end);
|
||||
|
||||
|
||||
if (error < bestError)
|
||||
{
|
||||
bestError = error;
|
||||
@ -401,45 +509,73 @@ __global__ void compress(const uint * permutations, const uint * image, uint * r
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 3; i < 15; i++)
|
||||
{
|
||||
ushort start, end;
|
||||
uint permutation = permutations[idx + NUM_THREADS * i];
|
||||
float error = evalPermutation4(colors, permutation, &start, &end);
|
||||
|
||||
if (error < bestError)
|
||||
{
|
||||
bestError = error;
|
||||
bestPermutation = permutation;
|
||||
bestStart = start;
|
||||
bestEnd = end;
|
||||
}
|
||||
}
|
||||
|
||||
if (bestStart < bestEnd)
|
||||
{
|
||||
swap(bestEnd, bestStart);
|
||||
bestPermutation ^= 0x55555555; // Flip indices.
|
||||
bestPermutation ^= 0x55555555; // Flip indices.
|
||||
}
|
||||
|
||||
for(int i = 0; i < 3; i++)
|
||||
{
|
||||
if (i == 2 && idx >= 32) break;
|
||||
|
||||
ushort start, end;
|
||||
uint permutation = permutations[idx + THREAD_NUM * i];
|
||||
float error = evalPermutation3(colors, permutation, &start, &end);
|
||||
|
||||
if (error < bestError)
|
||||
{
|
||||
bestError = error;
|
||||
bestPermutation = permutation;
|
||||
bestStart = start;
|
||||
bestEnd = end;
|
||||
|
||||
if (bestStart > bestEnd)
|
||||
|
||||
for(int i = 0; i < 3; i++)
|
||||
{
|
||||
if (i == 2 && idx >= 32) break;
|
||||
|
||||
ushort start, end;
|
||||
uint permutation = permutations[idx + NUM_THREADS * i];
|
||||
float error = evalPermutation3(colors, permutation, &start, &end);
|
||||
|
||||
if (error < bestError)
|
||||
{
|
||||
bestError = error;
|
||||
bestPermutation = permutation;
|
||||
bestStart = start;
|
||||
bestEnd = end;
|
||||
|
||||
if (bestStart > bestEnd)
|
||||
{
|
||||
swap(bestEnd, bestStart);
|
||||
bestPermutation ^= (~bestPermutation >> 1) & 0x55555555; // Flip indices.
|
||||
}
|
||||
}
|
||||
|
||||
error = evalPermutation4(colors, permutation, &start, &end);
|
||||
|
||||
if (error < bestError)
|
||||
{
|
||||
bestError = error;
|
||||
bestPermutation = permutation;
|
||||
bestStart = start;
|
||||
bestEnd = end;
|
||||
|
||||
if (bestStart < bestEnd)
|
||||
{
|
||||
swap(bestEnd, bestStart);
|
||||
bestPermutation ^= (~bestPermutation >> 1) & 0x55555555; // Flip indices.
|
||||
bestPermutation ^= 0x55555555; // Flip indices.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bestStart == bestEnd)
|
||||
{
|
||||
bestPermutation = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
__syncthreads();
|
||||
|
||||
// Use a parallel reduction to find minimum error.
|
||||
__shared__ float errors[THREAD_NUM];
|
||||
__shared__ int indices[THREAD_NUM];
|
||||
__shared__ float errors[NUM_THREADS];
|
||||
__shared__ int indices[NUM_THREADS];
|
||||
|
||||
errors[idx] = bestError;
|
||||
indices[idx] = idx;
|
||||
@ -451,31 +587,261 @@ __global__ void compress(const uint * permutations, const uint * image, uint * r
|
||||
// Only write the result of the winner thread.
|
||||
if (idx == indices[0])
|
||||
{
|
||||
if (bestStart == bestEnd)
|
||||
{
|
||||
bestPermutation = 0;
|
||||
}
|
||||
|
||||
// Reorder permutation.
|
||||
uint perm = 0;
|
||||
for(int i = 0; i < 16; i++)
|
||||
{
|
||||
int ref = xrefs[i];
|
||||
perm |= ((bestPermutation >> (2 * i)) & 3) << (2 * ref);
|
||||
perm |= ((bestPermutation >> (2 * ref)) & 3) << (2 * i);
|
||||
}
|
||||
|
||||
// Write endpoints. (bestStart, bestEnd)
|
||||
result[2 * bid + 0] = (bestEnd << 16) | bestStart;
|
||||
result[bid].x = (bestEnd << 16) | bestStart;
|
||||
|
||||
// Write palette indices (permutation).
|
||||
result[2 * bid + 1] = perm;
|
||||
result[bid].y = perm;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
__global__ void compressWeighted(const uint * permutations, const uint * image, uint2 * result)
|
||||
{
|
||||
const int bid = blockIdx.x;
|
||||
const int idx = threadIdx.x;
|
||||
|
||||
__shared__ float3 colors[16];
|
||||
__shared__ float weights[16];
|
||||
__shared__ float dps[16];
|
||||
__shared__ int xrefs[16];
|
||||
|
||||
if (idx < 16)
|
||||
{
|
||||
// Read color and copy to shared mem.
|
||||
uint c = image[(bid) * 16 + idx];
|
||||
|
||||
colors[idx].z = ((c >> 0) & 0xFF) * (1.0f / 255.0f);
|
||||
colors[idx].y = ((c >> 8) & 0xFF) * (1.0f / 255.0f);
|
||||
colors[idx].x = ((c >> 16) & 0xFF) * (1.0f / 255.0f);
|
||||
weights[idx] = ((c >> 24) & 0xFF) * (1.0f / 255.0f);
|
||||
|
||||
// No need to synchronize, 16 < warp size.
|
||||
#if __DEVICE_EMULATION__
|
||||
} __debugsync(); if (idx < 16) {
|
||||
#endif
|
||||
|
||||
// Sort colors along the best fit line.
|
||||
float3 axis = bestFitLine(colors);
|
||||
|
||||
dps[idx] = dot(colors[idx], axis);
|
||||
|
||||
#if __DEVICE_EMULATION__
|
||||
} __debugsync(); if (idx < 16) {
|
||||
#endif
|
||||
|
||||
sortColors(dps, colors, weights, xrefs);
|
||||
}
|
||||
|
||||
ushort bestStart, bestEnd;
|
||||
uint bestPermutation;
|
||||
float bestError = FLT_MAX;
|
||||
|
||||
__syncthreads();
|
||||
|
||||
#if 0
|
||||
// This version is more clear, but slightly slower.
|
||||
for(int i = 0; i < 16; i++)
|
||||
{
|
||||
if (i == 15 && idx >= 32) break;
|
||||
|
||||
ushort start, end;
|
||||
uint permutation = permutations[idx + NUM_THREADS * i];
|
||||
float error = evalPermutation4(colors, weights, permutation, &start, &end);
|
||||
|
||||
if (error < bestError)
|
||||
{
|
||||
bestError = error;
|
||||
bestPermutation = permutation;
|
||||
bestStart = start;
|
||||
bestEnd = end;
|
||||
}
|
||||
}
|
||||
|
||||
if (bestStart < bestEnd)
|
||||
{
|
||||
swap(bestEnd, bestStart);
|
||||
bestPermutation ^= 0x55555555; // Flip indices.
|
||||
}
|
||||
|
||||
for(int i = 0; i < 3; i++)
|
||||
{
|
||||
if (i == 2 && idx >= 32) break;
|
||||
|
||||
ushort start, end;
|
||||
uint permutation = permutations[idx + NUM_THREADS * i];
|
||||
float error = evalPermutation3(colors, weights, permutation, &start, &end);
|
||||
|
||||
if (error < bestError)
|
||||
{
|
||||
bestError = error;
|
||||
bestPermutation = permutation;
|
||||
bestStart = start;
|
||||
bestEnd = end;
|
||||
|
||||
if (bestStart > bestEnd)
|
||||
{
|
||||
swap(bestEnd, bestStart);
|
||||
bestPermutation ^= (~bestPermutation >> 1) & 0x55555555; // Flip indices.
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
{
|
||||
int pidx = idx + NUM_THREADS * 15;
|
||||
if (idx >= 32)
|
||||
{
|
||||
pidx = idx + NUM_THREADS * 2;
|
||||
}
|
||||
|
||||
ushort start, end;
|
||||
uint permutation = permutations[pidx];
|
||||
float error = evalPermutation4(colors, weights, permutation, &start, &end);
|
||||
|
||||
if (error < bestError)
|
||||
{
|
||||
bestError = error;
|
||||
bestPermutation = permutation;
|
||||
bestStart = start;
|
||||
bestEnd = end;
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 3; i < 15; i++)
|
||||
{
|
||||
ushort start, end;
|
||||
uint permutation = permutations[idx + NUM_THREADS * i];
|
||||
float error = evalPermutation4(colors, weights, permutation, &start, &end);
|
||||
|
||||
if (error < bestError)
|
||||
{
|
||||
bestError = error;
|
||||
bestPermutation = permutation;
|
||||
bestStart = start;
|
||||
bestEnd = end;
|
||||
}
|
||||
}
|
||||
|
||||
if (bestStart < bestEnd)
|
||||
{
|
||||
swap(bestEnd, bestStart);
|
||||
bestPermutation ^= 0x55555555; // Flip indices.
|
||||
}
|
||||
|
||||
|
||||
for(int i = 0; i < 3; i++)
|
||||
{
|
||||
if (i == 2 && idx >= 32) break;
|
||||
|
||||
ushort start, end;
|
||||
uint permutation = permutations[idx + NUM_THREADS * i];
|
||||
float error = evalPermutation3(colors, weights, permutation, &start, &end);
|
||||
|
||||
if (error < bestError)
|
||||
{
|
||||
bestError = error;
|
||||
bestPermutation = permutation;
|
||||
bestStart = start;
|
||||
bestEnd = end;
|
||||
|
||||
if (bestStart > bestEnd)
|
||||
{
|
||||
swap(bestEnd, bestStart);
|
||||
bestPermutation ^= (~bestPermutation >> 1) & 0x55555555; // Flip indices.
|
||||
}
|
||||
}
|
||||
|
||||
error = evalPermutation4(colors, weights, permutation, &start, &end);
|
||||
|
||||
if (error < bestError)
|
||||
{
|
||||
bestError = error;
|
||||
bestPermutation = permutation;
|
||||
bestStart = start;
|
||||
bestEnd = end;
|
||||
|
||||
if (bestStart < bestEnd)
|
||||
{
|
||||
swap(bestEnd, bestStart);
|
||||
bestPermutation ^= 0x55555555; // Flip indices.
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
__syncthreads();
|
||||
|
||||
// Use a parallel reduction to find minimum error.
|
||||
__shared__ float errors[NUM_THREADS];
|
||||
__shared__ int indices[NUM_THREADS];
|
||||
|
||||
errors[idx] = bestError;
|
||||
indices[idx] = idx;
|
||||
|
||||
minimizeError(errors, indices);
|
||||
|
||||
__syncthreads();
|
||||
|
||||
// Only write the result of the winner thread.
|
||||
if (idx == indices[0])
|
||||
{
|
||||
if (bestStart == bestEnd)
|
||||
{
|
||||
bestPermutation = 0;
|
||||
}
|
||||
|
||||
// Reorder permutation.
|
||||
uint perm = 0;
|
||||
for(int i = 0; i < 16; i++)
|
||||
{
|
||||
int ref = xrefs[i];
|
||||
perm |= ((bestPermutation >> (2 * ref)) & 3) << (2 * i);
|
||||
}
|
||||
|
||||
// Write endpoints. (bestStart, bestEnd)
|
||||
result[bid].x = (bestEnd << 16) | bestStart;
|
||||
|
||||
// Write palette indices (permutation).
|
||||
result[bid].y = perm;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Setup kernel
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
extern "C" void setupCompressKernel(const float weights[3])
|
||||
{
|
||||
// Set constants.
|
||||
cudaMemcpyToSymbol(kColorMetric, weights, sizeof(float) * 3, 0);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Launch kernel
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
extern "C" void compressKernel(uint blockNum, uint * d_data, uint * d_result, uint * d_bitmaps, float weights[3])
|
||||
{
|
||||
// Set constants.
|
||||
cudaMemcpyToSymbol(kColorMetric, weights, sizeof(float) * 3, 0);
|
||||
|
||||
compress<<<blockNum, THREAD_NUM>>>(d_bitmaps, d_data, d_result);
|
||||
extern "C" void compressKernel(uint blockNum, uint * d_data, uint * d_result, uint * d_bitmaps)
|
||||
{
|
||||
compress<<<blockNum, NUM_THREADS>>>(d_bitmaps, d_data, (uint2 *)d_result);
|
||||
}
|
||||
|
||||
extern "C" void compressWeightedKernel(uint blockNum, uint * d_data, uint * d_result, uint * d_bitmaps)
|
||||
{
|
||||
compressWeighted<<<blockNum, NUM_THREADS>>>(d_bitmaps, d_data, (uint2 *)d_result);
|
||||
}
|
||||
|
74
src/nvimage/nvtt/cuda/ConvolveKernel.cu
Normal file
74
src/nvimage/nvtt/cuda/ConvolveKernel.cu
Normal file
@ -0,0 +1,74 @@
|
||||
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "CudaMath.h"
|
||||
|
||||
#define THREAD_COUNT 256
|
||||
#define MAX_KERNEL_WIDTH 32
|
||||
|
||||
|
||||
#if __DEVICE_EMULATION__
|
||||
#define __debugsync() __syncthreads()
|
||||
#else
|
||||
#define __debugsync()
|
||||
#endif
|
||||
|
||||
|
||||
__constant__ float kernel[MAX_KERNEL_WIDTH];
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Monophase X convolution filter
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Monophase Y convolution filter
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Setup kernel
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
extern "C" void setupConvolveKernel(const float * k, int w)
|
||||
{
|
||||
w = min(w, MAX_KERNEL_WIDTH);
|
||||
cudaMemcpyToSymbol(kernel, k, sizeof(float) * w, 0);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Launch kernel
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
@ -24,7 +24,10 @@
|
||||
#include <nvcore/Debug.h>
|
||||
#include <nvcore/Containers.h>
|
||||
#include <nvmath/Color.h>
|
||||
#include <nvmath/Fitting.h>
|
||||
#include <nvimage/Image.h>
|
||||
#include <nvimage/ColorBlock.h>
|
||||
#include <nvimage/BlockDXT.h>
|
||||
#include <nvimage/nvtt/CompressionOptions.h>
|
||||
|
||||
#include "CudaCompressDXT.h"
|
||||
@ -34,13 +37,17 @@
|
||||
#include <cuda_runtime.h>
|
||||
#endif
|
||||
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
|
||||
using namespace nv;
|
||||
using namespace nvtt;
|
||||
|
||||
#if defined HAVE_CUDA
|
||||
|
||||
extern "C" void compressKernel(uint blockNum, uint * d_data, uint * d_result, uint * d_bitmaps, float weights[3]);
|
||||
|
||||
extern "C" void setupCompressKernel(const float weights[3]);
|
||||
extern "C" void compressKernel(uint blockNum, uint * d_data, uint * d_result, uint * d_bitmaps);
|
||||
extern "C" void compressWeightedKernel(uint blockNum, uint * d_data, uint * d_result, uint * d_bitmaps);
|
||||
|
||||
static uint * d_bitmaps = NULL;
|
||||
|
||||
@ -86,7 +93,7 @@ static void doPrecomputation()
|
||||
}
|
||||
|
||||
bitmaps[num] = bitmap;
|
||||
|
||||
|
||||
num++;
|
||||
}
|
||||
}
|
||||
@ -95,7 +102,7 @@ static void doPrecomputation()
|
||||
// Align to 160.
|
||||
for(int i = 0; i < 9; i++)
|
||||
{
|
||||
bitmaps[num] = 0x000AA555;
|
||||
bitmaps[num] = 0x555AA000;
|
||||
num++;
|
||||
}
|
||||
nvDebugCheck(num == 160);
|
||||
@ -153,25 +160,35 @@ static void doPrecomputation()
|
||||
// Align to 1024.
|
||||
for(int i = 0; i < 49; i++)
|
||||
{
|
||||
bitmaps[num] = 0x00AAFF55;
|
||||
bitmaps[num] = 0x555AA000;
|
||||
num++;
|
||||
}
|
||||
|
||||
nvDebugCheck(num == 1024);
|
||||
|
||||
/*
|
||||
printf("uint bitmaps[1024] = {\n");
|
||||
for (int i = 0; i < 1024; i++)
|
||||
{
|
||||
printf("\t0x%.8X,\n", bitmaps[i]);
|
||||
}
|
||||
printf("};\n");
|
||||
*/
|
||||
|
||||
// Upload bitmaps.
|
||||
cudaMalloc((void**) &d_bitmaps, 1024 * sizeof(uint));
|
||||
cudaMemcpy(d_bitmaps, bitmaps, 1024 * sizeof(uint), cudaMemcpyHostToDevice);
|
||||
|
||||
// @@ Check for errors.
|
||||
|
||||
// @@ Free allocated memory.
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/// Compress image using CUDA.
|
||||
void nv::cudaCompressDXT1(const Image * image, const OutputOptions & outputOptions, const nvtt::CompressionOptions::Private & compressionOptions)
|
||||
void nv::cudaCompressDXT1(const Image * image, const OutputOptions & outputOptions, const CompressionOptions::Private & compressionOptions)
|
||||
{
|
||||
nvDebugCheck(cuda::isHardwarePresent());
|
||||
#if defined HAVE_CUDA
|
||||
@ -192,7 +209,7 @@ void nv::cudaCompressDXT1(const Image * image, const OutputOptions & outputOptio
|
||||
const uint bh = min(image->height() - by * 4, 4U);
|
||||
|
||||
for (uint i = 0; i < 16; i++) {
|
||||
const int x = (i & 3) % bw;
|
||||
const int x = (i % 4) % bw;
|
||||
const int y = (i / 4) % bh;
|
||||
blockLinearImage[(by * w + bx) * 16 + i] = image->pixel(bx * 4 + x, by * 4 + y).u;
|
||||
}
|
||||
@ -211,6 +228,10 @@ void nv::cudaCompressDXT1(const Image * image, const OutputOptions & outputOptio
|
||||
uint * d_result = NULL;
|
||||
cudaMalloc((void**) &d_result, min(compressedSize, blockMax * 8U));
|
||||
|
||||
setupCompressKernel(compressionOptions.colorWeight.ptr());
|
||||
|
||||
clock_t start = clock();
|
||||
|
||||
// TODO: Add support for multiple GPUs.
|
||||
uint bn = 0;
|
||||
while(bn != blockNum)
|
||||
@ -220,11 +241,7 @@ void nv::cudaCompressDXT1(const Image * image, const OutputOptions & outputOptio
|
||||
cudaMemcpy(d_data, blockLinearImage + bn * 16, count * 64, cudaMemcpyHostToDevice);
|
||||
|
||||
// Launch kernel.
|
||||
float weights[3];
|
||||
weights[0] = compressionOptions.colorWeight.x();
|
||||
weights[1] = compressionOptions.colorWeight.y();
|
||||
weights[2] = compressionOptions.colorWeight.z();
|
||||
compressKernel(count, d_data, d_result, d_bitmaps, weights);
|
||||
compressKernel(count, d_data, d_result, d_bitmaps);
|
||||
|
||||
// Check for errors.
|
||||
cudaError_t err = cudaGetLastError();
|
||||
@ -234,7 +251,7 @@ void nv::cudaCompressDXT1(const Image * image, const OutputOptions & outputOptio
|
||||
|
||||
if (outputOptions.errorHandler != NULL)
|
||||
{
|
||||
outputOptions.errorHandler->error(nvtt::Error_CudaError);
|
||||
outputOptions.errorHandler->error(Error_CudaError);
|
||||
}
|
||||
}
|
||||
|
||||
@ -250,6 +267,9 @@ void nv::cudaCompressDXT1(const Image * image, const OutputOptions & outputOptio
|
||||
bn += count;
|
||||
}
|
||||
|
||||
clock_t end = clock();
|
||||
printf("\rCUDA time taken: %.3f seconds\n", float(end-start) / CLOCKS_PER_SEC);
|
||||
|
||||
free(blockLinearImage);
|
||||
cudaFree(d_data);
|
||||
cudaFree(d_result);
|
||||
@ -262,3 +282,189 @@ void nv::cudaCompressDXT1(const Image * image, const OutputOptions & outputOptio
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#if defined HAVE_CUDA
|
||||
|
||||
class Task
|
||||
{
|
||||
public:
|
||||
explicit Task(uint numBlocks) : blockMaxCount(numBlocks), blockCount(0)
|
||||
{
|
||||
// System memory allocations.
|
||||
blockLinearImage = new uint[blockMaxCount * 16];
|
||||
xrefs = new uint[blockMaxCount * 16];
|
||||
|
||||
// Device memory allocations.
|
||||
cudaMalloc((void**) &d_blockLinearImage, blockMaxCount * 16 * sizeof(uint));
|
||||
cudaMalloc((void**) &d_compressedImage, blockMaxCount * 8U);
|
||||
|
||||
// @@ Check for allocation errors.
|
||||
}
|
||||
|
||||
~Task()
|
||||
{
|
||||
delete [] blockLinearImage;
|
||||
delete [] xrefs;
|
||||
|
||||
cudaFree(d_blockLinearImage);
|
||||
cudaFree(d_compressedImage);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void addColorBlock(const ColorBlock & rgba)
|
||||
{
|
||||
nvDebugCheck(!isFull());
|
||||
|
||||
// @@ Count unique colors?
|
||||
/*
|
||||
// Convert colors to vectors.
|
||||
Array<Vector3> pointArray(16);
|
||||
|
||||
for(int i = 0; i < 16; i++) {
|
||||
const Color32 color = rgba.color(i);
|
||||
pointArray.append(Vector3(color.r, color.g, color.b));
|
||||
}
|
||||
|
||||
// Find best fit line.
|
||||
const Vector3 axis = Fit::bestLine(pointArray).direction();
|
||||
|
||||
// Project points to axis.
|
||||
float dps[16];
|
||||
uint * order = &xrefs[blockCount * 16];
|
||||
|
||||
for (uint i = 0; i < 16; ++i)
|
||||
{
|
||||
dps[i] = dot(pointArray[i], axis);
|
||||
order[i] = i;
|
||||
}
|
||||
|
||||
// Sort them.
|
||||
for (uint i = 0; i < 16; ++i)
|
||||
{
|
||||
for (uint j = i; j > 0 && dps[j] < dps[j - 1]; --j)
|
||||
{
|
||||
swap(dps[j], dps[j - 1]);
|
||||
swap(order[j], order[j - 1]);
|
||||
}
|
||||
}
|
||||
*/
|
||||
// Write sorted colors to blockLinearImage.
|
||||
for(uint i = 0; i < 16; ++i)
|
||||
{
|
||||
// blockLinearImage[blockCount * 16 + i] = rgba.color(order[i]);
|
||||
blockLinearImage[blockCount * 16 + i] = rgba.color(i);
|
||||
}
|
||||
|
||||
++blockCount;
|
||||
}
|
||||
|
||||
bool isFull()
|
||||
{
|
||||
nvDebugCheck(blockCount <= blockMaxCount);
|
||||
return blockCount == blockMaxCount;
|
||||
}
|
||||
|
||||
void flush(const OutputOptions & outputOptions)
|
||||
{
|
||||
if (blockCount == 0)
|
||||
{
|
||||
// Nothing to do.
|
||||
return;
|
||||
}
|
||||
|
||||
// Copy input color blocks.
|
||||
cudaMemcpy(d_blockLinearImage, blockLinearImage, blockCount * 64, cudaMemcpyHostToDevice);
|
||||
|
||||
// Launch kernel.
|
||||
compressKernel(blockCount, d_blockLinearImage, d_compressedImage, d_bitmaps);
|
||||
|
||||
// Check for errors.
|
||||
cudaError_t err = cudaGetLastError();
|
||||
if (err != cudaSuccess)
|
||||
{
|
||||
nvDebug("CUDA Error: %s\n", cudaGetErrorString(err));
|
||||
|
||||
if (outputOptions.errorHandler != NULL)
|
||||
{
|
||||
outputOptions.errorHandler->error(Error_CudaError);
|
||||
}
|
||||
}
|
||||
|
||||
// Copy result to host, overwrite swizzled image.
|
||||
uint * compressedImage = blockLinearImage;
|
||||
cudaMemcpy(compressedImage, d_compressedImage, blockCount * 8, cudaMemcpyDeviceToHost);
|
||||
|
||||
// @@ Sort block indices.
|
||||
|
||||
// Output result.
|
||||
if (outputOptions.outputHandler != NULL)
|
||||
{
|
||||
// outputOptions.outputHandler->writeData(compressedImage, blockCount * 8);
|
||||
}
|
||||
|
||||
blockCount = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
const uint blockMaxCount;
|
||||
uint blockCount;
|
||||
|
||||
uint * blockLinearImage;
|
||||
uint * xrefs;
|
||||
|
||||
uint * d_blockLinearImage;
|
||||
uint * d_compressedImage;
|
||||
|
||||
};
|
||||
|
||||
#endif // defined HAVE_CUDA
|
||||
|
||||
|
||||
void nv::cudaCompressDXT1_2(const Image * image, const OutputOptions & outputOptions, const CompressionOptions::Private & compressionOptions)
|
||||
{
|
||||
#if defined HAVE_CUDA
|
||||
const uint w = image->width();
|
||||
const uint h = image->height();
|
||||
|
||||
const uint blockNum = ((w + 3) / 4) * ((h + 3) / 4);
|
||||
const uint blockMax = 32768; // 65535
|
||||
|
||||
doPrecomputation();
|
||||
|
||||
setupCompressKernel(compressionOptions.colorWeight.ptr());
|
||||
|
||||
ColorBlock rgba;
|
||||
Task task(min(blockNum, blockMax));
|
||||
|
||||
clock_t start = clock();
|
||||
|
||||
for (uint y = 0; y < h; y += 4) {
|
||||
for (uint x = 0; x < w; x += 4) {
|
||||
|
||||
rgba.init(image, x, y);
|
||||
|
||||
task.addColorBlock(rgba);
|
||||
|
||||
if (task.isFull())
|
||||
{
|
||||
task.flush(outputOptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
task.flush(outputOptions);
|
||||
|
||||
clock_t end = clock();
|
||||
printf("\rCUDA time taken: %.3f seconds\n", float(end-start) / CLOCKS_PER_SEC);
|
||||
|
||||
#else
|
||||
if (outputOptions.errorHandler != NULL)
|
||||
{
|
||||
outputOptions.errorHandler->error(Error_CudaError);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -32,7 +32,8 @@ namespace nv
|
||||
class Image;
|
||||
|
||||
void cudaCompressDXT1(const Image * image, const nvtt::OutputOptions & outputOptions, const nvtt::CompressionOptions::Private & compressionOptions);
|
||||
|
||||
void cudaCompressDXT1_2(const Image * image, const nvtt::OutputOptions & outputOptions, const nvtt::CompressionOptions::Private & compressionOptions);
|
||||
|
||||
} // nv namespace
|
||||
|
||||
|
||||
|
@ -111,7 +111,7 @@ inline __device__ __host__ float3 clamp(float3 v, float3 a, float3 b)
|
||||
|
||||
inline __device__ __host__ float3 normalize(float3 v)
|
||||
{
|
||||
float len = 1.0f / dot(v, v);
|
||||
float len = 1.0f / sqrtf(dot(v, v));
|
||||
return make_float3(v.x * len, v.y * len, v.z * len);
|
||||
}
|
||||
|
||||
|
@ -73,8 +73,12 @@ static bool isWow32()
|
||||
bool nv::cuda::isHardwarePresent()
|
||||
{
|
||||
#if defined HAVE_CUDA
|
||||
#if NV_OS_WIN32
|
||||
return !isWindowsVista() && deviceCount() > 0;
|
||||
//return !isWindowsVista() && isWow32() && deviceCount() > 0;
|
||||
#else
|
||||
return deviceCount() > 0;
|
||||
#endif
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
|
@ -1,486 +1,485 @@
|
||||
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#include <nvcore/Memory.h>
|
||||
#include <nvcore/Ptr.h>
|
||||
|
||||
#include <nvimage/DirectDrawSurface.h>
|
||||
#include <nvimage/ColorBlock.h>
|
||||
#include <nvimage/Image.h>
|
||||
#include <nvimage/FloatImage.h>
|
||||
#include <nvimage/Filter.h>
|
||||
#include <nvimage/Quantize.h>
|
||||
#include <nvimage/NormalMap.h>
|
||||
|
||||
#include "CompressDXT.h"
|
||||
#include "FastCompressDXT.h"
|
||||
#include "CompressRGB.h"
|
||||
#include "BlockDXT.h"
|
||||
#include "InputOptions.h"
|
||||
#include "CompressionOptions.h"
|
||||
#include "cuda/CudaUtils.h"
|
||||
#include "cuda/CudaCompressDXT.h"
|
||||
|
||||
|
||||
using namespace nv;
|
||||
using namespace nvtt;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
static int blockSize(Format format)
|
||||
{
|
||||
if (format == Format_DXT1 /*|| format == Format_DXT1a*/) {
|
||||
return 8;
|
||||
}
|
||||
else if (format == Format_DXT3) {
|
||||
return 16;
|
||||
}
|
||||
else if (format == Format_DXT5 || format == Format_DXT5n) {
|
||||
return 16;
|
||||
}
|
||||
else if (format == Format_BC4) {
|
||||
return 8;
|
||||
}
|
||||
else if (format == Format_BC5) {
|
||||
return 16;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int computeImageSize(int w, int h, Format format)
|
||||
{
|
||||
if (format == Format_RGBA) {
|
||||
return w * h * sizeof(Color32);
|
||||
}
|
||||
else {
|
||||
return ((w + 3) / 4) * ((h + 3) / 4) * blockSize(format);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// compress
|
||||
//
|
||||
|
||||
static void outputHeader(const InputOptions::Private & inputOptions, const OutputOptions & outputOptions, const CompressionOptions::Private & compressionOptions)
|
||||
{
|
||||
// Output DDS header.
|
||||
if (outputOptions.outputHandler != NULL && outputOptions.outputHeader)
|
||||
{
|
||||
DDSHeader header;
|
||||
|
||||
// Only 1 face and 2d textures supported.
|
||||
nvCheck(inputOptions.faceCount == 1);
|
||||
|
||||
InputOptions::Private::Image * img = inputOptions.images;
|
||||
nvCheck(img != NULL);
|
||||
|
||||
header.setWidth(img->width);
|
||||
header.setHeight(img->height);
|
||||
|
||||
int mipmapCount = inputOptions.mipmapCount;
|
||||
if (!inputOptions.generateMipmaps) mipmapCount = 0;
|
||||
else if (inputOptions.maxLevel != -1 && inputOptions.maxLevel < mipmapCount) mipmapCount = inputOptions.maxLevel;
|
||||
header.setMipmapCount(mipmapCount);
|
||||
|
||||
if (inputOptions.textureType == TextureType_2D) {
|
||||
header.setTexture2D();
|
||||
}
|
||||
else if (inputOptions.textureType == TextureType_Cube) {
|
||||
header.setTextureCube();
|
||||
}
|
||||
/*else if (inputOptions.textureType == TextureType_3D) {
|
||||
header.setTexture3D();
|
||||
header.setDepth(img->depth);
|
||||
}*/
|
||||
|
||||
if (compressionOptions.format == Format_RGBA)
|
||||
{
|
||||
header.setPitch(4 * img->width);
|
||||
header.setPixelFormat(compressionOptions.bitcount, compressionOptions.rmask, compressionOptions.gmask, compressionOptions.bmask, compressionOptions.amask);
|
||||
}
|
||||
else
|
||||
{
|
||||
header.setLinearSize(computeImageSize(img->width, img->height, compressionOptions.format));
|
||||
|
||||
if (compressionOptions.format == Format_DXT1 /*|| compressionOptions.format == Format_DXT1a*/) {
|
||||
header.setFourCC('D', 'X', 'T', '1');
|
||||
}
|
||||
else if (compressionOptions.format == Format_DXT3) {
|
||||
header.setFourCC('D', 'X', 'T', '3');
|
||||
}
|
||||
else if (compressionOptions.format == Format_DXT5) {
|
||||
header.setFourCC('D', 'X', 'T', '5');
|
||||
}
|
||||
else if (compressionOptions.format == Format_DXT5n) {
|
||||
header.setFourCC('R', 'X', 'G', 'B');
|
||||
}
|
||||
else if (compressionOptions.format == Format_BC4) {
|
||||
header.setFourCC('A', 'T', 'I', '1');
|
||||
}
|
||||
else if (compressionOptions.format == Format_BC5) {
|
||||
header.setFourCC('A', 'T', 'I', '2');
|
||||
}
|
||||
}
|
||||
|
||||
// Swap bytes if necessary.
|
||||
header.swapBytes();
|
||||
|
||||
nvStaticCheck(sizeof(DDSHeader) == 128);
|
||||
outputOptions.outputHandler->writeData(&header, 128);
|
||||
|
||||
// Revert swap.
|
||||
header.swapBytes();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static bool compressMipmap(const Image * image, const OutputOptions & outputOptions, const CompressionOptions::Private & compressionOptions)
|
||||
{
|
||||
nvDebugCheck(image != NULL);
|
||||
|
||||
if (compressionOptions.format == Format_RGBA || compressionOptions.format == Format_RGB)
|
||||
{
|
||||
compressRGB(image, outputOptions, compressionOptions);
|
||||
}
|
||||
else if (compressionOptions.format == Format_DXT1)
|
||||
{
|
||||
#if defined(HAVE_S3QUANT)
|
||||
if (compressionOptions.externalCompressor == "s3")
|
||||
{
|
||||
s3CompressDXT1(image, outputOptions);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_ATITC)
|
||||
if (compressionOptions.externalCompressor == "ati")
|
||||
{
|
||||
printf("ATI\n");
|
||||
atiCompressDXT1(image, outputOptions);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (compressionOptions.useCuda && nv::cuda::isHardwarePresent())
|
||||
{
|
||||
cudaCompressDXT1(image, outputOptions, compressionOptions);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (compressionOptions.quality == Quality_Fastest)
|
||||
{
|
||||
fastCompressDXT1(image, outputOptions);
|
||||
}
|
||||
else
|
||||
{
|
||||
compressDXT1(image, outputOptions, compressionOptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (compressionOptions.format == Format_DXT3)
|
||||
{
|
||||
if (compressionOptions.quality == Quality_Fastest)
|
||||
{
|
||||
fastCompressDXT3(image, outputOptions);
|
||||
}
|
||||
else
|
||||
{
|
||||
compressDXT3(image, outputOptions, compressionOptions);
|
||||
}
|
||||
}
|
||||
else if (compressionOptions.format == Format_DXT5)
|
||||
{
|
||||
if (compressionOptions.quality == Quality_Fastest)
|
||||
{
|
||||
fastCompressDXT5(image, outputOptions);
|
||||
}
|
||||
else
|
||||
{
|
||||
compressDXT5(image, outputOptions, compressionOptions);
|
||||
}
|
||||
}
|
||||
else if (compressionOptions.format == Format_DXT5n)
|
||||
{
|
||||
if (compressionOptions.quality == Quality_Fastest)
|
||||
{
|
||||
fastCompressDXT5n(image, outputOptions);
|
||||
}
|
||||
else
|
||||
{
|
||||
compressDXT5n(image, outputOptions, compressionOptions);
|
||||
}
|
||||
}
|
||||
else if (compressionOptions.format == Format_BC4)
|
||||
{
|
||||
compressBC4(image, outputOptions, compressionOptions);
|
||||
}
|
||||
else if (compressionOptions.format == Format_BC5)
|
||||
{
|
||||
compressBC5(image, outputOptions, compressionOptions);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Convert input image to linear float image.
|
||||
static FloatImage * toFloatImage(const Image * image, const InputOptions::Private & inputOptions)
|
||||
{
|
||||
nvDebugCheck(image != NULL);
|
||||
|
||||
FloatImage * floatImage = new FloatImage(image);
|
||||
|
||||
// Convert to linear space.
|
||||
if (inputOptions.inputGamma != 1.0f) {
|
||||
floatImage->toLinear(0, 3, inputOptions.inputGamma);
|
||||
}
|
||||
|
||||
return floatImage;
|
||||
}
|
||||
|
||||
|
||||
// Convert linear float image to output image.
|
||||
static Image * toFixedImage(const FloatImage * floatImage, const InputOptions::Private & inputOptions)
|
||||
{
|
||||
nvDebugCheck(floatImage != NULL);
|
||||
|
||||
return floatImage->createImageGammaCorrect(inputOptions.outputGamma);
|
||||
}
|
||||
|
||||
|
||||
// Create mipmap from the given image.
|
||||
static FloatImage * createMipmap(const FloatImage * floatImage, const InputOptions::Private & inputOptions)
|
||||
{
|
||||
FloatImage * result = NULL;
|
||||
|
||||
if (inputOptions.mipmapFilter == MipmapFilter_Box)
|
||||
{
|
||||
// Use fast downsample.
|
||||
result = floatImage->fastDownSample();
|
||||
}
|
||||
else if (inputOptions.mipmapFilter == MipmapFilter_Triangle)
|
||||
{
|
||||
Kernel1 kernel(4);
|
||||
kernel.initFilter(Filter::Triangle);
|
||||
result = floatImage->downSample(kernel, (FloatImage::WrapMode)inputOptions.wrapMode);
|
||||
}
|
||||
else /*if (inputOptions.mipmapFilter == MipmapFilter_Kaiser)*/
|
||||
{
|
||||
Kernel1 kernel(10);
|
||||
kernel.initKaiser(8.0, 0.75f);
|
||||
result = floatImage->downSample(kernel, (FloatImage::WrapMode)inputOptions.wrapMode);
|
||||
}
|
||||
|
||||
// Normalize mipmap.
|
||||
if (inputOptions.normalizeMipmaps)
|
||||
{
|
||||
normalize(result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// Quantize the input image to the precision of the output format.
|
||||
static void quantize(Image * img, const InputOptions::Private & inputOptions, Format format)
|
||||
{
|
||||
if (inputOptions.enableColorDithering)
|
||||
{
|
||||
if (format >= Format_DXT1 && format <= Format_DXT5)
|
||||
{
|
||||
Quantize::FloydSteinberg_RGB16(img);
|
||||
}
|
||||
}
|
||||
if (inputOptions.binaryAlpha)
|
||||
{
|
||||
if (inputOptions.enableAlphaDithering)
|
||||
{
|
||||
Quantize::FloydSteinberg_BinaryAlpha(img, inputOptions.alphaThreshold);
|
||||
}
|
||||
else
|
||||
{
|
||||
Quantize::BinaryAlpha(img, inputOptions.alphaThreshold);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (inputOptions.enableAlphaDithering)
|
||||
{
|
||||
if (format == Format_DXT3)
|
||||
{
|
||||
Quantize::Alpha4(img);
|
||||
}
|
||||
/*else if (format == Format_DXT1a)
|
||||
{
|
||||
Quantize::BinaryAlpha(img, inputOptions.alphaThreshold);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Compress the input texture with the given compression options.
|
||||
bool nvtt::compress(const InputOptions & inputOptions, const OutputOptions & outputOptions, const CompressionOptions & compressionOptions)
|
||||
{
|
||||
// Make sure enums match.
|
||||
nvStaticCheck(FloatImage::WrapMode_Clamp == (FloatImage::WrapMode)WrapMode_Clamp);
|
||||
nvStaticCheck(FloatImage::WrapMode_Mirror == (FloatImage::WrapMode)WrapMode_Mirror);
|
||||
nvStaticCheck(FloatImage::WrapMode_Repeat == (FloatImage::WrapMode)WrapMode_Repeat);
|
||||
|
||||
// Output DDS header.
|
||||
outputHeader(inputOptions.m, outputOptions, compressionOptions.m);
|
||||
|
||||
Format format = compressionOptions.m.format;
|
||||
|
||||
for (int f = 0; f < inputOptions.m.faceCount; f++)
|
||||
{
|
||||
Image * lastImage = NULL;
|
||||
AutoPtr<FloatImage> floatImage(NULL);
|
||||
|
||||
for (int m = 0; m < inputOptions.m.mipmapCount; m++)
|
||||
{
|
||||
int idx = f * inputOptions.m.mipmapCount + m;
|
||||
InputOptions::Private::Image & mipmap = inputOptions.m.images[idx];
|
||||
|
||||
if (outputOptions.outputHandler)
|
||||
{
|
||||
int size = computeImageSize(mipmap.width, mipmap.height, format);
|
||||
outputOptions.outputHandler->mipmap(size, mipmap.width, mipmap.height, mipmap.depth, mipmap.face, mipmap.mipLevel);
|
||||
}
|
||||
|
||||
Image * img; // Image to compress.
|
||||
|
||||
if (mipmap.data != NULL) // Mipmap provided.
|
||||
{
|
||||
// Convert to normal map.
|
||||
if (inputOptions.m.convertToNormalMap)
|
||||
{
|
||||
floatImage = createNormalMap(mipmap.data, (FloatImage::WrapMode)inputOptions.m.wrapMode, inputOptions.m.heightFactors, inputOptions.m.bumpFrequencyScale);
|
||||
}
|
||||
else
|
||||
{
|
||||
lastImage = img = mipmap.data;
|
||||
|
||||
// Delete float image.
|
||||
floatImage = NULL;
|
||||
}
|
||||
}
|
||||
else // Create mipmap from last.
|
||||
{
|
||||
if (m == 0) {
|
||||
// First mipmap missing.
|
||||
if (outputOptions.errorHandler != NULL) outputOptions.errorHandler->error(Error_InvalidInput);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (floatImage == NULL)
|
||||
{
|
||||
nvDebugCheck(lastImage != NULL);
|
||||
floatImage = toFloatImage(lastImage, inputOptions.m);
|
||||
}
|
||||
|
||||
// Create mipmap.
|
||||
floatImage = createMipmap(floatImage.ptr(), inputOptions.m);
|
||||
}
|
||||
|
||||
if (floatImage != NULL)
|
||||
{
|
||||
// Convert to fixed.
|
||||
img = toFixedImage(floatImage.ptr(), inputOptions.m);
|
||||
}
|
||||
|
||||
quantize(img, inputOptions.m, format);
|
||||
|
||||
compressMipmap(img, outputOptions, compressionOptions.m);
|
||||
|
||||
if (img != mipmap.data)
|
||||
{
|
||||
delete img;
|
||||
}
|
||||
|
||||
if (!inputOptions.m.generateMipmaps || (inputOptions.m.maxLevel >= 0 && m >= inputOptions.m.maxLevel)) {
|
||||
// continue with next face.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// Estimate the size of compressing the input with the given options.
|
||||
int nvtt::estimateSize(const InputOptions & inputOptions, const CompressionOptions & compressionOptions)
|
||||
{
|
||||
Format format = compressionOptions.m.format;
|
||||
|
||||
int size = 0;
|
||||
|
||||
for (int f = 0; f < inputOptions.m.faceCount; f++)
|
||||
{
|
||||
for (int m = 0; m < inputOptions.m.mipmapCount; m++)
|
||||
{
|
||||
int idx = f * inputOptions.m.mipmapCount + m;
|
||||
const InputOptions::Private::Image & img = inputOptions.m.images[idx];
|
||||
|
||||
size += computeImageSize(img.width, img.height, format);
|
||||
|
||||
if (!inputOptions.m.generateMipmaps || (inputOptions.m.maxLevel >= 0 && m >= inputOptions.m.maxLevel)) {
|
||||
// continue with next face.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
/// Return a string for the given error.
|
||||
const char * nvtt::errorString(Error e)
|
||||
{
|
||||
switch(e)
|
||||
{
|
||||
case Error_InvalidInput:
|
||||
return "Invalid input";
|
||||
case Error_UserInterruption:
|
||||
return "User interruption";
|
||||
case Error_UnsupportedFeature:
|
||||
return "Unsupported feature";
|
||||
case Error_CudaError:
|
||||
return "CUDA error";
|
||||
case Error_Unknown:
|
||||
return "Unknown error";
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#include <nvcore/Memory.h>
|
||||
#include <nvcore/Ptr.h>
|
||||
|
||||
#include <nvimage/DirectDrawSurface.h>
|
||||
#include <nvimage/ColorBlock.h>
|
||||
#include <nvimage/BlockDXT.h>
|
||||
#include <nvimage/Image.h>
|
||||
#include <nvimage/FloatImage.h>
|
||||
#include <nvimage/Filter.h>
|
||||
#include <nvimage/Quantize.h>
|
||||
#include <nvimage/NormalMap.h>
|
||||
|
||||
#include "CompressDXT.h"
|
||||
#include "FastCompressDXT.h"
|
||||
#include "CompressRGB.h"
|
||||
#include "InputOptions.h"
|
||||
#include "CompressionOptions.h"
|
||||
#include "cuda/CudaUtils.h"
|
||||
#include "cuda/CudaCompressDXT.h"
|
||||
|
||||
|
||||
using namespace nv;
|
||||
using namespace nvtt;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
static int blockSize(Format format)
|
||||
{
|
||||
if (format == Format_DXT1 /*|| format == Format_DXT1a*/) {
|
||||
return 8;
|
||||
}
|
||||
else if (format == Format_DXT3) {
|
||||
return 16;
|
||||
}
|
||||
else if (format == Format_DXT5 || format == Format_DXT5n) {
|
||||
return 16;
|
||||
}
|
||||
else if (format == Format_BC4) {
|
||||
return 8;
|
||||
}
|
||||
else if (format == Format_BC5) {
|
||||
return 16;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int computeImageSize(int w, int h, Format format)
|
||||
{
|
||||
if (format == Format_RGBA) {
|
||||
return w * h * sizeof(Color32);
|
||||
}
|
||||
else {
|
||||
return ((w + 3) / 4) * ((h + 3) / 4) * blockSize(format);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// compress
|
||||
//
|
||||
|
||||
static void outputHeader(const InputOptions::Private & inputOptions, const OutputOptions & outputOptions, const CompressionOptions::Private & compressionOptions)
|
||||
{
|
||||
// Output DDS header.
|
||||
if (outputOptions.outputHandler != NULL && outputOptions.outputHeader)
|
||||
{
|
||||
DDSHeader header;
|
||||
|
||||
InputOptions::Private::Image * img = inputOptions.images;
|
||||
nvCheck(img != NULL);
|
||||
|
||||
header.setWidth(img->width);
|
||||
header.setHeight(img->height);
|
||||
|
||||
int mipmapCount = inputOptions.mipmapCount;
|
||||
if (!inputOptions.generateMipmaps) mipmapCount = 0;
|
||||
else if (inputOptions.maxLevel != -1 && inputOptions.maxLevel < mipmapCount) mipmapCount = inputOptions.maxLevel;
|
||||
header.setMipmapCount(mipmapCount);
|
||||
|
||||
if (inputOptions.textureType == TextureType_2D) {
|
||||
header.setTexture2D();
|
||||
}
|
||||
else if (inputOptions.textureType == TextureType_Cube) {
|
||||
header.setTextureCube();
|
||||
}
|
||||
/*else if (inputOptions.textureType == TextureType_3D) {
|
||||
header.setTexture3D();
|
||||
header.setDepth(img->depth);
|
||||
}*/
|
||||
|
||||
if (compressionOptions.format == Format_RGBA)
|
||||
{
|
||||
header.setPitch(4 * img->width);
|
||||
header.setPixelFormat(compressionOptions.bitcount, compressionOptions.rmask, compressionOptions.gmask, compressionOptions.bmask, compressionOptions.amask);
|
||||
}
|
||||
else
|
||||
{
|
||||
header.setLinearSize(computeImageSize(img->width, img->height, compressionOptions.format));
|
||||
|
||||
if (compressionOptions.format == Format_DXT1 /*|| compressionOptions.format == Format_DXT1a*/) {
|
||||
header.setFourCC('D', 'X', 'T', '1');
|
||||
}
|
||||
else if (compressionOptions.format == Format_DXT3) {
|
||||
header.setFourCC('D', 'X', 'T', '3');
|
||||
}
|
||||
else if (compressionOptions.format == Format_DXT5) {
|
||||
header.setFourCC('D', 'X', 'T', '5');
|
||||
}
|
||||
else if (compressionOptions.format == Format_DXT5n) {
|
||||
header.setFourCC('D', 'X', 'T', '5');
|
||||
header.setNormalFlag(true);
|
||||
}
|
||||
else if (compressionOptions.format == Format_BC4) {
|
||||
header.setFourCC('A', 'T', 'I', '1');
|
||||
}
|
||||
else if (compressionOptions.format == Format_BC5) {
|
||||
header.setFourCC('A', 'T', 'I', '2');
|
||||
header.setNormalFlag(true);
|
||||
}
|
||||
}
|
||||
|
||||
// Swap bytes if necessary.
|
||||
header.swapBytes();
|
||||
|
||||
nvStaticCheck(sizeof(DDSHeader) == 128);
|
||||
outputOptions.outputHandler->writeData(&header, 128);
|
||||
|
||||
// Revert swap.
|
||||
header.swapBytes();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static bool compressMipmap(const Image * image, const OutputOptions & outputOptions, const CompressionOptions::Private & compressionOptions)
|
||||
{
|
||||
nvDebugCheck(image != NULL);
|
||||
|
||||
if (compressionOptions.format == Format_RGBA || compressionOptions.format == Format_RGB)
|
||||
{
|
||||
compressRGB(image, outputOptions, compressionOptions);
|
||||
}
|
||||
else if (compressionOptions.format == Format_DXT1)
|
||||
{
|
||||
#if defined(HAVE_S3QUANT)
|
||||
if (compressionOptions.externalCompressor == "s3")
|
||||
{
|
||||
s3CompressDXT1(image, outputOptions);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_ATITC)
|
||||
if (compressionOptions.externalCompressor == "ati")
|
||||
{
|
||||
printf("ATI\n");
|
||||
atiCompressDXT1(image, outputOptions);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (compressionOptions.useCuda && nv::cuda::isHardwarePresent())
|
||||
{
|
||||
cudaCompressDXT1(image, outputOptions, compressionOptions);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (compressionOptions.quality == Quality_Fastest)
|
||||
{
|
||||
fastCompressDXT1(image, outputOptions);
|
||||
}
|
||||
else
|
||||
{
|
||||
compressDXT1(image, outputOptions, compressionOptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (compressionOptions.format == Format_DXT3)
|
||||
{
|
||||
if (compressionOptions.quality == Quality_Fastest)
|
||||
{
|
||||
fastCompressDXT3(image, outputOptions);
|
||||
}
|
||||
else
|
||||
{
|
||||
compressDXT3(image, outputOptions, compressionOptions);
|
||||
}
|
||||
}
|
||||
else if (compressionOptions.format == Format_DXT5)
|
||||
{
|
||||
if (compressionOptions.quality == Quality_Fastest)
|
||||
{
|
||||
fastCompressDXT5(image, outputOptions);
|
||||
}
|
||||
else
|
||||
{
|
||||
compressDXT5(image, outputOptions, compressionOptions);
|
||||
}
|
||||
}
|
||||
else if (compressionOptions.format == Format_DXT5n)
|
||||
{
|
||||
if (compressionOptions.quality == Quality_Fastest)
|
||||
{
|
||||
fastCompressDXT5n(image, outputOptions);
|
||||
}
|
||||
else
|
||||
{
|
||||
compressDXT5n(image, outputOptions, compressionOptions);
|
||||
}
|
||||
}
|
||||
else if (compressionOptions.format == Format_BC4)
|
||||
{
|
||||
compressBC4(image, outputOptions, compressionOptions);
|
||||
}
|
||||
else if (compressionOptions.format == Format_BC5)
|
||||
{
|
||||
compressBC5(image, outputOptions, compressionOptions);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Convert input image to linear float image.
|
||||
static FloatImage * toFloatImage(const Image * image, const InputOptions::Private & inputOptions)
|
||||
{
|
||||
nvDebugCheck(image != NULL);
|
||||
|
||||
FloatImage * floatImage = new FloatImage(image);
|
||||
|
||||
// Convert to linear space.
|
||||
if (inputOptions.inputGamma != 1.0f) {
|
||||
floatImage->toLinear(0, 3, inputOptions.inputGamma);
|
||||
}
|
||||
|
||||
return floatImage;
|
||||
}
|
||||
|
||||
|
||||
// Convert linear float image to output image.
|
||||
static Image * toFixedImage(const FloatImage * floatImage, const InputOptions::Private & inputOptions)
|
||||
{
|
||||
nvDebugCheck(floatImage != NULL);
|
||||
|
||||
return floatImage->createImageGammaCorrect(inputOptions.outputGamma);
|
||||
}
|
||||
|
||||
|
||||
// Create mipmap from the given image.
|
||||
static FloatImage * createMipmap(const FloatImage * floatImage, const InputOptions::Private & inputOptions)
|
||||
{
|
||||
FloatImage * result = NULL;
|
||||
|
||||
if (inputOptions.mipmapFilter == MipmapFilter_Box)
|
||||
{
|
||||
// Use fast downsample.
|
||||
result = floatImage->fastDownSample();
|
||||
}
|
||||
else if (inputOptions.mipmapFilter == MipmapFilter_Triangle)
|
||||
{
|
||||
Kernel1 kernel(4);
|
||||
kernel.initFilter(Filter::Triangle);
|
||||
result = floatImage->downSample(kernel, (FloatImage::WrapMode)inputOptions.wrapMode);
|
||||
}
|
||||
else /*if (inputOptions.mipmapFilter == MipmapFilter_Kaiser)*/
|
||||
{
|
||||
Kernel1 kernel(10);
|
||||
kernel.initKaiser(8.0, 0.75f);
|
||||
result = floatImage->downSample(kernel, (FloatImage::WrapMode)inputOptions.wrapMode);
|
||||
}
|
||||
|
||||
// Normalize mipmap.
|
||||
if (inputOptions.normalizeMipmaps)
|
||||
{
|
||||
normalize(result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// Quantize the input image to the precision of the output format.
|
||||
static void quantize(Image * img, const InputOptions::Private & inputOptions, Format format)
|
||||
{
|
||||
if (inputOptions.enableColorDithering)
|
||||
{
|
||||
if (format >= Format_DXT1 && format <= Format_DXT5)
|
||||
{
|
||||
Quantize::FloydSteinberg_RGB16(img);
|
||||
}
|
||||
}
|
||||
if (inputOptions.binaryAlpha)
|
||||
{
|
||||
if (inputOptions.enableAlphaDithering)
|
||||
{
|
||||
Quantize::FloydSteinberg_BinaryAlpha(img, inputOptions.alphaThreshold);
|
||||
}
|
||||
else
|
||||
{
|
||||
Quantize::BinaryAlpha(img, inputOptions.alphaThreshold);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (inputOptions.enableAlphaDithering)
|
||||
{
|
||||
if (format == Format_DXT3)
|
||||
{
|
||||
Quantize::Alpha4(img);
|
||||
}
|
||||
/*else if (format == Format_DXT1a)
|
||||
{
|
||||
Quantize::BinaryAlpha(img, inputOptions.alphaThreshold);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Compress the input texture with the given compression options.
|
||||
bool nvtt::compress(const InputOptions & inputOptions, const OutputOptions & outputOptions, const CompressionOptions & compressionOptions)
|
||||
{
|
||||
// Make sure enums match.
|
||||
nvStaticCheck(FloatImage::WrapMode_Clamp == (FloatImage::WrapMode)WrapMode_Clamp);
|
||||
nvStaticCheck(FloatImage::WrapMode_Mirror == (FloatImage::WrapMode)WrapMode_Mirror);
|
||||
nvStaticCheck(FloatImage::WrapMode_Repeat == (FloatImage::WrapMode)WrapMode_Repeat);
|
||||
|
||||
// Output DDS header.
|
||||
outputHeader(inputOptions.m, outputOptions, compressionOptions.m);
|
||||
|
||||
Format format = compressionOptions.m.format;
|
||||
|
||||
for (int f = 0; f < inputOptions.m.faceCount; f++)
|
||||
{
|
||||
Image * lastImage = NULL;
|
||||
AutoPtr<FloatImage> floatImage(NULL);
|
||||
|
||||
for (int m = 0; m < inputOptions.m.mipmapCount; m++)
|
||||
{
|
||||
int idx = f * inputOptions.m.mipmapCount + m;
|
||||
InputOptions::Private::Image & mipmap = inputOptions.m.images[idx];
|
||||
|
||||
if (outputOptions.outputHandler)
|
||||
{
|
||||
int size = computeImageSize(mipmap.width, mipmap.height, format);
|
||||
outputOptions.outputHandler->mipmap(size, mipmap.width, mipmap.height, mipmap.depth, mipmap.face, mipmap.mipLevel);
|
||||
}
|
||||
|
||||
Image * img; // Image to compress.
|
||||
|
||||
if (mipmap.data != NULL) // Mipmap provided.
|
||||
{
|
||||
// Convert to normal map.
|
||||
if (inputOptions.m.convertToNormalMap)
|
||||
{
|
||||
floatImage = createNormalMap(mipmap.data, (FloatImage::WrapMode)inputOptions.m.wrapMode, inputOptions.m.heightFactors, inputOptions.m.bumpFrequencyScale);
|
||||
}
|
||||
else
|
||||
{
|
||||
lastImage = img = mipmap.data;
|
||||
|
||||
// Delete float image.
|
||||
floatImage = NULL;
|
||||
}
|
||||
}
|
||||
else // Create mipmap from last.
|
||||
{
|
||||
if (m == 0) {
|
||||
// First mipmap missing.
|
||||
if (outputOptions.errorHandler != NULL) outputOptions.errorHandler->error(Error_InvalidInput);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (floatImage == NULL)
|
||||
{
|
||||
nvDebugCheck(lastImage != NULL);
|
||||
floatImage = toFloatImage(lastImage, inputOptions.m);
|
||||
}
|
||||
|
||||
// Create mipmap.
|
||||
floatImage = createMipmap(floatImage.ptr(), inputOptions.m);
|
||||
}
|
||||
|
||||
if (floatImage != NULL)
|
||||
{
|
||||
// Convert to fixed.
|
||||
img = toFixedImage(floatImage.ptr(), inputOptions.m);
|
||||
}
|
||||
|
||||
quantize(img, inputOptions.m, format);
|
||||
|
||||
compressMipmap(img, outputOptions, compressionOptions.m);
|
||||
|
||||
if (img != mipmap.data)
|
||||
{
|
||||
delete img;
|
||||
}
|
||||
|
||||
if (!inputOptions.m.generateMipmaps || (inputOptions.m.maxLevel >= 0 && m >= inputOptions.m.maxLevel)) {
|
||||
// continue with next face.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// Estimate the size of compressing the input with the given options.
|
||||
int nvtt::estimateSize(const InputOptions & inputOptions, const CompressionOptions & compressionOptions)
|
||||
{
|
||||
Format format = compressionOptions.m.format;
|
||||
|
||||
int size = 0;
|
||||
|
||||
for (int f = 0; f < inputOptions.m.faceCount; f++)
|
||||
{
|
||||
for (int m = 0; m < inputOptions.m.mipmapCount; m++)
|
||||
{
|
||||
int idx = f * inputOptions.m.mipmapCount + m;
|
||||
const InputOptions::Private::Image & img = inputOptions.m.images[idx];
|
||||
|
||||
size += computeImageSize(img.width, img.height, format);
|
||||
|
||||
if (!inputOptions.m.generateMipmaps || (inputOptions.m.maxLevel >= 0 && m >= inputOptions.m.maxLevel)) {
|
||||
// continue with next face.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
/// Return a string for the given error.
|
||||
const char * nvtt::errorString(Error e)
|
||||
{
|
||||
switch(e)
|
||||
{
|
||||
case Error_InvalidInput:
|
||||
return "Invalid input";
|
||||
case Error_UserInterruption:
|
||||
return "User interruption";
|
||||
case Error_UnsupportedFeature:
|
||||
return "Unsupported feature";
|
||||
case Error_CudaError:
|
||||
return "CUDA error";
|
||||
case Error_Unknown:
|
||||
return "Unknown error";
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1,242 +1,245 @@
|
||||
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#ifndef NV_TT_H
|
||||
#define NV_TT_H
|
||||
|
||||
#include <nvcore/nvcore.h>
|
||||
|
||||
// Function linkage
|
||||
#if NVTT_SHARED
|
||||
#ifdef NVTT_EXPORTS
|
||||
#define NVTT_API DLL_EXPORT
|
||||
#define NVTT_CLASS DLL_EXPORT_CLASS
|
||||
#else
|
||||
#define NVTT_API DLL_IMPORT
|
||||
#define NVTT_CLASS DLL_IMPORT
|
||||
#endif
|
||||
#else
|
||||
#define NVTT_API
|
||||
#define NVTT_CLASS
|
||||
#endif
|
||||
|
||||
// Public interface.
|
||||
namespace nvtt
|
||||
{
|
||||
/// Supported compression formats.
|
||||
enum Format
|
||||
{
|
||||
// No compression.
|
||||
Format_RGB,
|
||||
Format_RGBA = Format_RGB,
|
||||
|
||||
// DX9 formats.
|
||||
Format_DXT1,
|
||||
// Format_DXT1a, // DXT1 with binary alpha.
|
||||
Format_DXT3,
|
||||
Format_DXT5,
|
||||
Format_DXT5n, // Compressed HILO: R=0, G=x, B=0, A=y
|
||||
|
||||
// DX10 formats.
|
||||
Format_BC1 = Format_DXT1,
|
||||
Format_BC2 = Format_DXT3,
|
||||
Format_BC3 = Format_DXT5,
|
||||
Format_BC3n = Format_DXT5n,
|
||||
Format_BC4, // ATI1
|
||||
Format_BC5, // 3DC, ATI2
|
||||
|
||||
// OpenGL formats.
|
||||
Format_LATC = Format_BC5,
|
||||
};
|
||||
|
||||
/// Quality modes.
|
||||
enum Quality
|
||||
{
|
||||
Quality_Fastest,
|
||||
Quality_Normal,
|
||||
Quality_Production,
|
||||
Quality_Highest,
|
||||
};
|
||||
|
||||
/// Compression options. This class describes the desired compression format and other compression settings.
|
||||
class CompressionOptions
|
||||
{
|
||||
public:
|
||||
NVTT_API CompressionOptions();
|
||||
NVTT_API ~CompressionOptions();
|
||||
|
||||
NVTT_API void reset();
|
||||
|
||||
NVTT_API void setFormat(Format format);
|
||||
NVTT_API void setQuality(Quality quality, float errorThreshold = 0.5f);
|
||||
NVTT_API void setColorWeights(float red, float green, float blue);
|
||||
NVTT_API void enableHardwareCompression(bool enable);
|
||||
|
||||
NVTT_API void setExternalCompressor(const char * name);
|
||||
|
||||
// Set color mask to describe the RGB/RGBA format.
|
||||
NVTT_API void setPixelFormat(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask);
|
||||
|
||||
//private:
|
||||
struct Private;
|
||||
Private & m;
|
||||
};
|
||||
|
||||
|
||||
/// Wrap modes. // This matches FloatImage::WrapMode.
|
||||
enum WrapMode
|
||||
{
|
||||
WrapMode_Clamp,
|
||||
WrapMode_Repeat,
|
||||
WrapMode_Mirror,
|
||||
};
|
||||
|
||||
/// Texture types.
|
||||
enum TextureType
|
||||
{
|
||||
TextureType_2D,
|
||||
TextureType_Cube,
|
||||
// TextureType_3D,
|
||||
};
|
||||
|
||||
/// Input formats.
|
||||
enum InputFormat
|
||||
{
|
||||
InputFormat_BGRA_8UB,
|
||||
// InputFormat_RGBE_8UB,
|
||||
// InputFormat_BGRA_32F,
|
||||
};
|
||||
|
||||
/// Mipmap downsampling filters.
|
||||
enum MipmapFilter
|
||||
{
|
||||
MipmapFilter_Box, ///< Box filter is quite good and very fast.
|
||||
MipmapFilter_Triangle, ///< Triangle filter blurs the results too much, but that might be what you want.
|
||||
MipmapFilter_Kaiser, ///< Kaiser-windowed Sinc filter is the best downsampling filter.
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// Input options. Specify format and layout of the input texture.
|
||||
struct InputOptions
|
||||
{
|
||||
NVTT_API InputOptions();
|
||||
NVTT_API ~InputOptions();
|
||||
|
||||
// Set default options.
|
||||
NVTT_API void reset();
|
||||
|
||||
// Setup input layout.
|
||||
NVTT_API void setTextureLayout(TextureType type, int w, int h, int d = 1);
|
||||
NVTT_API void resetTextureLayout();
|
||||
|
||||
// Set mipmap data. Copies the data.
|
||||
NVTT_API bool setMipmapData(const void * data, int w, int h, int d = 1, int face = 0, int mipmap = 0);
|
||||
|
||||
// Describe the format of the input.
|
||||
NVTT_API void setFormat(InputFormat fmt, bool alphaTransparency);
|
||||
|
||||
// Set gamma settings.
|
||||
NVTT_API void setGamma(float inputGamma, float outputGamma);
|
||||
|
||||
// Set texture wrappign mode.
|
||||
NVTT_API void setWrapMode(WrapMode mode);
|
||||
|
||||
// Set mipmapping options.
|
||||
NVTT_API void setMipmapping(bool generateMipmaps, MipmapFilter filter = MipmapFilter_Kaiser, int maxLevel = -1);
|
||||
|
||||
// Set quantization options.
|
||||
NVTT_API void setQuantization(bool colorDithering, bool alphaDithering, bool binaryAlpha, int alphaThreshold = 127);
|
||||
|
||||
// Set normal map options.
|
||||
NVTT_API void setConvertToNormalMap(bool convert);
|
||||
NVTT_API void setHeightEvaluation(float redScale, float greenScale, float blueScale, float alphaScale);
|
||||
NVTT_API void setNormalFilter(float small, float medium, float big, float large);
|
||||
NVTT_API void setNormalizeMipmaps(bool b);
|
||||
|
||||
//private:
|
||||
struct Private;
|
||||
Private & m;
|
||||
};
|
||||
|
||||
|
||||
/// Output handler.
|
||||
struct OutputHandler
|
||||
{
|
||||
virtual ~OutputHandler() {}
|
||||
|
||||
/// Indicate the start of a new compressed image that's part of the final texture.
|
||||
virtual void mipmap(int size, int width, int height, int depth, int face, int miplevel) = 0;
|
||||
|
||||
/// Output data. Compressed data is output as soon as it's generated to minimize memory allocations.
|
||||
virtual void writeData(const void * data, int size) = 0;
|
||||
};
|
||||
|
||||
/// Error codes.
|
||||
enum Error
|
||||
{
|
||||
Error_InvalidInput,
|
||||
Error_UserInterruption,
|
||||
Error_UnsupportedFeature,
|
||||
Error_CudaError,
|
||||
Error_Unknown,
|
||||
};
|
||||
|
||||
/// Error handler.
|
||||
struct ErrorHandler
|
||||
{
|
||||
virtual ~ErrorHandler() {}
|
||||
|
||||
// Signal error.
|
||||
virtual void error(Error e) = 0;
|
||||
};
|
||||
|
||||
|
||||
/// Output Options. This class holds pointers to the interfaces that are used to report the output of
|
||||
/// the compressor to the user.
|
||||
struct OutputOptions
|
||||
{
|
||||
OutputOptions() : outputHandler(NULL), outputHeader(true) { reset(); }
|
||||
OutputOptions(OutputHandler * oh, ErrorHandler * eh) : outputHandler(oh), errorHandler(eh), outputHeader(true) { reset(); }
|
||||
|
||||
// Set default options.
|
||||
NVTT_API void reset();
|
||||
|
||||
OutputHandler * outputHandler;
|
||||
ErrorHandler * errorHandler;
|
||||
bool outputHeader;
|
||||
};
|
||||
|
||||
|
||||
// Main entrypoint of the compression library.
|
||||
NVTT_API bool compress(const InputOptions & inputOptions, const OutputOptions & outputOptions, const CompressionOptions & compressionOptions);
|
||||
|
||||
// Estimate the size of compressing the input with the given options.
|
||||
NVTT_API int estimateSize(const InputOptions & inputOptions, const CompressionOptions & compressionOptions);
|
||||
|
||||
// Return string for the given error.
|
||||
NVTT_API const char * errorString(Error e);
|
||||
|
||||
} // nvtt namespace
|
||||
|
||||
#endif // NV_TT_H
|
||||
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#ifndef NV_TT_H
|
||||
#define NV_TT_H
|
||||
|
||||
#include <nvcore/nvcore.h>
|
||||
|
||||
//#define HAVE_S3QUANT
|
||||
//#define HAVE_ATITC
|
||||
|
||||
// Function linkage
|
||||
#if NVTT_SHARED
|
||||
#ifdef NVTT_EXPORTS
|
||||
#define NVTT_API DLL_EXPORT
|
||||
#define NVTT_CLASS DLL_EXPORT_CLASS
|
||||
#else
|
||||
#define NVTT_API DLL_IMPORT
|
||||
#define NVTT_CLASS DLL_IMPORT
|
||||
#endif
|
||||
#else
|
||||
#define NVTT_API
|
||||
#define NVTT_CLASS
|
||||
#endif
|
||||
|
||||
// Public interface.
|
||||
namespace nvtt
|
||||
{
|
||||
/// Supported compression formats.
|
||||
enum Format
|
||||
{
|
||||
// No compression.
|
||||
Format_RGB,
|
||||
Format_RGBA = Format_RGB,
|
||||
|
||||
// DX9 formats.
|
||||
Format_DXT1,
|
||||
// Format_DXT1a, // DXT1 with binary alpha.
|
||||
Format_DXT3,
|
||||
Format_DXT5,
|
||||
Format_DXT5n, // Compressed HILO: R=0, G=x, B=0, A=y
|
||||
|
||||
// DX10 formats.
|
||||
Format_BC1 = Format_DXT1,
|
||||
Format_BC2 = Format_DXT3,
|
||||
Format_BC3 = Format_DXT5,
|
||||
Format_BC3n = Format_DXT5n,
|
||||
Format_BC4, // ATI1
|
||||
Format_BC5, // 3DC, ATI2
|
||||
|
||||
// OpenGL formats.
|
||||
Format_LATC = Format_BC5,
|
||||
};
|
||||
|
||||
/// Quality modes.
|
||||
enum Quality
|
||||
{
|
||||
Quality_Fastest,
|
||||
Quality_Normal,
|
||||
Quality_Production,
|
||||
Quality_Highest,
|
||||
};
|
||||
|
||||
/// Compression options. This class describes the desired compression format and other compression settings.
|
||||
class CompressionOptions
|
||||
{
|
||||
public:
|
||||
NVTT_API CompressionOptions();
|
||||
NVTT_API ~CompressionOptions();
|
||||
|
||||
NVTT_API void reset();
|
||||
|
||||
NVTT_API void setFormat(Format format);
|
||||
NVTT_API void setQuality(Quality quality, float errorThreshold = 0.5f);
|
||||
NVTT_API void setColorWeights(float red, float green, float blue);
|
||||
NVTT_API void enableHardwareCompression(bool enable);
|
||||
|
||||
NVTT_API void setExternalCompressor(const char * name);
|
||||
|
||||
// Set color mask to describe the RGB/RGBA format.
|
||||
NVTT_API void setPixelFormat(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask);
|
||||
|
||||
//private:
|
||||
struct Private;
|
||||
Private & m;
|
||||
};
|
||||
|
||||
|
||||
/// Wrap modes. // This matches FloatImage::WrapMode.
|
||||
enum WrapMode
|
||||
{
|
||||
WrapMode_Clamp,
|
||||
WrapMode_Repeat,
|
||||
WrapMode_Mirror,
|
||||
};
|
||||
|
||||
/// Texture types.
|
||||
enum TextureType
|
||||
{
|
||||
TextureType_2D,
|
||||
TextureType_Cube,
|
||||
// TextureType_3D,
|
||||
};
|
||||
|
||||
/// Input formats.
|
||||
enum InputFormat
|
||||
{
|
||||
InputFormat_BGRA_8UB,
|
||||
// InputFormat_RGBE_8UB,
|
||||
// InputFormat_BGRA_32F,
|
||||
};
|
||||
|
||||
/// Mipmap downsampling filters.
|
||||
enum MipmapFilter
|
||||
{
|
||||
MipmapFilter_Box, ///< Box filter is quite good and very fast.
|
||||
MipmapFilter_Triangle, ///< Triangle filter blurs the results too much, but that might be what you want.
|
||||
MipmapFilter_Kaiser, ///< Kaiser-windowed Sinc filter is the best downsampling filter.
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// Input options. Specify format and layout of the input texture.
|
||||
struct InputOptions
|
||||
{
|
||||
NVTT_API InputOptions();
|
||||
NVTT_API ~InputOptions();
|
||||
|
||||
// Set default options.
|
||||
NVTT_API void reset();
|
||||
|
||||
// Setup input layout.
|
||||
NVTT_API void setTextureLayout(TextureType type, int w, int h, int d = 1);
|
||||
NVTT_API void resetTextureLayout();
|
||||
|
||||
// Set mipmap data. Copies the data.
|
||||
NVTT_API bool setMipmapData(const void * data, int w, int h, int d = 1, int face = 0, int mipmap = 0);
|
||||
|
||||
// Describe the format of the input.
|
||||
NVTT_API void setFormat(InputFormat fmt, bool alphaTransparency);
|
||||
|
||||
// Set gamma settings.
|
||||
NVTT_API void setGamma(float inputGamma, float outputGamma);
|
||||
|
||||
// Set texture wrappign mode.
|
||||
NVTT_API void setWrapMode(WrapMode mode);
|
||||
|
||||
// Set mipmapping options.
|
||||
NVTT_API void setMipmapping(bool generateMipmaps, MipmapFilter filter = MipmapFilter_Kaiser, int maxLevel = -1);
|
||||
|
||||
// Set quantization options.
|
||||
NVTT_API void setQuantization(bool colorDithering, bool alphaDithering, bool binaryAlpha, int alphaThreshold = 127);
|
||||
|
||||
// Set normal map options.
|
||||
NVTT_API void setConvertToNormalMap(bool convert);
|
||||
NVTT_API void setHeightEvaluation(float redScale, float greenScale, float blueScale, float alphaScale);
|
||||
NVTT_API void setNormalFilter(float small, float medium, float big, float large);
|
||||
NVTT_API void setNormalizeMipmaps(bool b);
|
||||
|
||||
//private:
|
||||
struct Private;
|
||||
Private & m;
|
||||
};
|
||||
|
||||
|
||||
/// Output handler.
|
||||
struct OutputHandler
|
||||
{
|
||||
virtual ~OutputHandler() {}
|
||||
|
||||
/// Indicate the start of a new compressed image that's part of the final texture.
|
||||
virtual void mipmap(int size, int width, int height, int depth, int face, int miplevel) = 0;
|
||||
|
||||
/// Output data. Compressed data is output as soon as it's generated to minimize memory allocations.
|
||||
virtual void writeData(const void * data, int size) = 0;
|
||||
};
|
||||
|
||||
/// Error codes.
|
||||
enum Error
|
||||
{
|
||||
Error_InvalidInput,
|
||||
Error_UserInterruption,
|
||||
Error_UnsupportedFeature,
|
||||
Error_CudaError,
|
||||
Error_Unknown,
|
||||
};
|
||||
|
||||
/// Error handler.
|
||||
struct ErrorHandler
|
||||
{
|
||||
virtual ~ErrorHandler() {}
|
||||
|
||||
// Signal error.
|
||||
virtual void error(Error e) = 0;
|
||||
};
|
||||
|
||||
|
||||
/// Output Options. This class holds pointers to the interfaces that are used to report the output of
|
||||
/// the compressor to the user.
|
||||
struct OutputOptions
|
||||
{
|
||||
OutputOptions() : outputHandler(NULL), outputHeader(true) { reset(); }
|
||||
OutputOptions(OutputHandler * oh, ErrorHandler * eh) : outputHandler(oh), errorHandler(eh), outputHeader(true) { reset(); }
|
||||
|
||||
// Set default options.
|
||||
NVTT_API void reset();
|
||||
|
||||
OutputHandler * outputHandler;
|
||||
ErrorHandler * errorHandler;
|
||||
bool outputHeader;
|
||||
};
|
||||
|
||||
|
||||
// Main entrypoint of the compression library.
|
||||
NVTT_API bool compress(const InputOptions & inputOptions, const OutputOptions & outputOptions, const CompressionOptions & compressionOptions);
|
||||
|
||||
// Estimate the size of compressing the input with the given options.
|
||||
NVTT_API int estimateSize(const InputOptions & inputOptions, const CompressionOptions & compressionOptions);
|
||||
|
||||
// Return string for the given error.
|
||||
NVTT_API const char * errorString(Error e);
|
||||
|
||||
} // nvtt namespace
|
||||
|
||||
#endif // NV_TT_H
|
||||
|
65
src/nvimage/nvtt/tools/cmdline.h
Normal file
65
src/nvimage/nvtt/tools/cmdline.h
Normal file
@ -0,0 +1,65 @@
|
||||
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#ifndef CMDLINE_H
|
||||
#define CMDLINE_H
|
||||
|
||||
#include <nvcore/Debug.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
struct MyMessageHandler : public nv::MessageHandler {
|
||||
MyMessageHandler() {
|
||||
nv::debug::setMessageHandler( this );
|
||||
}
|
||||
~MyMessageHandler() {
|
||||
nv::debug::resetMessageHandler();
|
||||
}
|
||||
|
||||
virtual void log( const char * str, va_list arg ) {
|
||||
va_list val;
|
||||
va_copy(val, arg);
|
||||
vfprintf(stderr, str, arg);
|
||||
va_end(val);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct MyAssertHandler : public nv::AssertHandler {
|
||||
MyAssertHandler() {
|
||||
nv::debug::setAssertHandler( this );
|
||||
}
|
||||
~MyAssertHandler() {
|
||||
nv::debug::resetAssertHandler();
|
||||
}
|
||||
|
||||
// Handler method, note that func might be NULL!
|
||||
virtual int assert( const char *exp, const char *file, int line, const char *func ) {
|
||||
fprintf(stderr, "Assertion failed: %s\nIn %s:%d\n", exp, file, line);
|
||||
nv::debug::dumpInfo();
|
||||
exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif // CMDLINE_H
|
@ -1,354 +1,427 @@
|
||||
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#include <nvcore/StrLib.h>
|
||||
#include <nvcore/StdStream.h>
|
||||
|
||||
#include <nvimage/Image.h>
|
||||
#include <nvimage/nvtt/nvtt.h>
|
||||
|
||||
#include "cmdline.h"
|
||||
|
||||
#include <time.h> // clock
|
||||
|
||||
struct MyOutputHandler : public nvtt::OutputHandler
|
||||
{
|
||||
MyOutputHandler() : total(0), progress(0), percentage(0), stream(NULL) {}
|
||||
MyOutputHandler(const char * name) : total(0), progress(0), percentage(0), stream(new nv::StdOutputStream(name)) {}
|
||||
virtual ~MyOutputHandler() { delete stream; }
|
||||
|
||||
bool open(const char * name)
|
||||
{
|
||||
stream = new nv::StdOutputStream(name);
|
||||
percentage = progress = 0;
|
||||
if (stream->isError()) {
|
||||
printf("Error opening '%s' for writting\n", name);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void setTotal(int t)
|
||||
{
|
||||
total = t;
|
||||
}
|
||||
|
||||
virtual void mipmap(int size, int width, int height, int depth, int face, int miplevel)
|
||||
{
|
||||
// ignore.
|
||||
}
|
||||
|
||||
// Output data.
|
||||
virtual void writeData(const void * data, int size)
|
||||
{
|
||||
nvDebugCheck(stream != NULL);
|
||||
stream->serialize(const_cast<void *>(data), size);
|
||||
|
||||
progress += size;
|
||||
int p = (100 * progress) / total;
|
||||
if (p != percentage)
|
||||
{
|
||||
percentage = p;
|
||||
printf("\r%d%%", percentage);
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
int total;
|
||||
int progress;
|
||||
int percentage;
|
||||
nv::StdOutputStream * stream;
|
||||
};
|
||||
|
||||
struct MyErrorHandler : public nvtt::ErrorHandler
|
||||
{
|
||||
virtual void error(nvtt::Error e)
|
||||
{
|
||||
nvDebugBreak();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
// Set color to normal map conversion options.
|
||||
void setColorToNormalMap(nvtt::InputOptions & inputOptions)
|
||||
{
|
||||
inputOptions.setConvertToNormalMap(true);
|
||||
inputOptions.setHeightEvaluation(1.0f/3.0f, 1.0f/3.0f, 1.0f/3.0f, 0.0f);
|
||||
//inputOptions.setNormalFilter(1.0f, 0, 0, 0);
|
||||
//inputOptions.setNormalFilter(0.0f, 0, 0, 1);
|
||||
inputOptions.setGamma(1.0f, 1.0f);
|
||||
inputOptions.setNormalizeMipmaps(true);
|
||||
}
|
||||
|
||||
// Set options for normal maps.
|
||||
void setNormalMap(nvtt::InputOptions & inputOptions)
|
||||
{
|
||||
inputOptions.setConvertToNormalMap(false);
|
||||
inputOptions.setGamma(1.0f, 1.0f);
|
||||
inputOptions.setNormalizeMipmaps(true);
|
||||
}
|
||||
|
||||
// Set options for color maps.
|
||||
void setColorMap(nvtt::InputOptions & inputOptions)
|
||||
{
|
||||
inputOptions.setConvertToNormalMap(false);
|
||||
inputOptions.setGamma(2.2f, 2.2f);
|
||||
inputOptions.setNormalizeMipmaps(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
MyAssertHandler assertHandler;
|
||||
MyMessageHandler messageHandler;
|
||||
|
||||
bool normal = false;
|
||||
bool color2normal = false;
|
||||
bool wrapRepeat = false;
|
||||
bool noMipmaps = false;
|
||||
bool fast = false;
|
||||
bool nocuda = false;
|
||||
nvtt::Format format = nvtt::Format_BC1;
|
||||
|
||||
const char * externalCompressor = NULL;
|
||||
|
||||
nv::Path input;
|
||||
nv::Path output;
|
||||
|
||||
|
||||
// Parse arguments.
|
||||
for (int i = 1; i < argc; i++)
|
||||
{
|
||||
// Input options.
|
||||
if (strcmp("-color", argv[i]) == 0)
|
||||
{
|
||||
}
|
||||
else if (strcmp("-normal", argv[i]) == 0)
|
||||
{
|
||||
normal = true;
|
||||
}
|
||||
else if (strcmp("-tonormal", argv[i]) == 0)
|
||||
{
|
||||
color2normal = true;
|
||||
}
|
||||
else if (strcmp("-clamp", argv[i]) == 0)
|
||||
{
|
||||
}
|
||||
else if (strcmp("-repeat", argv[i]) == 0)
|
||||
{
|
||||
wrapRepeat = true;
|
||||
}
|
||||
else if (strcmp("-nomips", argv[i]) == 0)
|
||||
{
|
||||
noMipmaps = true;
|
||||
}
|
||||
|
||||
// Compression options.
|
||||
else if (strcmp("-fast", argv[i]) == 0)
|
||||
{
|
||||
fast = true;
|
||||
}
|
||||
else if (strcmp("-nocuda", argv[i]) == 0)
|
||||
{
|
||||
nocuda = true;
|
||||
}
|
||||
else if (strcmp("-rgb", argv[i]) == 0)
|
||||
{
|
||||
format = nvtt::Format_RGB;
|
||||
}
|
||||
else if (strcmp("-bc1", argv[i]) == 0)
|
||||
{
|
||||
format = nvtt::Format_BC1;
|
||||
}
|
||||
else if (strcmp("-bc2", argv[i]) == 0)
|
||||
{
|
||||
format = nvtt::Format_BC2;
|
||||
}
|
||||
else if (strcmp("-bc3", argv[i]) == 0)
|
||||
{
|
||||
format = nvtt::Format_BC3;
|
||||
}
|
||||
else if (strcmp("-bc3n", argv[i]) == 0)
|
||||
{
|
||||
format = nvtt::Format_BC3n;
|
||||
}
|
||||
else if (strcmp("-bc4", argv[i]) == 0)
|
||||
{
|
||||
format = nvtt::Format_BC4;
|
||||
}
|
||||
else if (strcmp("-bc5", argv[i]) == 0)
|
||||
{
|
||||
format = nvtt::Format_BC5;
|
||||
}
|
||||
|
||||
// Undocumented option. Mainly used for testing.
|
||||
else if (strcmp("-ext", argv[i]) == 0)
|
||||
{
|
||||
if (i+1 < argc && argv[i+1][0] != '-') {
|
||||
externalCompressor = argv[i+1];
|
||||
printf("using %s\n", argv[i+1]);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
else if (argv[i][0] != '-')
|
||||
{
|
||||
input = argv[i];
|
||||
|
||||
if (i+1 < argc && argv[i+1][0] != '-') {
|
||||
output = argv[i+1];
|
||||
}
|
||||
else
|
||||
{
|
||||
output.copy(input.str());
|
||||
output.stripExtension();
|
||||
output.append(".dds");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (input.empty())
|
||||
{
|
||||
printf("NVIDIA Texture Tools - Copyright NVIDIA Corporation 2007\n\n");
|
||||
|
||||
printf("usage: nvcompress [options] infile [outfile]\n\n");
|
||||
|
||||
printf("Input options:\n");
|
||||
printf(" -color \tThe input image is a color map (default).\n");
|
||||
printf(" -normal \tThe input image is a normal map.\n");
|
||||
printf(" -tonormal\tConvert input to normal map.\n");
|
||||
printf(" -clamp \tClamp wrapping mode (default).\n");
|
||||
printf(" -repeat \tRepeat wrapping mode.\n");
|
||||
printf(" -nomips \tDisable mipmap generation.\n\n");
|
||||
|
||||
printf("Compression options:\n");
|
||||
printf(" -fast \tFast compression.\n");
|
||||
printf(" -nocuda \tDo not use cuda compressor.\n");
|
||||
printf(" -rgb \tRGBA format\n");
|
||||
printf(" -bc1 \tBC1 format (DXT1)\n");
|
||||
printf(" -bc2 \tBC2 format (DXT3)\n");
|
||||
printf(" -bc3 \tBC3 format (DXT5)\n");
|
||||
printf(" -bc3n \tBC3 normal map format (DXT5n/RXGB)\n");
|
||||
printf(" -bc4 \tBC4 format (ATI1)\n");
|
||||
printf(" -bc5 \tBC5 format (3Dc/ATI2)\n\n");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
nv::Image image;
|
||||
if (!image.load(input))
|
||||
{
|
||||
printf("The file '%s' is not a supported image type.\n", input.str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
MyErrorHandler errorHandler;
|
||||
MyOutputHandler outputHandler(output);
|
||||
if (outputHandler.stream->isError())
|
||||
{
|
||||
printf("Error opening '%s' for writting\n", output.str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Set input options.
|
||||
nvtt::InputOptions inputOptions;
|
||||
inputOptions.setTextureLayout(nvtt::TextureType_2D, image.width(), image.height());
|
||||
inputOptions.setMipmapData(image.pixels(), image.width(), image.height());
|
||||
|
||||
if (fast)
|
||||
{
|
||||
inputOptions.setMipmapping(true, nvtt::MipmapFilter_Box);
|
||||
}
|
||||
else
|
||||
{
|
||||
inputOptions.setMipmapping(true, nvtt::MipmapFilter_Kaiser);
|
||||
}
|
||||
|
||||
if (wrapRepeat)
|
||||
{
|
||||
inputOptions.setWrapMode(nvtt::WrapMode_Repeat);
|
||||
}
|
||||
else
|
||||
{
|
||||
inputOptions.setWrapMode(nvtt::WrapMode_Clamp);
|
||||
}
|
||||
|
||||
if (normal)
|
||||
{
|
||||
setNormalMap(inputOptions);
|
||||
}
|
||||
else if (color2normal)
|
||||
{
|
||||
setColorToNormalMap(inputOptions);
|
||||
}
|
||||
else
|
||||
{
|
||||
setColorMap(inputOptions);
|
||||
}
|
||||
|
||||
if (noMipmaps)
|
||||
{
|
||||
inputOptions.setMipmapping(false);
|
||||
}
|
||||
|
||||
|
||||
nvtt::CompressionOptions compressionOptions;
|
||||
compressionOptions.setFormat(format);
|
||||
if (fast)
|
||||
{
|
||||
compressionOptions.setQuality(nvtt::Quality_Fastest);
|
||||
}
|
||||
else
|
||||
{
|
||||
compressionOptions.setQuality(nvtt::Quality_Normal);
|
||||
//compressionOptions.setQuality(nvtt::Quality_Production, 0.5f);
|
||||
//compressionOptions.setQuality(nvtt::Quality_Highest);
|
||||
}
|
||||
compressionOptions.enableHardwareCompression(!nocuda);
|
||||
compressionOptions.setColorWeights(1, 1, 1);
|
||||
|
||||
if (externalCompressor != NULL)
|
||||
{
|
||||
compressionOptions.setExternalCompressor(externalCompressor);
|
||||
}
|
||||
|
||||
outputHandler.setTotal(nvtt::estimateSize(inputOptions, compressionOptions));
|
||||
|
||||
nvtt::OutputOptions outputOptions(&outputHandler, &errorHandler);
|
||||
|
||||
clock_t start = clock();
|
||||
|
||||
nvtt::compress(inputOptions, outputOptions, compressionOptions);
|
||||
|
||||
clock_t end = clock();
|
||||
printf("\rtime taken: %.3f seconds\n", float(end-start) / CLOCKS_PER_SEC);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#include <nvcore/StrLib.h>
|
||||
#include <nvcore/StdStream.h>
|
||||
|
||||
#include <nvimage/Image.h>
|
||||
#include <nvimage/DirectDrawSurface.h>
|
||||
#include <nvimage/nvtt/nvtt.h>
|
||||
|
||||
#include "cmdline.h"
|
||||
|
||||
#include <time.h> // clock
|
||||
|
||||
//#define WINDOWS_LEAN_AND_MEAN
|
||||
//#include <windows.h> // TIMER
|
||||
|
||||
struct MyOutputHandler : public nvtt::OutputHandler
|
||||
{
|
||||
MyOutputHandler() : total(0), progress(0), percentage(0), stream(NULL) {}
|
||||
MyOutputHandler(const char * name) : total(0), progress(0), percentage(0), stream(new nv::StdOutputStream(name)) {}
|
||||
virtual ~MyOutputHandler() { delete stream; }
|
||||
|
||||
bool open(const char * name)
|
||||
{
|
||||
stream = new nv::StdOutputStream(name);
|
||||
percentage = progress = 0;
|
||||
if (stream->isError()) {
|
||||
printf("Error opening '%s' for writting\n", name);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void setTotal(int t)
|
||||
{
|
||||
total = t;
|
||||
}
|
||||
|
||||
virtual void mipmap(int size, int width, int height, int depth, int face, int miplevel)
|
||||
{
|
||||
// ignore.
|
||||
}
|
||||
|
||||
// Output data.
|
||||
virtual void writeData(const void * data, int size)
|
||||
{
|
||||
nvDebugCheck(stream != NULL);
|
||||
stream->serialize(const_cast<void *>(data), size);
|
||||
|
||||
progress += size;
|
||||
int p = (100 * progress) / total;
|
||||
if (p != percentage)
|
||||
{
|
||||
percentage = p;
|
||||
printf("\r%d%%", percentage);
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
int total;
|
||||
int progress;
|
||||
int percentage;
|
||||
nv::StdOutputStream * stream;
|
||||
};
|
||||
|
||||
struct MyErrorHandler : public nvtt::ErrorHandler
|
||||
{
|
||||
virtual void error(nvtt::Error e)
|
||||
{
|
||||
nvDebugBreak();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
// Set color to normal map conversion options.
|
||||
void setColorToNormalMap(nvtt::InputOptions & inputOptions)
|
||||
{
|
||||
inputOptions.setConvertToNormalMap(true);
|
||||
inputOptions.setHeightEvaluation(1.0f/3.0f, 1.0f/3.0f, 1.0f/3.0f, 0.0f);
|
||||
//inputOptions.setNormalFilter(1.0f, 0, 0, 0);
|
||||
//inputOptions.setNormalFilter(0.0f, 0, 0, 1);
|
||||
inputOptions.setGamma(1.0f, 1.0f);
|
||||
inputOptions.setNormalizeMipmaps(true);
|
||||
}
|
||||
|
||||
// Set options for normal maps.
|
||||
void setNormalMap(nvtt::InputOptions & inputOptions)
|
||||
{
|
||||
inputOptions.setConvertToNormalMap(false);
|
||||
inputOptions.setGamma(1.0f, 1.0f);
|
||||
inputOptions.setNormalizeMipmaps(true);
|
||||
}
|
||||
|
||||
// Set options for color maps.
|
||||
void setColorMap(nvtt::InputOptions & inputOptions)
|
||||
{
|
||||
inputOptions.setConvertToNormalMap(false);
|
||||
inputOptions.setGamma(2.2f, 2.2f);
|
||||
inputOptions.setNormalizeMipmaps(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
MyAssertHandler assertHandler;
|
||||
MyMessageHandler messageHandler;
|
||||
|
||||
bool normal = false;
|
||||
bool color2normal = false;
|
||||
bool wrapRepeat = false;
|
||||
bool noMipmaps = false;
|
||||
bool fast = false;
|
||||
bool nocuda = false;
|
||||
nvtt::Format format = nvtt::Format_BC1;
|
||||
|
||||
const char * externalCompressor = NULL;
|
||||
|
||||
nv::Path input;
|
||||
nv::Path output;
|
||||
|
||||
|
||||
// Parse arguments.
|
||||
for (int i = 1; i < argc; i++)
|
||||
{
|
||||
// Input options.
|
||||
if (strcmp("-color", argv[i]) == 0)
|
||||
{
|
||||
}
|
||||
else if (strcmp("-normal", argv[i]) == 0)
|
||||
{
|
||||
normal = true;
|
||||
}
|
||||
else if (strcmp("-tonormal", argv[i]) == 0)
|
||||
{
|
||||
color2normal = true;
|
||||
}
|
||||
else if (strcmp("-clamp", argv[i]) == 0)
|
||||
{
|
||||
}
|
||||
else if (strcmp("-repeat", argv[i]) == 0)
|
||||
{
|
||||
wrapRepeat = true;
|
||||
}
|
||||
else if (strcmp("-nomips", argv[i]) == 0)
|
||||
{
|
||||
noMipmaps = true;
|
||||
}
|
||||
|
||||
// Compression options.
|
||||
else if (strcmp("-fast", argv[i]) == 0)
|
||||
{
|
||||
fast = true;
|
||||
}
|
||||
else if (strcmp("-nocuda", argv[i]) == 0)
|
||||
{
|
||||
nocuda = true;
|
||||
}
|
||||
else if (strcmp("-rgb", argv[i]) == 0)
|
||||
{
|
||||
format = nvtt::Format_RGB;
|
||||
}
|
||||
else if (strcmp("-bc1", argv[i]) == 0)
|
||||
{
|
||||
format = nvtt::Format_BC1;
|
||||
}
|
||||
else if (strcmp("-bc2", argv[i]) == 0)
|
||||
{
|
||||
format = nvtt::Format_BC2;
|
||||
}
|
||||
else if (strcmp("-bc3", argv[i]) == 0)
|
||||
{
|
||||
format = nvtt::Format_BC3;
|
||||
}
|
||||
else if (strcmp("-bc3n", argv[i]) == 0)
|
||||
{
|
||||
format = nvtt::Format_BC3n;
|
||||
}
|
||||
else if (strcmp("-bc4", argv[i]) == 0)
|
||||
{
|
||||
format = nvtt::Format_BC4;
|
||||
}
|
||||
else if (strcmp("-bc5", argv[i]) == 0)
|
||||
{
|
||||
format = nvtt::Format_BC5;
|
||||
}
|
||||
|
||||
// Undocumented option. Mainly used for testing.
|
||||
else if (strcmp("-ext", argv[i]) == 0)
|
||||
{
|
||||
if (i+1 < argc && argv[i+1][0] != '-') {
|
||||
externalCompressor = argv[i+1];
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
else if (argv[i][0] != '-')
|
||||
{
|
||||
input = argv[i];
|
||||
|
||||
if (i+1 < argc && argv[i+1][0] != '-') {
|
||||
output = argv[i+1];
|
||||
}
|
||||
else
|
||||
{
|
||||
output.copy(input.str());
|
||||
output.stripExtension();
|
||||
output.append(".dds");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (input.empty())
|
||||
{
|
||||
printf("NVIDIA Texture Tools - Copyright NVIDIA Corporation 2007\n\n");
|
||||
|
||||
printf("usage: nvcompress [options] infile [outfile]\n\n");
|
||||
|
||||
printf("Input options:\n");
|
||||
printf(" -color \tThe input image is a color map (default).\n");
|
||||
printf(" -normal \tThe input image is a normal map.\n");
|
||||
printf(" -tonormal\tConvert input to normal map.\n");
|
||||
printf(" -clamp \tClamp wrapping mode (default).\n");
|
||||
printf(" -repeat \tRepeat wrapping mode.\n");
|
||||
printf(" -nomips \tDisable mipmap generation.\n\n");
|
||||
|
||||
printf("Compression options:\n");
|
||||
printf(" -fast \tFast compression.\n");
|
||||
printf(" -nocuda \tDo not use cuda compressor.\n");
|
||||
printf(" -rgb \tRGBA format\n");
|
||||
printf(" -bc1 \tBC1 format (DXT1)\n");
|
||||
printf(" -bc2 \tBC2 format (DXT3)\n");
|
||||
printf(" -bc3 \tBC3 format (DXT5)\n");
|
||||
printf(" -bc3n \tBC3 normal map format (DXT5nm)\n");
|
||||
printf(" -bc4 \tBC4 format (ATI1)\n");
|
||||
printf(" -bc5 \tBC5 format (3Dc/ATI2)\n\n");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// @@ Make sure input file exists.
|
||||
|
||||
// Set input options.
|
||||
nvtt::InputOptions inputOptions;
|
||||
|
||||
if (nv::strCaseCmp(input.extension(), ".dds") == 0)
|
||||
{
|
||||
// Load surface.
|
||||
printf("The file '%s' is not a supported image type.\n", input.str());
|
||||
|
||||
nv::DirectDrawSurface dds(input);
|
||||
if (!dds.isValid())
|
||||
{
|
||||
printf("The file '%s' is not a valid DDS file.\n", input.str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!dds.isSupported() || dds.isTexture3D())
|
||||
{
|
||||
printf("The file '%s' is not a supported DDS file.\n", input.str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint faceCount;
|
||||
if (dds.isTexture2D())
|
||||
{
|
||||
inputOptions.setTextureLayout(nvtt::TextureType_2D, dds.width(), dds.height());
|
||||
faceCount = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
nvDebugCheck(dds.isTextureCube());
|
||||
inputOptions.setTextureLayout(nvtt::TextureType_Cube, dds.width(), dds.height());
|
||||
faceCount = 6;
|
||||
}
|
||||
|
||||
uint mipmapCount = dds.mipmapCount();
|
||||
|
||||
nv::Image mipmap;
|
||||
|
||||
for (uint f = 0; f < faceCount; f++)
|
||||
{
|
||||
for (uint m = 0; m <= mipmapCount; m++)
|
||||
{
|
||||
dds.mipmap(&mipmap, f, m);
|
||||
|
||||
inputOptions.setMipmapData(mipmap.pixels(), mipmap.width(), mipmap.height(), 1, f, m);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Regular image.
|
||||
nv::Image image;
|
||||
if (!image.load(input))
|
||||
{
|
||||
printf("The file '%s' is not a supported image type.\n", input.str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
inputOptions.setTextureLayout(nvtt::TextureType_2D, image.width(), image.height());
|
||||
inputOptions.setMipmapData(image.pixels(), image.width(), image.height());
|
||||
}
|
||||
|
||||
if (fast)
|
||||
{
|
||||
inputOptions.setMipmapping(true, nvtt::MipmapFilter_Box);
|
||||
}
|
||||
else
|
||||
{
|
||||
inputOptions.setMipmapping(true, nvtt::MipmapFilter_Kaiser);
|
||||
}
|
||||
|
||||
if (wrapRepeat)
|
||||
{
|
||||
inputOptions.setWrapMode(nvtt::WrapMode_Repeat);
|
||||
}
|
||||
else
|
||||
{
|
||||
inputOptions.setWrapMode(nvtt::WrapMode_Clamp);
|
||||
}
|
||||
|
||||
if (normal)
|
||||
{
|
||||
setNormalMap(inputOptions);
|
||||
}
|
||||
else if (color2normal)
|
||||
{
|
||||
setColorToNormalMap(inputOptions);
|
||||
}
|
||||
else
|
||||
{
|
||||
setColorMap(inputOptions);
|
||||
}
|
||||
|
||||
if (noMipmaps)
|
||||
{
|
||||
inputOptions.setMipmapping(false);
|
||||
}
|
||||
|
||||
|
||||
nvtt::CompressionOptions compressionOptions;
|
||||
compressionOptions.setFormat(format);
|
||||
if (fast)
|
||||
{
|
||||
compressionOptions.setQuality(nvtt::Quality_Fastest);
|
||||
}
|
||||
else
|
||||
{
|
||||
compressionOptions.setQuality(nvtt::Quality_Normal);
|
||||
//compressionOptions.setQuality(nvtt::Quality_Production, 0.5f);
|
||||
//compressionOptions.setQuality(nvtt::Quality_Highest);
|
||||
}
|
||||
compressionOptions.enableHardwareCompression(!nocuda);
|
||||
compressionOptions.setColorWeights(1, 1, 1);
|
||||
|
||||
if (externalCompressor != NULL)
|
||||
{
|
||||
compressionOptions.setExternalCompressor(externalCompressor);
|
||||
}
|
||||
|
||||
|
||||
MyErrorHandler errorHandler;
|
||||
MyOutputHandler outputHandler(output);
|
||||
if (outputHandler.stream->isError())
|
||||
{
|
||||
printf("Error opening '%s' for writting\n", output.str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
outputHandler.setTotal(nvtt::estimateSize(inputOptions, compressionOptions));
|
||||
|
||||
nvtt::OutputOptions outputOptions(&outputHandler, &errorHandler);
|
||||
//nvtt::OutputOptions outputOptions(NULL, &errorHandler);
|
||||
|
||||
// printf("Press ENTER.\n");
|
||||
// fflush(stdout);
|
||||
// getchar();
|
||||
|
||||
/* LARGE_INTEGER temp;
|
||||
QueryPerformanceFrequency((LARGE_INTEGER*) &temp);
|
||||
double freq = ((double) temp.QuadPart) / 1000.0;
|
||||
|
||||
LARGE_INTEGER start_time;
|
||||
QueryPerformanceCounter((LARGE_INTEGER*) &start_time);
|
||||
*/
|
||||
clock_t start = clock();
|
||||
|
||||
nvtt::compress(inputOptions, outputOptions, compressionOptions);
|
||||
/*
|
||||
LARGE_INTEGER end_time;
|
||||
QueryPerformanceCounter((LARGE_INTEGER*) &end_time);
|
||||
|
||||
float diff_time = (float) (((double) end_time.QuadPart - (double) start_time.QuadPart) / freq);
|
||||
printf("\rtime taken: %.3f seconds\n", diff_time/1000);
|
||||
*/
|
||||
clock_t end = clock();
|
||||
printf("\rtime taken: %.3f seconds\n", float(end-start) / CLOCKS_PER_SEC);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
31
src/nvimage/nvtt/tools/configdialog.cpp
Normal file
31
src/nvimage/nvtt/tools/configdialog.cpp
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#include "configdialog.h"
|
||||
|
||||
|
||||
ConfigDialog::ConfigDialog(QWidget *parent/*=0*/) : QDialog(parent)
|
||||
{
|
||||
ui.setupUi(this);
|
||||
}
|
||||
|
43
src/nvimage/nvtt/tools/configdialog.h
Normal file
43
src/nvimage/nvtt/tools/configdialog.h
Normal file
@ -0,0 +1,43 @@
|
||||
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#ifndef CONFIGDIALOG_H
|
||||
#define CONFIGDIALOG_H
|
||||
|
||||
#include <QtGui/QDialog>
|
||||
|
||||
#include "ui_nvdxtdialog.h"
|
||||
|
||||
|
||||
class ConfigDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ConfigDialog(QWidget *parent = 0);
|
||||
|
||||
private:
|
||||
Ui::ConfigDialog ui;
|
||||
};
|
||||
|
||||
|
||||
#endif // CONFIGDIALOG_H
|
983
src/nvimage/nvtt/tools/configdialog.ui
Normal file
983
src/nvimage/nvtt/tools/configdialog.ui
Normal file
@ -0,0 +1,983 @@
|
||||
<ui version="4.0" >
|
||||
<class>ConfigDialog</class>
|
||||
<widget class="QDialog" name="ConfigDialog" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>626</width>
|
||||
<height>532</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<property name="sizeGripEnabled" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QListWidget" name="listWidget" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy>
|
||||
<hsizetype>7</hsizetype>
|
||||
<vsizetype>7</vsizetype>
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize" >
|
||||
<size>
|
||||
<width>64</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize" >
|
||||
<size>
|
||||
<width>128</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy" >
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="movement" >
|
||||
<enum>QListView::Static</enum>
|
||||
</property>
|
||||
<property name="flow" >
|
||||
<enum>QListView::TopToBottom</enum>
|
||||
</property>
|
||||
<property name="isWrapping" stdset="0" >
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="resizeMode" >
|
||||
<enum>QListView::Adjust</enum>
|
||||
</property>
|
||||
<property name="viewMode" >
|
||||
<enum>QListView::IconMode</enum>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>Input</string>
|
||||
</property>
|
||||
<property name="icon" >
|
||||
<iconset>../../../../../../castano-stuff/qshaderedit/src/images/win/fileopen.png</iconset>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>Output</string>
|
||||
</property>
|
||||
<property name="icon" >
|
||||
<iconset>../../../../../../castano-stuff/qshaderedit/src/images/win/filesave.png</iconset>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>Settings</string>
|
||||
</property>
|
||||
<property name="icon" >
|
||||
<iconset>../../../../../../castano-stuff/qshaderedit/src/images/toolbutton.png</iconset>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>Preview</string>
|
||||
</property>
|
||||
<property name="icon" >
|
||||
<iconset>../../../../../../castano-stuff/qshaderedit/src/images/colorpicker.png</iconset>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>3D Preview</string>
|
||||
</property>
|
||||
<property name="icon" >
|
||||
<iconset>../../../../../../castano-stuff/qshaderedit/src/images/colorpicker.png</iconset>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabWidget" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy>
|
||||
<hsizetype>7</hsizetype>
|
||||
<vsizetype>7</vsizetype>
|
||||
<horstretch>5</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize" >
|
||||
<size>
|
||||
<width>400</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="tabPosition" >
|
||||
<enum>QTabWidget::North</enum>
|
||||
</property>
|
||||
<property name="tabShape" >
|
||||
<enum>QTabWidget::Rounded</enum>
|
||||
</property>
|
||||
<property name="currentIndex" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab_5" >
|
||||
<attribute name="title" >
|
||||
<string>Input</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="lineEdit" />
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="openButton" >
|
||||
<property name="text" >
|
||||
<string>Open</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy>
|
||||
<hsizetype>0</hsizetype>
|
||||
<vsizetype>0</vsizetype>
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize" >
|
||||
<size>
|
||||
<width>172</width>
|
||||
<height>172</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="baseSize" >
|
||||
<size>
|
||||
<width>172</width>
|
||||
<height>172</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="acceptDrops" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="toolTip" >
|
||||
<string>Drop images here</string>
|
||||
</property>
|
||||
<property name="frameShape" >
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap" >
|
||||
<pixmap>../../../../../../castano-stuff/qshaderedit/src/images/default.png</pixmap>
|
||||
</property>
|
||||
<property name="scaledContents" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="margin" >
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTextEdit" name="textEdit" >
|
||||
<property name="enabled" >
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy>
|
||||
<hsizetype>0</hsizetype>
|
||||
<vsizetype>7</vsizetype>
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize" >
|
||||
<size>
|
||||
<width>172</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="frameShape" >
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>4</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_4" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy>
|
||||
<hsizetype>5</hsizetype>
|
||||
<vsizetype>5</vsizetype>
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title" >
|
||||
<string>Type</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButton" >
|
||||
<property name="text" >
|
||||
<string>RGB</string>
|
||||
</property>
|
||||
<property name="checked" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButton_2" >
|
||||
<property name="text" >
|
||||
<string>RGBA</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButton_3" >
|
||||
<property name="text" >
|
||||
<string>Monochrome</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButton_4" >
|
||||
<property name="text" >
|
||||
<string>Normal Map</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBox_5" >
|
||||
<property name="enabled" >
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Alpha is opacity</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBox_2" >
|
||||
<property name="enabled" >
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Convert to normal map</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBox" >
|
||||
<property name="text" >
|
||||
<string>Generate mipmaps</string>
|
||||
</property>
|
||||
<property name="checked" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_8" >
|
||||
<property name="text" >
|
||||
<string>Mipmap filter</string>
|
||||
</property>
|
||||
<property name="buddy" >
|
||||
<cstring>comboBox</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBox" >
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>Box</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>Triangle</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>Mitchell</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>Kaiser</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy>
|
||||
<hsizetype>1</hsizetype>
|
||||
<vsizetype>5</vsizetype>
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Gamma</string>
|
||||
</property>
|
||||
<property name="buddy" >
|
||||
<cstring>gammaSpinBox</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="gammaSpinBox" >
|
||||
<property name="buttonSymbols" >
|
||||
<enum>QAbstractSpinBox::UpDownArrows</enum>
|
||||
</property>
|
||||
<property name="maximum" >
|
||||
<double>4.000000000000000</double>
|
||||
</property>
|
||||
<property name="minimum" >
|
||||
<double>0.050000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep" >
|
||||
<double>0.050000000000000</double>
|
||||
</property>
|
||||
<property name="value" >
|
||||
<double>2.200000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>204</width>
|
||||
<height>71</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_3" >
|
||||
<attribute name="title" >
|
||||
<string>Output</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3" >
|
||||
<property name="text" >
|
||||
<string>Format:</string>
|
||||
</property>
|
||||
<property name="textFormat" >
|
||||
<enum>Qt::PlainText</enum>
|
||||
</property>
|
||||
<property name="textInteractionFlags" >
|
||||
<enum>Qt::NoTextInteraction</enum>
|
||||
</property>
|
||||
<property name="buddy" >
|
||||
<cstring>formatComboBox</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="formatComboBox" >
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>BC1 (DXT1)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>BC2 (DXT3)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>BC3 (DXT5)</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_9" >
|
||||
<property name="text" >
|
||||
<string>Color Space:</string>
|
||||
</property>
|
||||
<property name="buddy" >
|
||||
<cstring>comboBox_2</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBox_2" >
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>RGB</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>YCoCg</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>JPEG LS (R-G, G, B-G)</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_5" >
|
||||
<property name="text" >
|
||||
<string>Export</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_4" >
|
||||
<attribute name="title" >
|
||||
<string>Settings</string>
|
||||
</attribute>
|
||||
<widget class="QWidget" name="verticalLayout_3" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>10</y>
|
||||
<width>202</width>
|
||||
<height>242</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_3" >
|
||||
<property name="title" >
|
||||
<string>Quality</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QSlider" name="horizontalSlider" >
|
||||
<property name="maximum" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="value" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2" >
|
||||
<property name="frameShape" >
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow" >
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>9 - Best</string>
|
||||
</property>
|
||||
<property name="textFormat" >
|
||||
<enum>Qt::PlainText</enum>
|
||||
</property>
|
||||
<property name="textInteractionFlags" >
|
||||
<enum>Qt::NoTextInteraction</enum>
|
||||
</property>
|
||||
<property name="buddy" >
|
||||
<cstring>horizontalSlider</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label" >
|
||||
<property name="text" >
|
||||
<string>Threshold</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="doubleSpinBox" />
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_6" >
|
||||
<property name="title" >
|
||||
<string>Color Weights</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_10" >
|
||||
<property name="text" >
|
||||
<string>Red</string>
|
||||
</property>
|
||||
<property name="buddy" >
|
||||
<cstring>doubleSpinBox_2</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="doubleSpinBox_2" />
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_11" >
|
||||
<property name="text" >
|
||||
<string>Green</string>
|
||||
</property>
|
||||
<property name="buddy" >
|
||||
<cstring>doubleSpinBox_3</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="doubleSpinBox_3" />
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_12" >
|
||||
<property name="text" >
|
||||
<string>Blue</string>
|
||||
</property>
|
||||
<property name="buddy" >
|
||||
<cstring>doubleSpinBox_4</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="doubleSpinBox_4" />
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab" >
|
||||
<attribute name="title" >
|
||||
<string>Preview</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox" >
|
||||
<property name="title" >
|
||||
<string>Input</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2" >
|
||||
<property name="title" >
|
||||
<string>Output</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="filterCheckBox" >
|
||||
<property name="text" >
|
||||
<string>Bilinear Filter</string>
|
||||
</property>
|
||||
<property name="checked" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="diffCheckBox" >
|
||||
<property name="text" >
|
||||
<string>View difference</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_2" >
|
||||
<attribute name="title" >
|
||||
<string>3D Preview</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBox_3" >
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>Quad</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>Sphere</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>Cylinder</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>Teapot</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame" >
|
||||
<property name="frameShape" >
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow" >
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_6" >
|
||||
<property name="text" >
|
||||
<string>Default</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QProgressBar" name="progressBar" >
|
||||
<property name="value" >
|
||||
<number>24</number>
|
||||
</property>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton" >
|
||||
<property name="text" >
|
||||
<string>Quit</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>listWidget</sender>
|
||||
<signal>currentRowChanged(int)</signal>
|
||||
<receiver>tabWidget</receiver>
|
||||
<slot>setCurrentPage(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel" >
|
||||
<x>114</x>
|
||||
<y>67</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel" >
|
||||
<x>173</x>
|
||||
<y>95</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
Reference in New Issue
Block a user