From f08e2c4f649271e90fa1430c6bfdf41cbba2f07c Mon Sep 17 00:00:00 2001 From: castano Date: Thu, 3 Jun 2010 05:49:04 +0000 Subject: [PATCH] Add alpha map processor. --- src/nvtt/TexImage.cpp | 45 ++++++++- src/nvtt/nvtt.h | 4 + src/nvtt/tests/CMakeLists.txt | 4 + src/nvtt/tests/process_alpha_map.cpp | 142 +++++++++++++++++++++++++++ 4 files changed, 193 insertions(+), 2 deletions(-) create mode 100644 src/nvtt/tests/process_alpha_map.cpp diff --git a/src/nvtt/TexImage.cpp b/src/nvtt/TexImage.cpp index e860f80..b889e04 100644 --- a/src/nvtt/TexImage.cpp +++ b/src/nvtt/TexImage.cpp @@ -1132,8 +1132,8 @@ float TexImage::rootMeanSquaredError_alpha(const TexImage & reference) const return float(sqrt(mse / totalCount)); } -void TexImage::flipVertically() { - +void TexImage::flipVertically() +{ detach(); foreach (i, m->imageArray) @@ -1143,3 +1143,44 @@ void TexImage::flipVertically() { m->imageArray[i]->flip(); } } + +bool TexImage::copyChannel(const TexImage & srcImage, int srcChannel) +{ + return copyChannel(srcImage, srcChannel, srcChannel); +} + +bool TexImage::copyChannel(const TexImage & srcImage, int srcChannel, int dstChannel) +{ + const int faceCount = this->faceCount(); + if (faceCount != srcImage.faceCount()) { + return false; + } + + detach(); + + foreach (i, m->imageArray) + { + FloatImage * dst = m->imageArray[i]; + const FloatImage * src = srcImage.m->imageArray[i]; + + if (dst == NULL || src == NULL) { + return false; + } + + nvCheck(src->componentNum() == 4); + nvCheck(dst->componentNum() == 4); + + const uint w = src->width(); + const uint h = src->height(); + + if (w != dst->width() || h != dst->height()) { + return false; + } + + memcpy(dst->channel(dstChannel), src->channel(srcChannel), w*h*sizeof(float)); + } + + return true; +} + + diff --git a/src/nvtt/nvtt.h b/src/nvtt/nvtt.h index 921f906..dce44c3 100644 --- a/src/nvtt/nvtt.h +++ b/src/nvtt/nvtt.h @@ -453,6 +453,10 @@ namespace nvtt // Geometric transforms. NVTT_API void flipVertically(); + // Copy image data. + NVTT_API bool copyChannel(const TexImage & srcImage, int srcChannel); + NVTT_API bool copyChannel(const TexImage & srcImage, int srcChannel, int dstChannel); + private: void detach(); diff --git a/src/nvtt/tests/CMakeLists.txt b/src/nvtt/tests/CMakeLists.txt index b30c353..4b49dd5 100644 --- a/src/nvtt/tests/CMakeLists.txt +++ b/src/nvtt/tests/CMakeLists.txt @@ -19,6 +19,10 @@ ENDIF (CUDA_FOUND) ADD_EXECUTABLE(imperativeapi imperativeapi.cpp) TARGET_LINK_LIBRARIES(imperativeapi nvcore nvmath nvimage nvtt) +ADD_EXECUTABLE(process_alpha_map process_alpha_map.cpp) +TARGET_LINK_LIBRARIES(process_alpha_map + nvcore nvmath nvimage nvtt) + INSTALL(TARGETS nvtestsuite DESTINATION bin) #include_directories("/usr/include/ffmpeg/") diff --git a/src/nvtt/tests/process_alpha_map.cpp b/src/nvtt/tests/process_alpha_map.cpp new file mode 100644 index 0000000..850ce65 --- /dev/null +++ b/src/nvtt/tests/process_alpha_map.cpp @@ -0,0 +1,142 @@ +// Copyright NVIDIA Corporation 2007 -- 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 +#include + +#include // EXIT_SUCCESS, EXIT_FAILURE +#include // printf + +int main(int argc, char *argv[]) +{ + if (argc != 2 || argc != 3) { + printf("Usage:\n process_alpha_map color_map [normal_map].\n"); + return EXIT_FAILURE; + } + + const char * inputFileNameColor = argv[1]; + const char * inputFileNameNormal = NULL; + if (argc == 3) inputFileNameNormal = argv[2]; + + // Init context. + nvtt::Context context; + context.enableCudaAcceleration(false); + + // Load color map. + nvtt::TexImage colorMap = context.createTexImage(); + if (!colorMap.load(inputFileNameColor)) { + printf("Image '%s' could not be loaded.\n", inputFileNameColor); + return EXIT_FAILURE; + } + + // Setup compression options. + nvtt::CompressionOptions colorCompressionOptions; + colorCompressionOptions.setFormat(nvtt::Format_BC3); + + // Setup output options. + nvtt::OutputOptions colorOutputOptions; + + nv::Path outputFileNameColor(inputFileNameColor); + outputFileNameColor.stripExtension(); + outputFileNameColor.append(".dds"); + + colorOutputOptions.setFileName(outputFileNameColor); + + // Load normal map. + nvtt::TexImage normalMap; + if (inputFileNameNormal != NULL) { + normalMap = context.createTexImage(); + if (!normalMap.load(inputFileNameColor)) { + printf("Image '%s' could not be loaded.\n", inputFileNameNormal); + return EXIT_FAILURE; + } + + if (colorMap.width() != normalMap.width() || colorMap.height() != normalMap.height()) { + printf("Image '%s' and '%s' do not have the same extents.\n", inputFileNameColor, inputFileNameNormal); + return EXIT_FAILURE; + } + } + + // Setup compression options. + nvtt::CompressionOptions normalCompressionOptions; + normalCompressionOptions.setFormat(nvtt::Format_BC3n); + + // Setup output options. + nvtt::OutputOptions normalOutputOptions; + + if (inputFileNameNormal != NULL) { + nv::Path outputFileNameNormal(inputFileNameNormal); + outputFileNameNormal.stripExtension(); + outputFileNameNormal.append(".dds"); + + normalOutputOptions.setFileName(outputFileNameNormal); + } + + + // Output header and first mipmap. + context.outputHeader(colorMap, colorMap.countMipmaps(), colorCompressionOptions, colorOutputOptions); + + colorMap.flipVertically(); + colorMap.setAlphaMode(nvtt::AlphaMode_Transparency); + + context.compress(colorMap, colorCompressionOptions, colorOutputOptions); + + if (inputFileNameNormal != NULL) { + context.outputHeader(normalMap, normalMap.countMipmaps(), normalCompressionOptions, normalOutputOptions); + + normalMap.flipVertically(); + normalMap.setAlphaMode(nvtt::AlphaMode_Transparency); + normalMap.normalizeNormalMap(); + normalMap.copyChannel(colorMap, 3); // Copy alpha channel from color to normal map. + + context.compress(normalMap, normalCompressionOptions, normalOutputOptions); + } + + const float gamma = 2.2f; + colorMap.toLinear(gamma); + + const float alphaRef = 0.95; + const float coverage = colorMap.alphaTestCoverage(alphaRef); + + // Build and output mipmaps. + while (colorMap.buildNextMipmap(nvtt::MipmapFilter_Kaiser)) + { + colorMap.scaleAlphaToCoverage(coverage, alphaRef); + + nvtt::TexImage tmpColorMap = colorMap; + tmpColorMap.toGamma(gamma); + + context.compress(tmpColorMap, colorCompressionOptions, colorOutputOptions); + + if (inputFileNameNormal != NULL) { + normalMap.buildNextMipmap(nvtt::MipmapFilter_Kaiser); + normalMap.normalizeNormalMap(); + normalMap.copyChannel(tmpColorMap, 3); + + context.compress(normalMap, normalCompressionOptions, normalOutputOptions); + } + } + + return EXIT_SUCCESS; +} +