Imperative api is sort of working now. Fixed various bugs.

pull/216/head
castano 14 years ago
parent adbb0c3338
commit da503d2b3e

@ -2,6 +2,8 @@
#error "Do not include this file directly." #error "Do not include this file directly."
#endif #endif
#include <cstddef> // size_t, NULL
// Function linkage // Function linkage
#define DLL_IMPORT __declspec(dllimport) #define DLL_IMPORT __declspec(dllimport)
#define DLL_EXPORT __declspec(dllexport) #define DLL_EXPORT __declspec(dllexport)

@ -542,7 +542,7 @@ const char * Path::extension(const char * str)
l = length = (int)strlen( str ); l = length = (int)strlen( str );
while (length > 0 && str[length] != '.') { while (length > 0 && str[length] != '.') {
length--; length--;
if (str[length] != '\\' || str[length] != '/') { if (str[length] == '\\' || str[length] == '/') {
return &str[l]; // no extension return &str[l]; // no extension
} }
} }

@ -154,9 +154,6 @@
/// Null index. @@ Move this somewhere else... This could have collisions with other definitions! /// Null index. @@ Move this somewhere else... This could have collisions with other definitions!
#define NIL uint(~0) #define NIL uint(~0)
// @@ Move this to DefsGnuc?
#include <cstddef> // size_t, NULL
/// Null pointer. /// Null pointer.
#ifndef NULL #ifndef NULL
#define NULL 0 #define NULL 0

@ -56,34 +56,10 @@ ColorBlock::ColorBlock(const Image * img, uint x, uint y)
void ColorBlock::init(const Image * img, uint x, uint y) void ColorBlock::init(const Image * img, uint x, uint y)
{ {
nvDebugCheck(img != NULL); init(img->width(), img->height(), (const uint *)img->pixels(), x, y);
const uint bw = min(img->width() - x, 4U);
const uint bh = min(img->height() - y, 4U);
nvDebugCheck(bw != 0 && bh != 0);
static const int remainder[] = {
0, 0, 0, 0,
0, 1, 0, 1,
0, 1, 2, 0,
0, 1, 2, 3,
};
// 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. :(
for(uint i = 0; i < 4; i++) {
//const int by = i % bh;
const int by = remainder[(bh - 1) * 4 + i];
for(uint e = 0; e < 4; e++) {
//const int bx = e % bw;
const int bx = remainder[(bw - 1) * 4 + e];
color(e, i) = img->pixel(x + bx, y + by);
}
}
} }
void ColorBlock::init(uint w, uint h, uint * data, uint x, uint y) void ColorBlock::init(uint w, uint h, const uint * data, uint x, uint y)
{ {
nvDebugCheck(data != NULL); nvDebugCheck(data != NULL);
@ -93,6 +69,7 @@ void ColorBlock::init(uint w, uint h, uint * data, uint x, uint y)
// Blocks that are smaller than 4x4 are handled by repeating the pixels. // 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. :(
// @@ Ideally we should zero the weights of the pixels out of range.
for (uint i = 0; i < 4; i++) for (uint i = 0; i < 4; i++)
{ {
@ -108,7 +85,7 @@ void ColorBlock::init(uint w, uint h, uint * data, uint x, uint y)
} }
} }
void ColorBlock::init(uint w, uint h, float * data, uint x, uint y) void ColorBlock::init(uint w, uint h, const float * data, uint x, uint y)
{ {
nvDebugCheck(data != NULL); nvDebugCheck(data != NULL);
@ -118,6 +95,9 @@ void ColorBlock::init(uint w, uint h, float * data, uint x, uint y)
// Blocks that are smaller than 4x4 are handled by repeating the pixels. // 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. :(
// @@ Ideally we should zero the weights of the pixels out of range.
uint srcPlane = w * h;
for (uint i = 0; i < 4; i++) for (uint i = 0; i < 4; i++)
{ {
@ -126,13 +106,13 @@ void ColorBlock::init(uint w, uint h, float * data, uint x, uint y)
for (uint e = 0; e < 4; e++) for (uint e = 0; e < 4; e++)
{ {
const uint bx = e % bw; const uint bx = e % bw;
const uint idx = ((y + by) * w + x + bx) * 4; const uint idx = ((y + by) * w + x + bx);
Color32 & c = color(e, i); Color32 & c = color(e, i);
c.r = uint8(255 * clamp(data[idx + 0], 0.0f, 1.0f)); c.r = uint8(255 * clamp(data[idx + 0 * srcPlane], 0.0f, 1.0f)); // @@ Is this the right way to quantize floats to bytes?
c.g = uint8(255 * clamp(data[idx + 1], 0.0f, 1.0f)); c.g = uint8(255 * clamp(data[idx + 1 * srcPlane], 0.0f, 1.0f));
c.b = uint8(255 * clamp(data[idx + 2], 0.0f, 1.0f)); c.b = uint8(255 * clamp(data[idx + 2 * srcPlane], 0.0f, 1.0f));
c.a = uint8(255 * clamp(data[idx + 3], 0.0f, 1.0f)); c.a = uint8(255 * clamp(data[idx + 3 * srcPlane], 0.0f, 1.0f));
} }
} }
} }

@ -19,8 +19,8 @@ namespace nv
ColorBlock(const Image * img, uint x, uint y); ColorBlock(const Image * img, uint x, uint y);
void init(const Image * img, uint x, uint y); void init(const Image * img, uint x, uint y);
void init(uint w, uint h, uint * data, uint x, uint y); void init(uint w, uint h, const uint * data, uint x, uint y);
void init(uint w, uint h, float * data, uint x, uint y); void init(uint w, uint h, const float * data, uint x, uint y);
void swizzle(uint x, uint y, uint z, uint w); // 0=r, 1=g, 2=b, 3=a, 4=0xFF, 5=0 void swizzle(uint x, uint y, uint z, uint w); // 0=r, 1=g, 2=b, 3=a, 4=0xFF, 5=0

@ -206,10 +206,16 @@ void FloatImage::scaleBias(uint base_component, uint num, float scale, float bia
} }
/// Clamp the elements of the image. /// Clamp the elements of the image.
void FloatImage::clamp(float low, float high) void FloatImage::clamp(uint base_component, uint num, float low, float high)
{ {
for(uint i = 0; i < m_count; i++) { const uint size = m_width * m_height;
m_mem[i] = nv::clamp(m_mem[i], low, high);
for(uint c = 0; c < num; c++) {
float * ptr = this->channel(base_component + c);
for(uint i = 0; i < size; i++) {
ptr[i] = nv::clamp(ptr[i], low, high);
}
} }
} }
@ -697,23 +703,24 @@ FloatImage * FloatImage::resize(const Filter & filter, uint w, uint h, WrapMode
Array<float> tmp_column(h); Array<float> tmp_column(h);
tmp_column.resize(h); tmp_column.resize(h);
for (uint c = 0; c < m_componentNum; c++) for (uint i = 0; i < m_componentNum; i++)
{ {
// Process alpha channel first.
uint c;
if (i == 0) c = alpha;
else if (i > alpha) c = i;
else c = i - 1;
float * tmp_channel = tmp_image->channel(c); float * tmp_channel = tmp_image->channel(c);
for (uint y = 0; y < m_height; y++) { for (uint y = 0; y < m_height; y++) {
this->applyKernelHorizontal(xkernel, y, c, alpha, wm, tmp_channel + y * w); this->applyKernelHorizontal(xkernel, y, c, wm, tmp_channel + y * w);
} }
}
// Process all channels before applying vertical kernel to make sure alpha has been computed.
for (uint c = 0; c < m_componentNum; c++)
{
float * dst_channel = dst_image->channel(c); float * dst_channel = dst_image->channel(c);
for (uint x = 0; x < w; x++) { for (uint x = 0; x < w; x++) {
tmp_image->applyKernelVertical(ykernel, x, c, alpha, wm, tmp_column.mutableBuffer()); tmp_image->applyKernelVertical(ykernel, x, c, wm, tmp_column.mutableBuffer());
for (uint y = 0; y < h; y++) { for (uint y = 0; y < h; y++) {
dst_channel[y * w + x] = tmp_column[y]; dst_channel[y * w + x] = tmp_column[y];
@ -938,69 +945,72 @@ void FloatImage::applyKernelHorizontal(const PolyphaseKernel & k, int y, uint c,
} }
} }
// Vertical flip in place. // Vertical flip in place.
void FloatImage::flip() void FloatImage::flip()
{ {
const uint w = m_width; const uint w = m_width;
const uint h = m_height; const uint h = m_height;
const uint h2 = h / 2; const uint h2 = h / 2;
for (uint c = 0; c < m_componentNum; c++) { for (uint c = 0; c < m_componentNum; c++) {
for (uint y = 0; y < h2; y++) { for (uint y = 0; y < h2; y++) {
float * src = scanline(y, c); float * src = scanline(y, c);
float * dst = scanline(h - 1 - y, c); float * dst = scanline(h - 1 - y, c);
for (uint x = 0; x < w; x++) { for (uint x = 0; x < w; x++) {
swap(src[x], dst[x]); swap(src[x], dst[x]);
} }
} }
} }
} }
float FloatImage::alphaTestCoverage(float alphaRef, int alphaChannel) const float FloatImage::alphaTestCoverage(float alphaRef, int alphaChannel) const
{ {
const uint w = m_width; const uint w = m_width;
const uint h = m_height; const uint h = m_height;
float coverage = 0.0f; float coverage = 0.0f;
for (uint y = 0; y < h; y++) { for (uint y = 0; y < h; y++) {
const float * alpha = scanline(y, alphaChannel); const float * alpha = scanline(y, alphaChannel);
for (uint x = 0; x < w; x++) { for (uint x = 0; x < w; x++) {
if (alpha[x] > alphaRef) coverage += 1.0f; // @@ gt or lt? if (alpha[x] > alphaRef) coverage += 1.0f; // @@ gt or lt?
} }
} }
return coverage / float(w * h); return coverage / float(w * h);
} }
void FloatImage::scaleAlphaToCoverage(float desiredCoverage, float alphaRef, int alphaChannel) void FloatImage::scaleAlphaToCoverage(float desiredCoverage, float alphaRef, int alphaChannel)
{ {
float minAlphaRef = 0.0f; float minAlphaRef = 0.0f;
float maxAlphaRef = 1.0f; float maxAlphaRef = 1.0f;
float midAlphaRef = 0.5f; float midAlphaRef = 0.5f;
// Determine desired scale using a binary search. Hardcoded to 8 steps max. // Determine desired scale using a binary search. Hardcoded to 8 steps max.
for (int i = 0; i < 8; i++) { for (int i = 0; i < 10; i++) {
float currentCoverage = alphaTestCoverage(midAlphaRef, alphaChannel); float currentCoverage = alphaTestCoverage(midAlphaRef, alphaChannel);
if (currentCoverage > desiredCoverage) { if (currentCoverage > desiredCoverage) {
maxAlphaRef = midAlphaRef; minAlphaRef = midAlphaRef;
} }
else if (currentCoverage < desiredCoverage) { else if (currentCoverage < desiredCoverage) {
minAlphaRef = midAlphaRef; maxAlphaRef = midAlphaRef;
} }
else { else {
break; break;
} }
midAlphaRef = (minAlphaRef + maxAlphaRef) * 0.5f; midAlphaRef = (minAlphaRef + maxAlphaRef) * 0.5f;
} }
float alphaScale = alphaRef / midAlphaRef; float alphaScale = alphaRef / midAlphaRef;
// Scale alpha channel. // Scale alpha channel.
scaleBias(alphaChannel, 1, alphaScale, 0.0f); scaleBias(alphaChannel, 1, alphaScale, 0.0f);
clamp(alphaChannel, 1, 0.0f, 1.0f);
//float newCoverage = alphaTestCoverage(alphaRef, alphaChannel);
} }
FloatImage* FloatImage::clone() const FloatImage* FloatImage::clone() const

@ -60,8 +60,7 @@ namespace nv
NVIMAGE_API void expandNormals(uint base_component); NVIMAGE_API void expandNormals(uint base_component);
NVIMAGE_API void scaleBias(uint base_component, uint num, float scale, float add); NVIMAGE_API void scaleBias(uint base_component, uint num, float scale, float add);
//NVIMAGE_API void clamp(uint base_component, uint num); NVIMAGE_API void clamp(uint base_component, uint num, float low, float high);
NVIMAGE_API void clamp(float low, float high);
NVIMAGE_API void toLinear(uint base_component, uint num, float gamma = 2.2f); NVIMAGE_API void toLinear(uint base_component, uint num, float gamma = 2.2f);
NVIMAGE_API void toGamma(uint base_component, uint num, float gamma = 2.2f); NVIMAGE_API void toGamma(uint base_component, uint num, float gamma = 2.2f);

@ -203,10 +203,15 @@ FloatImage * nv::ImageIO::loadFloat(const char * fileName, Stream & s)
const char * extension = Path::extension(fileName); const char * extension = Path::extension(fileName);
FloatImage * floatImage = NULL;
const uint spos = s.tell(); // Save stream position.
// Try to load as a floating point image.
#if defined(HAVE_FREEIMAGE) #if defined(HAVE_FREEIMAGE)
FREE_IMAGE_FORMAT fif = FreeImage_GetFIFFromFilename(fileName); FREE_IMAGE_FORMAT fif = FreeImage_GetFIFFromFilename(fileName);
if (fif != FIF_UNKNOWN && FreeImage_FIFSupportsReading(fif)) { if (fif != FIF_UNKNOWN && FreeImage_FIFSupportsReading(fif)) {
return loadFloatFreeImage(fif, s); floatImage = loadFloatFreeImage(fif, s);
} }
#else // defined(HAVE_FREEIMAGE) #else // defined(HAVE_FREEIMAGE)
#pragma message(NV_FILE_LINE "TODO: Load TIFF and EXR files from stream.") #pragma message(NV_FILE_LINE "TODO: Load TIFF and EXR files from stream.")
@ -222,7 +227,17 @@ FloatImage * nv::ImageIO::loadFloat(const char * fileName, Stream & s)
#endif #endif
#endif // defined(HAVE_FREEIMAGE) #endif // defined(HAVE_FREEIMAGE)
return NULL; // Try to load as an RGBA8 image and convert to float.
if (floatImage == NULL) {
s.seek(spos); // Restore stream position.
AutoPtr<Image> img = load(fileName, s);
if (img != NULL) {
floatImage = new FloatImage(img.ptr());
}
}
return floatImage;
} }
bool nv::ImageIO::saveFloat(const char * fileName, Stream & s, const FloatImage * fimage, uint baseComponent, uint componentCount) bool nv::ImageIO::saveFloat(const char * fileName, Stream & s, const FloatImage * fimage, uint baseComponent, uint componentCount)
@ -357,16 +372,7 @@ Image * nv::ImageIO::loadFreeImage(FREE_IMAGE_FORMAT fif, Stream & s)
const int w = FreeImage_GetWidth(bitmap); const int w = FreeImage_GetWidth(bitmap);
const int h = FreeImage_GetHeight(bitmap); const int h = FreeImage_GetHeight(bitmap);
if (FreeImage_GetImageType(bitmap) == FIT_BITMAP) if (FreeImage_GetImageType(bitmap) != FIT_BITMAP)
{
if (FreeImage_GetBPP(bitmap) != 32)
{
FIBITMAP * tmp = FreeImage_ConvertTo32Bits(bitmap);
FreeImage_Unload(bitmap);
bitmap = tmp;
}
}
else
{ {
// @@ Use tone mapping? // @@ Use tone mapping?
FIBITMAP * tmp = FreeImage_ConvertToType(bitmap, FIT_BITMAP, true); FIBITMAP * tmp = FreeImage_ConvertToType(bitmap, FIT_BITMAP, true);
@ -374,6 +380,14 @@ Image * nv::ImageIO::loadFreeImage(FREE_IMAGE_FORMAT fif, Stream & s)
bitmap = tmp; bitmap = tmp;
} }
nvDebugCheck(FreeImage_GetImageType(bitmap) == FIT_BITMAP);
if (FreeImage_GetBPP(bitmap) != 32)
{
FIBITMAP * tmp = FreeImage_ConvertTo32Bits(bitmap);
FreeImage_Unload(bitmap);
bitmap = tmp;
}
Image * image = new Image(); Image * image = new Image();
image->allocate(w, h); image->allocate(w, h);

@ -107,11 +107,11 @@ void FixedBlockCompressor::compress(nvtt::InputFormat inputFormat, nvtt::AlphaMo
ColorBlock rgba; ColorBlock rgba;
if (inputFormat == nvtt::InputFormat_BGRA_8UB) { if (inputFormat == nvtt::InputFormat_BGRA_8UB) {
rgba.init(w, h, (uint *)data, x, y); rgba.init(w, h, (const uint *)data, x, y);
} }
else { else {
nvDebugCheck(inputFormat == nvtt::InputFormat_RGBA_32F); nvDebugCheck(inputFormat == nvtt::InputFormat_RGBA_32F);
rgba.init(w, h, (float *)data, x, y); rgba.init(w, h, (const float *)data, x, y);
} }
compressBlock(rgba, alphaMode, compressionOptions, mem); compressBlock(rgba, alphaMode, compressionOptions, mem);

@ -25,12 +25,12 @@
#include "CompressionOptions.h" #include "CompressionOptions.h"
#include "OutputOptions.h" #include "OutputOptions.h"
#include <nvimage/Image.h> #include "nvimage/Image.h"
#include <nvimage/FloatImage.h> #include "nvimage/FloatImage.h"
#include <nvmath/Color.h> #include "nvmath/Color.h"
#include <nvcore/Debug.h> #include "nvcore/Debug.h"
using namespace nv; using namespace nv;
using namespace nvtt; using namespace nvtt;
@ -63,7 +63,7 @@ void CompressorRGBE::compress(nvtt::InputFormat inputFormat, nvtt::AlphaMode alp
uint srcPlane = w * h; uint srcPlane = w * h;
// Allocate output scanline. // Allocate output scanline.
Color32 * dst = (Color32 *)mem::malloc(w); Color32 * dst = new Color32[w];
for (uint y = 0; y < h; y++) for (uint y = 0; y < h; y++)
{ {
@ -83,8 +83,6 @@ void CompressorRGBE::compress(nvtt::InputFormat inputFormat, nvtt::AlphaMode alp
else { else {
nvDebugCheck (inputFormat == nvtt::InputFormat_RGBA_32F); nvDebugCheck (inputFormat == nvtt::InputFormat_RGBA_32F);
#pragma message(NV_FILE_LINE "TODO: Interleave color components")
// Color components not interleaved. // Color components not interleaved.
r = fsrc[x + 0 * srcPlane]; r = fsrc[x + 0 * srcPlane];
g = fsrc[x + 1 * srcPlane]; g = fsrc[x + 1 * srcPlane];
@ -100,5 +98,5 @@ void CompressorRGBE::compress(nvtt::InputFormat inputFormat, nvtt::AlphaMode alp
} }
} }
mem::free(dst); delete [] dst;
} }

@ -337,8 +337,6 @@ bool Compressor::outputHeader(const TexImage & tex, int mipmapCount, const Compr
bool Compressor::compress(const TexImage & tex, const CompressionOptions & compressionOptions, const OutputOptions & outputOptions) const bool Compressor::compress(const TexImage & tex, const CompressionOptions & compressionOptions, const OutputOptions & outputOptions) const
{ {
// @@ Decide whether to change the swizzling of FloatImage.
foreach(i, tex.m->imageArray) { foreach(i, tex.m->imageArray) {
FloatImage * image = tex.m->imageArray[i]; FloatImage * image = tex.m->imageArray[i];
if (!m.compress2D(InputFormat_RGBA_32F, tex.m->alphaMode, image->width(), image->height(), image->channel(0), compressionOptions.m, outputOptions.m)) { if (!m.compress2D(InputFormat_RGBA_32F, tex.m->alphaMode, image->width(), image->height(), image->channel(0), compressionOptions.m, outputOptions.m)) {
@ -1493,7 +1491,7 @@ CompressorInterface * Compressor::Private::chooseGpuCompressor(const Compression
bool Compressor::Private::compress2D(InputFormat inputFormat, AlphaMode alphaMode, int w, int h, const void * data, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const bool Compressor::Private::compress2D(InputFormat inputFormat, AlphaMode alphaMode, int w, int h, const void * data, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const
{ {
// Decide what compressor to use. // Decide what compressor to use.
CompressorInterface * compressor = NULL; AutoPtr<CompressorInterface> compressor;
#if defined HAVE_CUDA #if defined HAVE_CUDA
if (cudaEnabled && w * h >= 512) if (cudaEnabled && w * h >= 512)
{ {
@ -1512,8 +1510,6 @@ bool Compressor::Private::compress2D(InputFormat inputFormat, AlphaMode alphaMod
else else
{ {
compressor->compress(inputFormat, alphaMode, w, h, data, compressionOptions, outputOptions); compressor->compress(inputFormat, alphaMode, w, h, data, compressionOptions, outputOptions);
delete compressor;
} }
return true; return true;

@ -23,15 +23,15 @@
#include "TexImage.h" #include "TexImage.h"
#include <nvmath/Vector.h> #include "nvmath/Vector.h"
#include <nvmath/Matrix.h> #include "nvmath/Matrix.h"
#include <nvmath/Color.h> #include "nvmath/Color.h"
#include <nvimage/Filter.h> #include "nvimage/Filter.h"
#include <nvimage/ImageIO.h> #include "nvimage/ImageIO.h"
#include <nvimage/NormalMap.h> #include "nvimage/NormalMap.h"
#include <nvimage/BlockDXT.h> #include "nvimage/BlockDXT.h"
#include <nvimage/ColorBlock.h> #include "nvimage/ColorBlock.h"
#include <float.h> #include <float.h>
@ -128,6 +128,7 @@ void TexImage::detach()
{ {
if (m->refCount() > 1) if (m->refCount() > 1)
{ {
m->release();
m = new TexImage::Private(*m); m = new TexImage::Private(*m);
m->addRef(); m->addRef();
nvDebugCheck(m->refCount() == 1); nvDebugCheck(m->refCount() == 1);
@ -281,6 +282,8 @@ bool TexImage::load(const char * fileName)
detach(); detach();
#pragma message(NV_FILE_LINE "TODO: Make sure that floating point image has 4 channels.")
m->imageArray.resize(1); m->imageArray.resize(1);
m->imageArray[0] = img.release(); m->imageArray[0] = img.release();
@ -674,19 +677,21 @@ bool TexImage::buildNextMipmap(MipmapFilter filter)
foreach (i, m->imageArray) foreach (i, m->imageArray)
{ {
if (m->imageArray[i] == NULL) continue; FloatImage * img = m->imageArray[i];
if (img == NULL) continue;
if (m->alphaMode == AlphaMode_Transparency) if (m->alphaMode == AlphaMode_Transparency)
{ {
if (filter == MipmapFilter_Box) if (filter == MipmapFilter_Box)
{ {
BoxFilter filter; BoxFilter filter;
m->imageArray[i]->downSample(filter, wrapMode, 3); img = img->downSample(filter, wrapMode, 3);
} }
else if (filter == MipmapFilter_Triangle) else if (filter == MipmapFilter_Triangle)
{ {
TriangleFilter filter; TriangleFilter filter;
m->imageArray[i]->downSample(filter, wrapMode, 3); img = img->downSample(filter, wrapMode, 3);
} }
else if (filter == MipmapFilter_Kaiser) else if (filter == MipmapFilter_Kaiser)
{ {
@ -694,19 +699,19 @@ bool TexImage::buildNextMipmap(MipmapFilter filter)
//KaiserFilter filter(inputOptions.kaiserWidth); //KaiserFilter filter(inputOptions.kaiserWidth);
//filter.setParameters(inputOptions.kaiserAlpha, inputOptions.kaiserStretch); //filter.setParameters(inputOptions.kaiserAlpha, inputOptions.kaiserStretch);
KaiserFilter filter(3); KaiserFilter filter(3);
m->imageArray[i]->downSample(filter, wrapMode, 3); img = img->downSample(filter, wrapMode, 3);
} }
} }
else else
{ {
if (filter == MipmapFilter_Box) if (filter == MipmapFilter_Box)
{ {
m->imageArray[i]->fastDownSample(); img = img->fastDownSample();
} }
else if (filter == MipmapFilter_Triangle) else if (filter == MipmapFilter_Triangle)
{ {
TriangleFilter filter; TriangleFilter filter;
m->imageArray[i]->downSample(filter, wrapMode); img = img->downSample(filter, wrapMode);
} }
else //if (filter == MipmapFilter_Kaiser) else //if (filter == MipmapFilter_Kaiser)
{ {
@ -714,9 +719,12 @@ bool TexImage::buildNextMipmap(MipmapFilter filter)
//KaiserFilter filter(inputOptions.kaiserWidth); //KaiserFilter filter(inputOptions.kaiserWidth);
//filter.setParameters(inputOptions.kaiserAlpha, inputOptions.kaiserStretch); //filter.setParameters(inputOptions.kaiserAlpha, inputOptions.kaiserStretch);
KaiserFilter filter(3); KaiserFilter filter(3);
m->imageArray[i]->downSample(filter, wrapMode); img = img->downSample(filter, wrapMode);
} }
} }
delete m->imageArray[i];
m->imageArray[i] = img;
} }
return true; return true;

@ -56,7 +56,10 @@ namespace nvtt
alphaMode = p.alphaMode; alphaMode = p.alphaMode;
isNormalMap = p.isNormalMap; isNormalMap = p.isNormalMap;
imageArray = p.imageArray; imageArray.reserve(p.imageArray.count());
foreach(i, p.imageArray) {
imageArray.append(p.imageArray[i]->clone());
}
} }
~Private() ~Private()
{ {

@ -48,7 +48,7 @@
# define NVTT_API # define NVTT_API
#endif #endif
#define NVTT_VERSION 201 #define NVTT_VERSION 020100
#define NVTT_FORBID_COPY(Class) \ #define NVTT_FORBID_COPY(Class) \
private: \ private: \

@ -47,7 +47,7 @@
# define NVTT_API # define NVTT_API
#endif #endif
#define NVTT_VERSION 201 #define NVTT_VERSION 020100
#ifdef __cplusplus #ifdef __cplusplus
typedef struct nvtt::InputOptions NvttInputOptions; typedef struct nvtt::InputOptions NvttInputOptions;

@ -21,6 +21,7 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE. // OTHER DEALINGS IN THE SOFTWARE.
#include <nvcore/StrLib.h>
#include <nvtt/nvtt.h> #include <nvtt/nvtt.h>
#include <stdlib.h> // EXIT_SUCCESS, EXIT_FAILURE #include <stdlib.h> // EXIT_SUCCESS, EXIT_FAILURE
@ -30,30 +31,54 @@ int main(int argc, char *argv[])
{ {
if (argc != 2) return EXIT_FAILURE; if (argc != 2) return EXIT_FAILURE;
const char * inputFileName = argv[1];
// Init context.
nvtt::Context context;
context.enableCudaAcceleration(false);
// Load input image.
nvtt::TexImage image = context.createTexImage();
if (!image.load(inputFileName)) {
return EXIT_FAILURE;
}
// Setup compression options.
nvtt::CompressionOptions compressionOptions; nvtt::CompressionOptions compressionOptions;
compressionOptions.setFormat(nvtt::Format_BC1); compressionOptions.setFormat(nvtt::Format_BC3);
//compressionOptions.setFormat(nvtt::Format_RGBA);
// Setup output options.
nvtt::OutputOptions outputOptions; nvtt::OutputOptions outputOptions;
outputOptions.setFileName("output.dds");
nvtt::Context context; nv::Path outputFileName(inputFileName);
nvtt::TexImage image = context.createTexImage(); outputFileName.stripExtension();
outputFileName.append(".dds");
outputOptions.setFileName(outputFileName);
// Output compressed image.
context.outputHeader(image, image.countMipmaps(), compressionOptions, outputOptions);
image.load(argv[1]); image.flipVertically();
image.setAlphaMode(nvtt::AlphaMode_Transparency);
context.outputHeader(image, image.countMipmaps(), compressionOptions, outputOptions); // Output first mipmap.
context.compress(image, compressionOptions, outputOptions);
float gamma = 2.2f; float gamma = 2.2f;
image.toLinear(gamma); image.toLinear(gamma);
float coverage = image.alphaTestCoverage(); float alphaRef = 0.95;
float coverage = image.alphaTestCoverage(alphaRef);
while (image.buildNextMipmap(nvtt::MipmapFilter_Box)) // Build mimaps.
while (image.buildNextMipmap(nvtt::MipmapFilter_Kaiser))
{ {
nvtt::TexImage tmpImage = image; nvtt::TexImage tmpImage = image;
tmpImage.toGamma(gamma); tmpImage.toGamma(gamma);
tmpImage.scaleAlphaToCoverage(coverage); tmpImage.scaleAlphaToCoverage(coverage, alphaRef);
context.compress(tmpImage, compressionOptions, outputOptions); context.compress(tmpImage, compressionOptions, outputOptions);
} }

Loading…
Cancel
Save