From a088ae5789d20f8a72ec805da59ac23ec8980fb8 Mon Sep 17 00:00:00 2001 From: castano Date: Sun, 18 Oct 2009 20:03:21 +0000 Subject: [PATCH] Implement normal map generation for floating point images. --- src/nvimage/NormalMap.cpp | 78 ++++++++++++++++++++++++++++++++++++--- src/nvimage/NormalMap.h | 4 +- 2 files changed, 75 insertions(+), 7 deletions(-) diff --git a/src/nvimage/NormalMap.cpp b/src/nvimage/NormalMap.cpp index 2ece574..5ab1691 100644 --- a/src/nvimage/NormalMap.cpp +++ b/src/nvimage/NormalMap.cpp @@ -36,9 +36,9 @@ 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); + nvDebugCheck(kdu != NULL); + nvDebugCheck(kdv != NULL); + nvDebugCheck(img != NULL); const uint w = img->width(); const uint h = img->height(); @@ -75,10 +75,54 @@ static FloatImage * createNormalMap(const Image * img, FloatImage::WrapMode wm, } +// Create normal map using the given kernels. +static FloatImage * createNormalMap(const FloatImage * img, FloatImage::WrapMode wm, const Kernel2 * kdu, const Kernel2 * kdv) +{ + nvDebugCheck(kdu != NULL); + nvDebugCheck(kdv != NULL); + nvDebugCheck(img != NULL); + + #pragma message(NV_FILE_LINE "Height scale parameter should go away. It should be a sensible value that produces good results when the heightmap is in the [0, 1] range.") + const float heightScale = 1.0f / 16.0f; + + const uint w = img->width(); + const uint h = img->height(); + + AutoPtr img_out(new FloatImage()); + img_out->allocate(4, w, h); + + for (uint y = 0; y < h; y++) + { + for (uint x = 0; x < w; x++) + { + const float du = img->applyKernel(kdu, x, y, 3, wm); + const float dv = img->applyKernel(kdv, x, y, 3, wm); + + Vector3 n = normalize(Vector3(du, dv, heightScale)); + + img_out->setPixel(n.x(), x, y, 0); + img_out->setPixel(n.y(), x, y, 1); + img_out->setPixel(n.z(), x, y, 2); + } + } + + // Copy alpha channel. + for (uint y = 0; y < h; y++) + { + for (uint x = 0; x < w; x++) + { + img_out->setPixel(img->pixel(x, y, 3), x, y, 3); + } + } + + return img_out.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); + nvDebugCheck(img != NULL); // Init the kernels. Kernel2 * kdu = NULL; @@ -115,7 +159,7 @@ FloatImage * nv::createNormalMap(const Image * img, FloatImage::WrapMode wm, Vec /// 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); + nvDebugCheck(img != NULL); Kernel2 * kdu = NULL; Kernel2 * kdv = NULL; @@ -130,10 +174,32 @@ FloatImage * nv::createNormalMap(const Image * img, FloatImage::WrapMode wm, Vec return ::createNormalMap(img, wm, heightWeights, kdu, kdv); } + +FloatImage * nv::createNormalMap(const FloatImage * img, FloatImage::WrapMode wm, Vector4::Arg filterWeights) +{ + nvDebugCheck(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, kdu, kdv); +} + + /// Normalize the given image in place. void nv::normalizeNormalMap(FloatImage * img) { - nvCheck(img != NULL); + nvDebugCheck(img != NULL); + +#pragma messsage(NV_FILE_LINE "Pack and expand normals explicitly") + img->expandNormals(0); img->normalize(0); img->packNormals(0); diff --git a/src/nvimage/NormalMap.h b/src/nvimage/NormalMap.h index 670ead4..48b2fbe 100644 --- a/src/nvimage/NormalMap.h +++ b/src/nvimage/NormalMap.h @@ -41,10 +41,12 @@ namespace nv NormalMapFilter_Sobel9x9, // very large }; + // @@ These two functions should be deprecated: FloatImage * createNormalMap(const Image * img, FloatImage::WrapMode wm, Vector4::Arg heightWeights, NormalMapFilter filter = NormalMapFilter_Sobel3x3); - FloatImage * createNormalMap(const Image * img, FloatImage::WrapMode wm, Vector4::Arg heightWeights, Vector4::Arg filterWeights); + FloatImage * createNormalMap(const FloatImage * img, FloatImage::WrapMode wm, Vector4::Arg filterWeights); + void normalizeNormalMap(FloatImage * img); // @@ Add generation of DU/DV maps.