diff --git a/src/nvtt/CMakeLists.txt b/src/nvtt/CMakeLists.txt index 793e0e5..29e0482 100644 --- a/src/nvtt/CMakeLists.txt +++ b/src/nvtt/CMakeLists.txt @@ -24,12 +24,11 @@ SET(NVTT_SRCS OutputOptions.h OutputOptions.cpp TaskDispatcher.h TaskDispatcher.cpp TexImage.h TexImage.cpp - cuda/CudaUtils.h - cuda/CudaUtils.cpp + CubeImage.h CubeImage.cpp + cuda/CudaUtils.h cuda/CudaUtils.cpp cuda/CudaMath.h cuda/BitmapTable.h - cuda/CudaCompressorDXT.h - cuda/CudaCompressorDXT.cpp) + cuda/CudaCompressorDXT.h cuda/CudaCompressorDXT.cpp) IF (CUDA_FOUND) ADD_DEFINITIONS(-DHAVE_CUDA) diff --git a/src/nvtt/CubeImage.cpp b/src/nvtt/CubeImage.cpp new file mode 100644 index 0000000..61c229e --- /dev/null +++ b/src/nvtt/CubeImage.cpp @@ -0,0 +1,126 @@ +// Copyright (c) 2009-2011 Ignacio Castano +// +// 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 "CubeImage.h" + +using namespace nv; +using namespace nvtt; + + + + +CubeImage::CubeImage() : m(new CubeImage::Private()) +{ + m->addRef(); +} + +CubeImage::CubeImage(const CubeImage & cube) : m(cube.m) +{ + if (m != NULL) m->addRef(); +} + +CubeImage::~CubeImage() +{ + if (m != NULL) m->release(); + m = NULL; +} + +void CubeImage::operator=(const CubeImage & cube) +{ + if (cube.m != NULL) cube.m->addRef(); + if (m != NULL) m->release(); + m = cube.m; +} + +void CubeImage::detach() +{ + if (m->refCount() > 1) + { + m->release(); + m = new CubeImage::Private(*m); + m->addRef(); + nvDebugCheck(m->refCount() == 1); + } +} + + + +bool CubeImage::isNull() const +{ + return m->size == 0; +} + +int CubeImage::size() const +{ + return m->size; +} + +int CubeImage::countMipmaps() const +{ + return nv::countMipmaps(m->size); +} + +TexImage & CubeImage::face(int f) +{ + nvDebugCheck(f >= 0 && f < 6); + return m->face[f]; +} + + +bool CubeImage::load(const char * fileName) +{ + return false; +} + +bool CubeImage::save(const char * fileName) const +{ + return false; +} + + +void CubeImage::fold(const TexImage & tex, CubeLayout layout) +{ + +} + +TexImage CubeImage::unfold(CubeLayout layout) +{ + +} + + + +void CubeImage::toLinear(float gamma) +{ + for (int i = 0; i < 6; i++) { + m->face.toLinear(gamma); + } +} + +void CubeImage::toGamma(float gamma) +{ + for (int i = 0; i < 6; i++) { + m->face.toGamma(gamma); + } +} + diff --git a/src/nvtt/CubeImage.h b/src/nvtt/CubeImage.h new file mode 100644 index 0000000..659675b --- /dev/null +++ b/src/nvtt/CubeImage.h @@ -0,0 +1,66 @@ +// Copyright (c) 2009-2011 Ignacio Castano +// +// 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 NVTT_CUBEIMAGE_H +#define NVTT_CUBEIMAGE_H + +#include "nvtt.h" + +#include "nvcore/RefCounted.h" +#include "nvcore/Ptr.h" + + +namespace nvtt +{ + + struct CubeImage::Private : public nv::RefCounted + { + void operator=(const Private &); + public: + Private() + { + nvDebugCheck( refCount() == 0 ); + + size = 0; + } + Private(const Private & p) : RefCounted() // Copy ctor. inits refcount to 0. + { + nvDebugCheck( refCount() == 0 ); + + size = p.size; + for (uint i = 0; i < 6; i++) { + face[i] = p.face[6]; + } + } + ~Private() + { + } + + int size; + TexImage face[6]; + }; + +} // nvtt namespace + + +#endif // NVTT_CUBEIMAGE_H diff --git a/src/nvtt/TexImage.cpp b/src/nvtt/TexImage.cpp index da2789e..17312be 100644 --- a/src/nvtt/TexImage.cpp +++ b/src/nvtt/TexImage.cpp @@ -55,14 +55,14 @@ namespace const uint np2 = nextPowerOfTwo(v); const uint pp2 = previousPowerOfTwo(v); - if (np2 - v <= v - pp2) - { - return np2; - } - else - { - return pp2; - } + if (np2 - v <= v - pp2) + { + return np2; + } + else + { + return pp2; + } } static int blockSize(Format format) @@ -95,6 +95,18 @@ namespace } } +uint nv::countMipmaps(uint w) +{ + uint mipmap = 0; + + while (w != 1) { + w = max(1U, w / 2); + mipmap++; + } + + return mipmap + 1; +} + uint nv::countMipmaps(uint w, uint h, uint d) { uint mipmap = 0; @@ -115,9 +127,7 @@ uint nv::computeImageSize(uint w, uint h, uint d, uint bitCount, uint pitchAlign return d * h * computeBytePitch(w, bitCount, pitchAlignmentInBytes); } else { - nvDebugCheck(d == 1); - // @@ Handle 3D textures. DXT and VTC have different behaviors. - return ((w + 3) / 4) * ((h + 3) / 4) * blockSize(format); + return ((w + 3) / 4) * ((h + 3) / 4) * blockSize(format) * d; } } @@ -1118,6 +1128,8 @@ void TexImage::toRGBM(float range/*= 1*/, float threshold/*= 0.25*/) detach(); + //threshold = clamp(threshold, 1e-6f, 1.0f); + threshold = 1e-6f; float irange = 1.0f / range; FloatImage * img = m->image; @@ -1131,13 +1143,51 @@ void TexImage::toRGBM(float range/*= 1*/, float threshold/*= 0.25*/) float R = nv::clamp(r[i] * irange, 0.0f, 1.0f); float G = nv::clamp(g[i] * irange, 0.0f, 1.0f); float B = nv::clamp(b[i] * irange, 0.0f, 1.0f); - - float M = max(max(R, G), max(B, 1e-6f)); // Avoid division by zero. +#if 1 + float M = max(max(R, G), max(B, threshold)); r[i] = R / M; g[i] = G / M; b[i] = B / M; a[i] = M; + +#else + + // The optimal compressor theoretically produces the best results, but unfortunately introduces + // severe interpolation errors! + float bestM; + float bestError = FLT_MAX; + + int minM = iround(min(R, G, B) * 255.0f); + + for (int m = minM; m < 256; m++) { + float fm = float(m) / 255.0f; + + // Encode. + int ir = iround(255.0f * nv::clamp(R / fm, 0.0f, 1.0f)); + int ig = iround(255.0f * nv::clamp(G / fm, 0.0f, 1.0f)); + int ib = iround(255.0f * nv::clamp(B / fm, 0.0f, 1.0f)); + + // Decode. + float fr = (float(ir) / 255.0f) * fm; + float fg = (float(ig) / 255.0f) * fm; + float fb = (float(ib) / 255.0f) * fm; + + // Measure error. + float error = square(R-fr) + square(G-fg) + square(B-fb); + + if (error < bestError) { + bestError = error; + bestM = fm; + } + } + + M = bestM; + r[i] = nv::clamp(R / M, 0.0f, 1.0f); + g[i] = nv::clamp(G / M, 0.0f, 1.0f); + b[i] = nv::clamp(B / M, 0.0f, 1.0f); + a[i] = M; +#endif } } diff --git a/src/nvtt/TexImage.h b/src/nvtt/TexImage.h index 7cef68e..e8ef412 100644 --- a/src/nvtt/TexImage.h +++ b/src/nvtt/TexImage.h @@ -78,6 +78,7 @@ namespace nvtt } // nvtt namespace namespace nv { + uint countMipmaps(uint w); uint countMipmaps(uint w, uint h, uint d); uint computeImageSize(uint w, uint h, uint d, uint bitCount, uint alignmentInBytes, nvtt::Format format); void getTargetExtent(int & w, int & h, int & d, int maxExtent, nvtt::RoundMode roundMode, nvtt::TextureType textureType); diff --git a/src/nvtt/nvtt.h b/src/nvtt/nvtt.h index a8c6942..e8577b9 100644 --- a/src/nvtt/nvtt.h +++ b/src/nvtt/nvtt.h @@ -507,7 +507,15 @@ namespace nvtt }; - /// A texture mipmap. + enum CubeLayout { + CubeLayout_VerticalCross, + CubeLayout_HorizontalCross, + CubeLayout_Column, + CubeLayout_Row, + CubeLayout_LatitudeLongitude, + }; + + /// A cubemap mipmap. struct CubeImage { NVTT_API CubeImage(); @@ -520,20 +528,24 @@ namespace nvtt NVTT_API bool isNull() const; NVTT_API int size() const; NVTT_API int countMipmaps() const; - NVTT_API float average(int channel, int alpha_channel = -1, float gamma = 2.2f) const; // Texture data. NVTT_API bool load(const char * fileName); NVTT_API bool save(const char * fileName) const; - NVTT_API bool setImage2D(InputFormat format, int face, int w, int h, const void * data); - NVTT_API bool setImage2D(InputFormat format, int face, int w, int h, const void * r, const void * g, const void * b, const void * a); - NVTT_API bool setImage2D(Format format, Decoder decoder, int face, int w, int h, const void * data); TexImage & face(int face); - // + // Layout conversion. + void fold(TexImage & img, CubeLayout layout); + TexImage unfold(CubeLayout layout); + + // @@ Angular extent filtering. // @@ Add resizing methods. + + // @@ Irradiance cubemaps. + CubeImage irradiance(int size); + /* NVTT_API void resize(int w, int h, ResizeFilter filter); NVTT_API void resize(int w, int h, ResizeFilter filter, float filterWidth, const float * params = 0);