diff --git a/src/nvtt/Context.cpp b/src/nvtt/Context.cpp index f0faa2c..e2f1b27 100644 --- a/src/nvtt/Context.cpp +++ b/src/nvtt/Context.cpp @@ -286,10 +286,32 @@ int Compressor::estimateSize(const InputOptions & inputOptions, const Compressio return m.estimateSize(inputOptions.m, compressionOptions.m); } -/// Estimate the size of compressing the input with the given options. -Texture Compressor::createTexture() +/// Create a texture. +TexImage Compressor::createTexImage() +{ + return *new TexImage(); +} + +/// Estimate the size of compressing the given texture. +int Compressor::estimateSize(const TexImage & tex, const CompressionOptions & compressionOptions) +{ + const CompressionOptions::Private & co = compressionOptions.m; + + const Format format = co.format; + + uint bitCount = co.bitcount; + if (format == Format_RGBA && bitCount == 0) bitCount = co.rsize + co.gsize + co.bsize + co.asize; + + const uint w = tex.width(); + const uint h = tex.height(); + const uint d = tex.depth(); + const uint faceCount = tex.faceCount(); + + return faceCount * computeImageSize(w, h, d, bitCount, format); +} + +void Compressor::outputCompressed(const TexImage & tex, const CompressionOptions & compressionOptions, const OutputOptions & outputOptions) { - return *new Texture(); } diff --git a/src/nvtt/Texture.cpp b/src/nvtt/Texture.cpp index f9e88cd..d8ed8ba 100644 --- a/src/nvtt/Texture.cpp +++ b/src/nvtt/Texture.cpp @@ -25,9 +25,11 @@ #include #include +#include #include #include +#include using namespace nv; using namespace nvtt; @@ -57,48 +59,60 @@ namespace } -Texture::Texture() : m(new Texture::Private()) +TexImage::TexImage() : m(new TexImage::Private()) { } -Texture::Texture(const Texture & tex) : m(tex.m) +TexImage::TexImage(const TexImage & tex) : m(tex.m) { m->addRef(); } -Texture::~Texture() +TexImage::~TexImage() { m->release(); m = NULL; } -void Texture::operator=(const Texture & tex) +void TexImage::operator=(const TexImage & tex) { tex.m->addRef(); m = tex.m; m->release(); } -void Texture::detach() +void TexImage::detach() { if (m->refCount() > 1) { - m = new Texture::Private(*m); + m = new TexImage::Private(*m); m->addRef(); nvDebugCheck(m->refCount() == 1); } } -void Texture::setType(TextureType type) +void TexImage::setTextureType(TextureType type) { if (m->type != type) { detach(); + m->type = type; + + if (type == TextureType_2D) + { + // @@ Free images. + m->imageArray.resize(1, NULL); + } + else + { + nvCheck (type == TextureType_Cube); + m->imageArray.resize(6, NULL); + } } } -void Texture::setWrapMode(WrapMode wrapMode) +void TexImage::setWrapMode(WrapMode wrapMode) { if (m->wrapMode != wrapMode) { @@ -107,7 +121,7 @@ void Texture::setWrapMode(WrapMode wrapMode) } } -void Texture::setAlphaMode(AlphaMode alphaMode) +void TexImage::setAlphaMode(AlphaMode alphaMode) { if (m->alphaMode != alphaMode) { @@ -116,7 +130,7 @@ void Texture::setAlphaMode(AlphaMode alphaMode) } } -void Texture::setNormalMap(bool isNormalMap) +void TexImage::setNormalMap(bool isNormalMap) { if (m->isNormalMap != isNormalMap) { @@ -125,7 +139,55 @@ void Texture::setNormalMap(bool isNormalMap) } } -bool Texture::load(const char * fileName) +int TexImage::width() const +{ + if (m->imageArray.count() > 0) + { + return m->imageArray[0]->width(); + } + return 0; +} + +int TexImage::height() const +{ + if (m->imageArray.count() > 0) + { + return m->imageArray[0]->height(); + } + return 0; +} + +int TexImage::depth() const +{ + return 0; +} + +int TexImage::faceCount() const +{ + return m->imageArray.count(); +} + +TextureType TexImage::textureType() const +{ + return m->type; +} + +WrapMode TexImage::wrapMode() const +{ + return m->wrapMode; +} + +AlphaMode TexImage::alphaMode() const +{ + return m->alphaMode; +} + +bool TexImage::isNormalMap() const +{ + return m->isNormalMap; +} + +bool TexImage::load(const char * fileName) { // @@ Add support for DDS textures! @@ -136,26 +198,142 @@ bool Texture::load(const char * fileName) return false; } + detach(); + m->imageArray.resize(1); m->imageArray[0] = img.release(); return true; } -void Texture::setTexture2D(InputFormat format, int w, int h, int idx, void * data) +bool TexImage::setImage2D(InputFormat format, int w, int h, int idx, const void * restrict data) { - // @@ Not implemented. + if (idx >= m->imageArray.count()) + { + return false; + } + + FloatImage * img = m->imageArray[idx]; + if (img->width() != w || img->height() != h) + { + return false; + } + + detach(); + + const int count = w * h; + + float * restrict rdst = img->channel(0); + float * restrict gdst = img->channel(1); + float * restrict bdst = img->channel(2); + float * restrict adst = img->channel(3); + + if (format == InputFormat_BGRA_8UB) + { + const Color32 * src = (const Color32 *)data; + + try { + for (int i = 0; i < count; i++) + { + rdst[i] = src[i].r; + gdst[i] = src[i].g; + bdst[i] = src[i].b; + adst[i] = src[i].a; + } + } + catch(...) { + return false; + } + } + else if (format == InputFormat_RGBA_32F) + { + const float * src = (const float *)data; + + try { + for (int i = 0; i < count; i++) + { + rdst[i] = src[4 * i + 0]; + gdst[i] = src[4 * i + 1]; + bdst[i] = src[4 * i + 2]; + adst[i] = src[4 * i + 3]; + } + } + catch(...) { + return false; + } + } + + return true; } +bool TexImage::setImage2D(InputFormat format, int w, int h, int idx, const void * restrict r, const void * restrict g, const void * restrict b, const void * restrict a) +{ + if (idx >= m->imageArray.count()) + { + return false; + } + + FloatImage * img = m->imageArray[idx]; + if (img->width() != w || img->height() != h) + { + return false; + } + + detach(); -void Texture::resize(int w, int h, ResizeFilter filter) + const int count = w * h; + + float * restrict rdst = img->channel(0); + float * restrict gdst = img->channel(1); + float * restrict bdst = img->channel(2); + float * restrict adst = img->channel(3); + + if (format == InputFormat_BGRA_8UB) + { + const uint8 * restrict rsrc = (const uint8 *)r; + const uint8 * restrict gsrc = (const uint8 *)g; + const uint8 * restrict bsrc = (const uint8 *)b; + const uint8 * restrict asrc = (const uint8 *)a; + + try { + for (int i = 0; i < count; i++) rdst[i] = float(rsrc[i]) / 255.0f; + for (int i = 0; i < count; i++) gdst[i] = float(gsrc[i]) / 255.0f; + for (int i = 0; i < count; i++) bdst[i] = float(bsrc[i]) / 255.0f; + for (int i = 0; i < count; i++) adst[i] = float(asrc[i]) / 255.0f; + } + catch(...) { + return false; + } + } + else if (format == InputFormat_RGBA_32F) + { + const float * rsrc = (const float *)r; + const float * gsrc = (const float *)g; + const float * bsrc = (const float *)b; + const float * asrc = (const float *)a; + + try { + memcpy(rdst, rsrc, count * sizeof(float)); + memcpy(gdst, gsrc, count * sizeof(float)); + memcpy(bdst, bsrc, count * sizeof(float)); + memcpy(adst, asrc, count * sizeof(float)); + } + catch(...) { + return false; + } + } + + return true; +} + +void TexImage::resize(int w, int h, ResizeFilter filter) { if (m->imageArray.count() > 0) { if (w == m->imageArray[0]->width() && h == m->imageArray[0]->height()) return; } - // @TODO: if cubemap, make sure w == h. + // @@ TODO: if cubemap, make sure w == h. detach(); @@ -218,7 +396,7 @@ void Texture::resize(int w, int h, ResizeFilter filter) } } -void Texture::resize(int maxExtent, RoundMode roundMode, ResizeFilter filter) +void TexImage::resize(int maxExtent, RoundMode roundMode, ResizeFilter filter) { if (m->imageArray.count() > 0) { @@ -263,7 +441,7 @@ void Texture::resize(int maxExtent, RoundMode roundMode, ResizeFilter filter) } } -bool Texture::buildNextMipmap(MipmapFilter filter) +bool TexImage::buildNextMipmap(MipmapFilter filter) { if (m->imageArray.count() > 0) { @@ -332,7 +510,7 @@ bool Texture::buildNextMipmap(MipmapFilter filter) } // Color transforms. -void Texture::toLinear(float gamma) +void TexImage::toLinear(float gamma) { if (equal(gamma, 1.0f)) return; @@ -344,7 +522,7 @@ void Texture::toLinear(float gamma) } } -void Texture::toGamma(float gamma) +void TexImage::toGamma(float gamma) { if (equal(gamma, 1.0f)) return; @@ -356,7 +534,7 @@ void Texture::toGamma(float gamma) } } -void Texture::transform(const float w0[4], const float w1[4], const float w2[4], const float w3[4], const float offset[4]) +void TexImage::transform(const float w0[4], const float w1[4], const float w2[4], const float w3[4], const float offset[4]) { detach(); @@ -374,7 +552,7 @@ void Texture::transform(const float w0[4], const float w1[4], const float w2[4], } } -void Texture::swizzle(int r, int g, int b, int a) +void TexImage::swizzle(int r, int g, int b, int a) { if (r == 0 && g == 1 && b == 2 && a == 3) return; @@ -386,7 +564,7 @@ void Texture::swizzle(int r, int g, int b, int a) } } -void Texture::scaleBias(int channel, float scale, float bias) +void TexImage::scaleBias(int channel, float scale, float bias) { if (equal(scale, 1.0f) && equal(bias, 0.0f)) return; @@ -398,31 +576,61 @@ void Texture::scaleBias(int channel, float scale, float bias) } } -void Texture::normalizeNormals() +void TexImage::blend(float r, float g, float b, float a) { detach(); foreach(i, m->imageArray) { - m->imageArray[i]->normalize(0); + // @@ Not implemented. } } -void Texture::blend(float r, float g, float b, float a) +void TexImage::premultiplyAlpha() { detach(); - foreach(i, m->imageArray) - { - // @@ Not implemented. - } + // @@ Not implemented. +} + + +void TexImage::toGreyScale(float redScale, float greenScale, float blueScale, float alphaScale) +{ + detach(); + + // @@ Not implemented. +} + +// Set normal map options. +void TexImage::toNormalMap(float sm, float medium, float big, float large) +{ + detach(); + + + // @@ Not implemented. } -void Texture::premultiplyAlpha() +void TexImage::toHeightMap() { detach(); // @@ Not implemented. } +void TexImage::normalizeNormalMap() +{ + //nvCheck(m->isNormalMap); + + detach(); + foreach(i, m->imageArray) + { + nv::normalizeNormalMap(m->imageArray[i]); + } +} + +// Compress. +void TexImage::outputCompressed(const CompressionOptions & compressionOptions, const OutputOptions & outputOptions) +{ + // @@ Not implemented. +} diff --git a/src/nvtt/Texture.h b/src/nvtt/Texture.h index a57401c..f149886 100644 --- a/src/nvtt/Texture.h +++ b/src/nvtt/Texture.h @@ -36,7 +36,7 @@ namespace nvtt { - struct Texture::Private : public nv::RefCounted + struct TexImage::Private : public nv::RefCounted { Private() { @@ -44,6 +44,8 @@ namespace nvtt wrapMode = WrapMode_Mirror; alphaMode = AlphaMode_None; isNormalMap = false; + + imageArray.resize(1, NULL); } Private(const Private & p) { diff --git a/src/nvtt/nvtt.h b/src/nvtt/nvtt.h index ba74f30..1a044ed 100644 --- a/src/nvtt/nvtt.h +++ b/src/nvtt/nvtt.h @@ -65,7 +65,7 @@ namespace nvtt { // Forward declarations. - struct Texture; + struct TexImage; /// Supported compression formats. enum Format @@ -357,31 +357,45 @@ namespace nvtt // Estimate the size of compressing the input with the given options. NVTT_API int estimateSize(const InputOptions & inputOptions, const CompressionOptions & compressionOptions) const; - NVTT_API Texture createTexture(); + // TexImage api + NVTT_API TexImage createTexImage(); + NVTT_API int estimateSize(const TexImage & tex, const CompressionOptions & compressionOptions); + NVTT_API void outputCompressed(const TexImage & tex, const CompressionOptions & compressionOptions, const OutputOptions & outputOptions); }; // "Compressor" is deprecated. This should have been called "Context" typedef Compressor Context; - /// Texture data. - struct Texture + /// A texture mipmap. + struct TexImage { - NVTT_API Texture(); - NVTT_API Texture(const Texture & tex); - NVTT_API ~Texture(); + NVTT_API TexImage(); + NVTT_API TexImage(const TexImage & tex); + NVTT_API ~TexImage(); - NVTT_API void operator=(const Texture & tex); + NVTT_API void operator=(const TexImage & tex); // Texture parameters. - NVTT_API void setType(TextureType type); + NVTT_API void setTextureType(TextureType type); NVTT_API void setWrapMode(WrapMode mode); NVTT_API void setAlphaMode(AlphaMode alphaMode); NVTT_API void setNormalMap(bool isNormalMap); + // Accessors. + NVTT_API int width() const; + NVTT_API int height() const; + NVTT_API int depth() const; + NVTT_API int faceCount() const; + NVTT_API TextureType textureType() const; + NVTT_API WrapMode wrapMode() const; + NVTT_API AlphaMode alphaMode() const; + NVTT_API bool isNormalMap() const; + // Texture data. NVTT_API bool load(const char * fileName); - NVTT_API void setTexture2D(InputFormat format, int w, int h, int idx, void * data); + NVTT_API bool setImage2D(InputFormat format, int w, int h, int idx, const void * data); + NVTT_API bool setImage2D(InputFormat format, int w, int h, int idx, const void * r, const void * g, const void * b, const void * a); // Resizing methods. NVTT_API void resize(int w, int h, ResizeFilter filter); @@ -401,10 +415,10 @@ namespace nvtt // Set normal map options. NVTT_API void toNormalMap(float sm, float medium, float big, float large); NVTT_API void toHeightMap(); - NVTT_API void normalizeNormals(); + NVTT_API void normalizeNormalMap(); // Compress. - NVTT_API void process(const CompressionOptions & compressionOptions, const OutputOptions & outputOptions); + NVTT_API void outputCompressed(const CompressionOptions & compressionOptions, const OutputOptions & outputOptions); private: void detach(); diff --git a/src/nvtt/tests/imperativeapi.cpp b/src/nvtt/tests/imperativeapi.cpp index abbe4a7..9ebc98f 100644 --- a/src/nvtt/tests/imperativeapi.cpp +++ b/src/nvtt/tests/imperativeapi.cpp @@ -35,20 +35,20 @@ int main(int argc, char *argv[]) outputOptions.setFileName("output.dds"); nvtt::Context context; - nvtt::Texture texture = context.createTexture(); + nvtt::TexImage image = context.createTexImage(); - texture.load("kodim01.png"); + image.load("kodim01.png"); float gamma = 2.2; - texture.toLinear(gamma); + image.toLinear(gamma); - while (texture.buildNextMipmap(nvtt::MipmapFilter_Box)) + while (image.buildNextMipmap(nvtt::MipmapFilter_Box)) { - nvtt::Texture tmp = texture; - tmp.toGamma(gamma); + nvtt::TexImage tmpImage = image; + tmpImage.toGamma(gamma); - // context.process(tmp, compressionOptions, outputOptions); - // tmp.process(compressionOptions, outputOptions); + context.outputCompressed(tmpImage, compressionOptions, outputOptions); + // tmpImage.outputCompressed(compressionOptions, outputOptions); } return EXIT_SUCCESS;