Add support for 3D texture. Integrate patch provided in issue 28 plus some additional changes.
This commit is contained in:
@ -2,6 +2,7 @@
|
||||
|
||||
#include "ColorBlock.h"
|
||||
#include "Image.h"
|
||||
#include "FloatImage.h"
|
||||
|
||||
#include "nvmath/Box.h"
|
||||
#include "nvcore/Utils.h" // swap
|
||||
@ -458,7 +459,6 @@ float ColorBlock::volume() const
|
||||
return bounds.volume();
|
||||
}*/
|
||||
|
||||
#include "FloatImage.h"
|
||||
|
||||
void ColorSet::setColors(const float * data, uint img_w, uint img_h, uint img_x, uint img_y)
|
||||
{
|
||||
|
@ -983,12 +983,6 @@ bool DirectDrawSurface::isSupported() const
|
||||
// Cubemaps must contain all faces.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isTexture3D())
|
||||
{
|
||||
// @@ 3D textures not supported yet.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -1127,15 +1121,17 @@ void DirectDrawSurface::mipmap(Image * img, uint face, uint mipmap)
|
||||
|
||||
uint w = width();
|
||||
uint h = height();
|
||||
uint d = depth();
|
||||
|
||||
// Compute width and height.
|
||||
for (uint m = 0; m < mipmap; m++)
|
||||
{
|
||||
w = max(1U, w / 2);
|
||||
h = max(1U, h / 2);
|
||||
d = max(1U, d / 2);
|
||||
}
|
||||
|
||||
img->allocate(w, h);
|
||||
img->allocate(w, h, d);
|
||||
|
||||
if (hasAlpha())
|
||||
{
|
||||
@ -1416,7 +1412,7 @@ uint DirectDrawSurface::mipmapSize(uint mipmap) const
|
||||
// @@ How are 3D textures aligned?
|
||||
w = (w + 3) / 4;
|
||||
h = (h + 3) / 4;
|
||||
return blockSize() * w * h;
|
||||
return blockSize() * w * h * d;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -11,15 +11,15 @@ using namespace nv;
|
||||
|
||||
float nv::rmsColorError(const FloatImage * img, const FloatImage * ref, bool alphaWeight)
|
||||
{
|
||||
if (img == NULL || ref == NULL || img->width() != ref->width() || img->height() != ref->height()) {
|
||||
if (!sameLayout(img, ref)) {
|
||||
return FLT_MAX;
|
||||
}
|
||||
nvDebugCheck(img->componentNum() == 4);
|
||||
nvDebugCheck(ref->componentNum() == 4);
|
||||
nvDebugCheck(img->componentCount() == 4);
|
||||
nvDebugCheck(ref->componentCount() == 4);
|
||||
|
||||
double mse = 0;
|
||||
|
||||
const uint count = img->width() * img->height();
|
||||
const uint count = img->pixelCount();
|
||||
for (uint i = 0; i < count; i++)
|
||||
{
|
||||
float r0 = img->pixel(i + count * 0);
|
||||
@ -48,14 +48,14 @@ float nv::rmsColorError(const FloatImage * img, const FloatImage * ref, bool alp
|
||||
|
||||
float nv::rmsAlphaError(const FloatImage * img, const FloatImage * ref)
|
||||
{
|
||||
if (img == NULL || ref == NULL || img->width() != ref->width() || img->height() != ref->height()) {
|
||||
if (!sameLayout(img, ref)) {
|
||||
return FLT_MAX;
|
||||
}
|
||||
nvDebugCheck(img->componentNum() == 4 && ref->componentNum() == 4);
|
||||
nvDebugCheck(img->componentCount() == 4 && ref->componentCount() == 4);
|
||||
|
||||
double mse = 0;
|
||||
|
||||
const uint count = img->width() * img->height();
|
||||
const uint count = img->pixelCount();
|
||||
for (uint i = 0; i < count; i++)
|
||||
{
|
||||
float a0 = img->pixel(i + count * 3);
|
||||
@ -72,15 +72,15 @@ float nv::rmsAlphaError(const FloatImage * img, const FloatImage * ref)
|
||||
|
||||
float nv::averageColorError(const FloatImage * img, const FloatImage * ref, bool alphaWeight)
|
||||
{
|
||||
if (img == NULL || ref == NULL || img->width() != ref->width() || img->height() != ref->height()) {
|
||||
if (!sameLayout(img, ref)) {
|
||||
return FLT_MAX;
|
||||
}
|
||||
nvDebugCheck(img->componentNum() == 4);
|
||||
nvDebugCheck(ref->componentNum() == 4);
|
||||
nvDebugCheck(img->componentCount() == 4);
|
||||
nvDebugCheck(ref->componentCount() == 4);
|
||||
|
||||
double mae = 0;
|
||||
|
||||
const uint count = img->width() * img->height();
|
||||
const uint count = img->pixelCount();
|
||||
for (uint i = 0; i < count; i++)
|
||||
{
|
||||
float r0 = img->pixel(i + count * 0);
|
||||
@ -112,7 +112,7 @@ float nv::averageAlphaError(const FloatImage * img, const FloatImage * ref)
|
||||
if (img == NULL || ref == NULL || img->width() != ref->width() || img->height() != ref->height()) {
|
||||
return FLT_MAX;
|
||||
}
|
||||
nvDebugCheck(img->componentNum() == 4 && ref->componentNum() == 4);
|
||||
nvDebugCheck(img->componentCount() == 4 && ref->componentCount() == 4);
|
||||
|
||||
double mae = 0;
|
||||
|
||||
@ -227,7 +227,7 @@ static void rgbToCieLab(const FloatImage * rgbImage, FloatImage * LabImage)
|
||||
{
|
||||
nvDebugCheck(rgbImage != NULL && LabImage != NULL);
|
||||
nvDebugCheck(rgbImage->width() == LabImage->width() && rgbImage->height() == LabImage->height());
|
||||
nvDebugCheck(rgbImage->componentNum() >= 3 && LabImage->componentNum() >= 3);
|
||||
nvDebugCheck(rgbImage->componentCount() >= 3 && LabImage->componentCount() >= 3);
|
||||
|
||||
const uint w = rgbImage->width();
|
||||
const uint h = LabImage->height();
|
||||
@ -254,13 +254,8 @@ static void rgbToCieLab(const FloatImage * rgbImage, FloatImage * LabImage)
|
||||
// Assumes input images are in linear sRGB space.
|
||||
float nv::cieLabError(const FloatImage * img0, const FloatImage * img1)
|
||||
{
|
||||
if (img0 == NULL || img1 == NULL || img0->width() != img1->width() || img0->height() != img1->height()) {
|
||||
return FLT_MAX;
|
||||
}
|
||||
nvDebugCheck(img0->componentNum() == 4 && img0->componentNum() == 4);
|
||||
|
||||
uint w = img0->width();
|
||||
uint h = img0->height();
|
||||
if (!sameLayout(img0, img1)) return FLT_MAX;
|
||||
nvDebugCheck(img0->componentCount() == 4 && img0->componentCount() == 4);
|
||||
|
||||
const float * r0 = img0->channel(0);
|
||||
const float * g0 = img0->channel(1);
|
||||
@ -272,7 +267,7 @@ float nv::cieLabError(const FloatImage * img0, const FloatImage * img1)
|
||||
|
||||
double error = 0.0f;
|
||||
|
||||
const uint count = w*h;
|
||||
const uint count = img0->pixelCount();
|
||||
for (uint i = 0; i < count; i++)
|
||||
{
|
||||
Vector3 lab0 = rgbToCieLab(Vector3(r0[i], g0[i], b0[i]));
|
||||
@ -292,14 +287,15 @@ float nv::spatialCieLabError(const FloatImage * img0, const FloatImage * img1)
|
||||
if (img0 == NULL || img1 == NULL || img0->width() != img1->width() || img0->height() != img1->height()) {
|
||||
return FLT_MAX;
|
||||
}
|
||||
nvDebugCheck(img0->componentNum() == 4 && img0->componentNum() == 4);
|
||||
nvDebugCheck(img0->componentCount() == 4 && img0->componentCount() == 4);
|
||||
|
||||
uint w = img0->width();
|
||||
uint h = img0->height();
|
||||
uint d = img0->depth();
|
||||
|
||||
FloatImage lab0, lab1; // Original images in CIE-Lab space.
|
||||
lab0.allocate(3, w, h);
|
||||
lab1.allocate(3, w, h);
|
||||
lab0.allocate(3, w, h, d);
|
||||
lab1.allocate(3, w, h, d);
|
||||
|
||||
// Convert input images to CIE-Lab.
|
||||
rgbToCieLab(img0, &lab0);
|
||||
@ -331,7 +327,7 @@ float nv::averageAngularError(const FloatImage * img0, const FloatImage * img1)
|
||||
if (img0 == NULL || img1 == NULL || img0->width() != img1->width() || img0->height() != img1->height()) {
|
||||
return FLT_MAX;
|
||||
}
|
||||
nvDebugCheck(img0->componentNum() == 4 && img0->componentNum() == 4);
|
||||
nvDebugCheck(img0->componentCount() == 4 && img0->componentCount() == 4);
|
||||
|
||||
uint w = img0->width();
|
||||
uint h = img0->height();
|
||||
@ -369,7 +365,7 @@ float nv::rmsAngularError(const FloatImage * img0, const FloatImage * img1)
|
||||
if (img0 == NULL || img1 == NULL || img0->width() != img1->width() || img0->height() != img1->height()) {
|
||||
return FLT_MAX;
|
||||
}
|
||||
nvDebugCheck(img0->componentNum() == 4 && img0->componentNum() == 4);
|
||||
nvDebugCheck(img0->componentCount() == 4 && img0->componentCount() == 4);
|
||||
|
||||
uint w = img0->width();
|
||||
uint h = img0->height();
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -5,6 +5,8 @@
|
||||
|
||||
#include "nvimage.h"
|
||||
|
||||
#include "nvmath/nvmath.h" // lerp
|
||||
|
||||
#include "nvcore/Debug.h"
|
||||
#include "nvcore/Utils.h" // clamp
|
||||
|
||||
@ -45,7 +47,7 @@ namespace nv
|
||||
|
||||
/** @name Allocation. */
|
||||
//@{
|
||||
NVIMAGE_API void allocate(uint c, uint w, uint h);
|
||||
NVIMAGE_API void allocate(uint c, uint w, uint h, uint d = 1);
|
||||
NVIMAGE_API void free(); // Does not clear members.
|
||||
NVIMAGE_API void resizeChannelCount(uint c);
|
||||
//@}
|
||||
@ -74,21 +76,30 @@ namespace nv
|
||||
NVIMAGE_API FloatImage * downSample(const Filter & filter, WrapMode wm) const;
|
||||
NVIMAGE_API FloatImage * downSample(const Filter & filter, WrapMode wm, uint alpha) const;
|
||||
NVIMAGE_API FloatImage * resize(const Filter & filter, uint w, uint h, WrapMode wm) const;
|
||||
NVIMAGE_API FloatImage * resize(const Filter & filter, uint w, uint h, uint d, WrapMode wm) const;
|
||||
NVIMAGE_API FloatImage * resize(const Filter & filter, uint w, uint h, WrapMode wm, uint alpha) const;
|
||||
NVIMAGE_API FloatImage * resize(const Filter & filter, uint w, uint h, uint d, WrapMode wm, uint alpha) const;
|
||||
|
||||
|
||||
//NVIMAGE_API FloatImage * downSample(const Kernel1 & filter, WrapMode wm) const;
|
||||
//NVIMAGE_API FloatImage * downSample(const Kernel1 & filter, uint w, uint h, WrapMode wm) const;
|
||||
//@}
|
||||
|
||||
NVIMAGE_API float applyKernel(const Kernel2 * k, int x, int y, uint c, WrapMode wm) const;
|
||||
NVIMAGE_API float applyKernelVertical(const Kernel1 * k, int x, int y, uint c, WrapMode wm) const;
|
||||
NVIMAGE_API float applyKernelHorizontal(const Kernel1 * k, int x, int y, uint c, WrapMode wm) const;
|
||||
NVIMAGE_API void applyKernelVertical(const PolyphaseKernel & k, int x, uint c, WrapMode wm, float * output) const;
|
||||
NVIMAGE_API void applyKernelHorizontal(const PolyphaseKernel & k, int y, uint c, WrapMode wm, float * output) const;
|
||||
NVIMAGE_API void applyKernelVertical(const PolyphaseKernel & k, int x, uint c, uint a, WrapMode wm, float * output) const;
|
||||
NVIMAGE_API void applyKernelHorizontal(const PolyphaseKernel & k, int y, uint c, uint a, WrapMode wm, float * output) const;
|
||||
NVIMAGE_API float applyKernelXY(const Kernel2 * k, int x, int y, int z, uint c, WrapMode wm) const;
|
||||
NVIMAGE_API float applyKernelX(const Kernel1 * k, int x, int y, int z, uint c, WrapMode wm) const;
|
||||
NVIMAGE_API float applyKernelY(const Kernel1 * k, int x, int y, int z, uint c, WrapMode wm) const;
|
||||
NVIMAGE_API float applyKernelZ(const Kernel1 * k, int x, int y, int z, uint c, WrapMode wm) const;
|
||||
NVIMAGE_API void applyKernelX(const PolyphaseKernel & k, int y, int z, uint c, WrapMode wm, float * output) const;
|
||||
NVIMAGE_API void applyKernelY(const PolyphaseKernel & k, int x, int z, uint c, WrapMode wm, float * output) const;
|
||||
NVIMAGE_API void applyKernelZ(const PolyphaseKernel & k, int x, int y, uint c, WrapMode wm, float * output) const;
|
||||
NVIMAGE_API void applyKernelX(const PolyphaseKernel & k, int y, int z, uint c, uint a, WrapMode wm, float * output) const;
|
||||
NVIMAGE_API void applyKernelY(const PolyphaseKernel & k, int x, int z, uint c, uint a, WrapMode wm, float * output) const;
|
||||
NVIMAGE_API void applyKernelZ(const PolyphaseKernel & k, int x, int y, uint c, uint a, WrapMode wm, float * output) const;
|
||||
|
||||
NVIMAGE_API void flip();
|
||||
|
||||
NVIMAGE_API void flipX();
|
||||
NVIMAGE_API void flipY();
|
||||
NVIMAGE_API void flipZ();
|
||||
|
||||
NVIMAGE_API float alphaTestCoverage(float alphaRef, int alphaChannel) const;
|
||||
NVIMAGE_API void scaleAlphaToCoverage(float coverage, float alphaRef, int alphaChannel);
|
||||
@ -96,37 +107,58 @@ namespace nv
|
||||
|
||||
uint width() const { return m_width; }
|
||||
uint height() const { return m_height; }
|
||||
uint componentNum() const { return m_componentNum; }
|
||||
uint count() const { return m_count; }
|
||||
uint depth() const { return m_depth; }
|
||||
uint componentCount() const { return m_componentCount; }
|
||||
uint floatCount() const { return m_floatCount; }
|
||||
uint pixelCount() const { return m_pixelCount; }
|
||||
|
||||
|
||||
// @@ It would make sense to swap the order of the arguments so that 'c' is always first.
|
||||
|
||||
/** @name Pixel access. */
|
||||
//@{
|
||||
const float * channel(uint c) const;
|
||||
float * channel(uint c);
|
||||
|
||||
const float * scanline(uint y, uint c) const;
|
||||
float * scanline(uint y, uint c);
|
||||
const float * plane(uint c, uint z) const;
|
||||
float * plane(uint c, uint z);
|
||||
|
||||
float pixel(uint x, uint y, uint c) const;
|
||||
float & pixel(uint x, uint y, uint c);
|
||||
const float * scanline(uint c, uint y, uint z) const;
|
||||
float * scanline(uint c, uint y, uint z);
|
||||
|
||||
float pixel(uint idx, uint c) const;
|
||||
float & pixel(uint idx, uint c);
|
||||
//float pixel(uint c, uint x, uint y) const;
|
||||
//float & pixel(uint c, uint x, uint y);
|
||||
|
||||
float pixel(uint c, uint x, uint y, uint z) const;
|
||||
float & pixel(uint c, uint x, uint y, uint z);
|
||||
|
||||
float pixel(uint c, uint idx) const;
|
||||
float & pixel(uint c, uint idx);
|
||||
|
||||
float pixel(uint idx) const;
|
||||
float & pixel(uint idx);
|
||||
|
||||
float sampleNearest(float x, float y, int c, WrapMode wm) const;
|
||||
float sampleLinear(float x, float y, int c, WrapMode wm) const;
|
||||
float sampleNearest(uint c, float x, float y, WrapMode wm) const;
|
||||
float sampleLinear(uint c, float x, float y, WrapMode wm) const;
|
||||
|
||||
float sampleNearestClamp(float x, float y, int c) const;
|
||||
float sampleNearestRepeat(float x, float y, int c) const;
|
||||
float sampleNearestMirror(float x, float y, int c) const;
|
||||
float sampleNearest(uint c, float x, float y, float z, WrapMode wm) const;
|
||||
float sampleLinear(uint c, float x, float y, float z, WrapMode wm) const;
|
||||
|
||||
float sampleLinearClamp(float x, float y, int c) const;
|
||||
float sampleLinearRepeat(float x, float y, int c) const;
|
||||
float sampleLinearMirror(float x, float y, int c) const;
|
||||
float sampleNearestClamp(uint c, float x, float y) const;
|
||||
float sampleNearestRepeat(uint c, float x, float y) const;
|
||||
float sampleNearestMirror(uint c, float x, float y) const;
|
||||
|
||||
float sampleNearestClamp(uint c, float x, float y, float z) const;
|
||||
float sampleNearestRepeat(uint c, float x, float y, float z) const;
|
||||
float sampleNearestMirror(uint c, float x, float y, float z) const;
|
||||
|
||||
float sampleLinearClamp(uint c, float x, float y) const;
|
||||
float sampleLinearRepeat(uint c, float x, float y) const;
|
||||
float sampleLinearMirror(uint c, float x, float y) const;
|
||||
|
||||
float sampleLinearClamp(uint c, float x, float y, float z) const;
|
||||
float sampleLinearRepeat(uint c, float x, float y, float z) const;
|
||||
float sampleLinearMirror(uint c, float x, float y, float z) const;
|
||||
//@}
|
||||
|
||||
|
||||
@ -134,18 +166,23 @@ namespace nv
|
||||
|
||||
public:
|
||||
|
||||
uint index(uint x, uint y) const;
|
||||
uint indexClamp(int x, int y) const;
|
||||
uint indexRepeat(int x, int y) const;
|
||||
uint indexMirror(int x, int y) const;
|
||||
uint index(int x, int y, WrapMode wm) const;
|
||||
uint index(uint x, uint y, uint z) const;
|
||||
uint indexClamp(int x, int y, int z) const;
|
||||
uint indexRepeat(int x, int y, int z) const;
|
||||
uint indexMirror(int x, int y, int z) const;
|
||||
uint index(int x, int y, int z, WrapMode wm) const;
|
||||
|
||||
float bilerp(uint c, int ix0, int iy0, int ix1, int iy1, float fx, float fy) const;
|
||||
float trilerp(uint c, int ix0, int iy0, int iz0, int ix1, int iy1, int iz1, float fx, float fy, float fz) const;
|
||||
|
||||
public:
|
||||
|
||||
uint16 m_width; ///< Width of the texture.
|
||||
uint16 m_height; ///< Height of the texture.
|
||||
uint32 m_componentNum; ///< Number of components.
|
||||
uint32 m_count; ///< Image pixel count.
|
||||
uint16 m_componentCount;
|
||||
uint16 m_width;
|
||||
uint16 m_height;
|
||||
uint16 m_depth;
|
||||
uint32 m_pixelCount;
|
||||
uint32 m_floatCount;
|
||||
float * m_mem;
|
||||
|
||||
};
|
||||
@ -155,132 +192,202 @@ namespace nv
|
||||
inline const float * FloatImage::channel(uint c) const
|
||||
{
|
||||
nvDebugCheck(m_mem != NULL);
|
||||
nvDebugCheck(c < m_componentNum);
|
||||
return m_mem + c * m_width * m_height;
|
||||
nvDebugCheck(c < m_componentCount);
|
||||
return m_mem + c * m_pixelCount;
|
||||
}
|
||||
|
||||
/// Get channel pointer.
|
||||
inline float * FloatImage::channel(uint c) {
|
||||
nvDebugCheck(m_mem != NULL);
|
||||
nvDebugCheck(c < m_componentNum);
|
||||
return m_mem + c * m_width * m_height;
|
||||
nvDebugCheck(c < m_componentCount);
|
||||
return m_mem + c * m_pixelCount;
|
||||
}
|
||||
|
||||
inline const float * FloatImage::plane(uint c, uint z) const {
|
||||
nvDebugCheck(z < m_depth);
|
||||
return channel(c) + z * m_width * m_height;
|
||||
}
|
||||
|
||||
inline float * FloatImage::plane(uint c, uint z) {
|
||||
nvDebugCheck(z < m_depth);
|
||||
return channel(c) + z * m_width * m_height;
|
||||
}
|
||||
|
||||
/// Get const scanline pointer.
|
||||
inline const float * FloatImage::scanline(uint y, uint c) const
|
||||
inline const float * FloatImage::scanline(uint c, uint y, uint z) const
|
||||
{
|
||||
nvDebugCheck(y < m_height);
|
||||
return channel(c) + y * m_width;
|
||||
return plane(c, z) + y * m_width;
|
||||
}
|
||||
|
||||
/// Get scanline pointer.
|
||||
inline float * FloatImage::scanline(uint y, uint c)
|
||||
inline float * FloatImage::scanline(uint z, uint y, uint c)
|
||||
{
|
||||
nvDebugCheck(y < m_height);
|
||||
return channel(c) + y * m_width;
|
||||
return plane(c, z) + y * m_width;
|
||||
}
|
||||
|
||||
/// Get pixel component.
|
||||
inline float FloatImage::pixel(uint x, uint y, uint c) const
|
||||
inline float FloatImage::pixel(uint c, uint x, uint y, uint z) const
|
||||
{
|
||||
nvDebugCheck(m_mem != NULL);
|
||||
nvDebugCheck(c < m_componentCount);
|
||||
nvDebugCheck(x < m_width);
|
||||
nvDebugCheck(y < m_height);
|
||||
nvDebugCheck(c < m_componentNum);
|
||||
return m_mem[(c * m_height + y) * m_width + x];
|
||||
nvDebugCheck(z < m_depth);
|
||||
return m_mem[((c * m_depth + z) * m_height + y) * m_width + x];
|
||||
}
|
||||
|
||||
/// Get pixel component.
|
||||
inline float & FloatImage::pixel(uint x, uint y, uint c)
|
||||
inline float & FloatImage::pixel(uint c, uint x, uint y, uint z)
|
||||
{
|
||||
nvDebugCheck(m_mem != NULL);
|
||||
nvDebugCheck(c < m_componentCount);
|
||||
nvDebugCheck(x < m_width);
|
||||
nvDebugCheck(y < m_height);
|
||||
nvDebugCheck(c < m_componentNum);
|
||||
return m_mem[(c * m_height + y) * m_width + x];
|
||||
nvDebugCheck(z < m_depth);
|
||||
return m_mem[((c * m_depth + z) * m_height + y) * m_width + x];
|
||||
}
|
||||
|
||||
/// Get pixel component.
|
||||
inline float FloatImage::pixel(uint idx, uint c) const
|
||||
inline float FloatImage::pixel(uint c, uint idx) const
|
||||
{
|
||||
nvDebugCheck(m_mem != NULL);
|
||||
nvDebugCheck(idx < uint(m_width*m_height));
|
||||
nvDebugCheck(c < m_componentNum);
|
||||
nvDebugCheck(c < m_componentCount);
|
||||
nvDebugCheck(idx < m_pixelCount);
|
||||
return m_mem[c * m_height * m_width + idx];
|
||||
}
|
||||
|
||||
/// Get pixel component.
|
||||
inline float & FloatImage::pixel(uint idx, uint c)
|
||||
inline float & FloatImage::pixel(uint c, uint idx)
|
||||
{
|
||||
nvDebugCheck(m_mem != NULL);
|
||||
nvDebugCheck(idx < uint(m_width*m_height));
|
||||
nvDebugCheck(c < m_componentNum);
|
||||
nvDebugCheck(c < m_componentCount);
|
||||
nvDebugCheck(idx < m_pixelCount);
|
||||
return m_mem[c * m_height * m_width + idx];
|
||||
}
|
||||
|
||||
/// Get pixel component.
|
||||
inline float FloatImage::pixel(uint idx) const
|
||||
{
|
||||
nvDebugCheck(idx < m_count);
|
||||
nvDebugCheck(m_mem != NULL);
|
||||
nvDebugCheck(idx < m_floatCount);
|
||||
return m_mem[idx];
|
||||
}
|
||||
|
||||
/// Get pixel component.
|
||||
inline float & FloatImage::pixel(uint idx)
|
||||
{
|
||||
nvDebugCheck(idx < m_count);
|
||||
nvDebugCheck(m_mem != NULL);
|
||||
nvDebugCheck(idx < m_floatCount);
|
||||
return m_mem[idx];
|
||||
}
|
||||
|
||||
inline uint FloatImage::index(uint x, uint y) const
|
||||
inline uint FloatImage::index(uint x, uint y, uint z) const
|
||||
{
|
||||
nvDebugCheck(x < m_width);
|
||||
nvDebugCheck(y < m_height);
|
||||
return y * m_width + x;
|
||||
nvDebugCheck(z < m_depth);
|
||||
return (z * m_height + y) * m_width + x;
|
||||
}
|
||||
|
||||
inline uint FloatImage::indexClamp(int x, int y) const
|
||||
{
|
||||
return nv::clamp(y, int(0), int(m_height-1)) * m_width + nv::clamp(x, int(0), int(m_width-1));
|
||||
}
|
||||
|
||||
inline int repeat_remainder(int a, int b)
|
||||
inline int wrapClamp(int x, int w)
|
||||
{
|
||||
if (a >= 0) return a % b;
|
||||
else return (a + 1) % b + b - 1;
|
||||
return nv::clamp(x, 0, w - 1);
|
||||
}
|
||||
|
||||
inline uint FloatImage::indexRepeat(int x, int y) const
|
||||
inline int wrapRepeat(int x, int w)
|
||||
{
|
||||
return repeat_remainder(y, m_height) * m_width + repeat_remainder(x, m_width);
|
||||
if (x >= 0) return x % w;
|
||||
else return (x + 1) % w + w - 1;
|
||||
}
|
||||
|
||||
inline uint FloatImage::indexMirror(int x, int y) const
|
||||
inline int wrapMirror(int x, int w)
|
||||
{
|
||||
if (m_width == 1) x = 0;
|
||||
if (w == 1) x = 0;
|
||||
|
||||
x = abs(x);
|
||||
while (x >= m_width) {
|
||||
x = abs(m_width + m_width - x - 2);
|
||||
while (x >= w) {
|
||||
x = abs(w + w - x - 2);
|
||||
}
|
||||
|
||||
if (m_height == 1) y = 0;
|
||||
|
||||
y = abs(y);
|
||||
while (y >= m_height) {
|
||||
y = abs(m_height + m_height - y - 2);
|
||||
}
|
||||
|
||||
return index(x, y);
|
||||
return x;
|
||||
}
|
||||
|
||||
inline uint FloatImage::index(int x, int y, WrapMode wm) const
|
||||
|
||||
|
||||
inline uint FloatImage::indexClamp(int x, int y, int z) const
|
||||
{
|
||||
if (wm == WrapMode_Clamp) return indexClamp(x, y);
|
||||
if (wm == WrapMode_Repeat) return indexRepeat(x, y);
|
||||
/*if (wm == WrapMode_Mirror)*/ return indexMirror(x, y);
|
||||
x = wrapClamp(x, m_width - 1);
|
||||
y = wrapClamp(y, m_height - 1);
|
||||
z = wrapClamp(z, m_depth - 1);
|
||||
return index(x, y, z);
|
||||
}
|
||||
|
||||
|
||||
inline uint FloatImage::indexRepeat(int x, int y, int z) const
|
||||
{
|
||||
x = wrapRepeat(x, m_width);
|
||||
y = wrapRepeat(y, m_height);
|
||||
z = wrapRepeat(z, m_depth);
|
||||
return index(x, y, z);
|
||||
}
|
||||
|
||||
inline uint FloatImage::indexMirror(int x, int y, int z) const
|
||||
{
|
||||
x = wrapMirror(x, m_width);
|
||||
y = wrapMirror(y, m_height);
|
||||
z = wrapMirror(z, m_depth);
|
||||
return index(x, y, z);
|
||||
}
|
||||
|
||||
inline uint FloatImage::index(int x, int y, int z, WrapMode wm) const
|
||||
{
|
||||
if (wm == WrapMode_Clamp) return indexClamp(x, y, z);
|
||||
if (wm == WrapMode_Repeat) return indexRepeat(x, y, z);
|
||||
/*if (wm == WrapMode_Mirror)*/ return indexMirror(x, y, z);
|
||||
}
|
||||
|
||||
inline float FloatImage::bilerp(uint c, int ix0, int iy0, int ix1, int iy1, float fx, float fy) const {
|
||||
int iz = 0;
|
||||
float f1 = pixel(c, ix0, iy0, iz);
|
||||
float f2 = pixel(c, ix1, iy0, iz);
|
||||
float f3 = pixel(c, ix0, iy1, iz);
|
||||
float f4 = pixel(c, ix1, iy1, iz);
|
||||
|
||||
float i1 = lerp(f1, f2, fx);
|
||||
float i2 = lerp(f3, f4, fx);
|
||||
|
||||
return lerp(i1, i2, fy);
|
||||
}
|
||||
|
||||
inline float FloatImage::trilerp(uint c, int ix0, int iy0, int iz0, int ix1, int iy1, int iz1, float fx, float fy, float fz) const {
|
||||
float f000 = pixel(c, ix0, iy0, iz0);
|
||||
float f100 = pixel(c, ix1, iy0, iz0);
|
||||
float f010 = pixel(c, ix0, iy1, iz0);
|
||||
float f110 = pixel(c, ix1, iy1, iz0);
|
||||
float f001 = pixel(c, ix0, iy0, iz1);
|
||||
float f101 = pixel(c, ix1, iy0, iz1);
|
||||
float f011 = pixel(c, ix0, iy1, iz1);
|
||||
float f111 = pixel(c, ix1, iy1, iz1);
|
||||
|
||||
float i1 = lerp(f000, f001, fz);
|
||||
float i2 = lerp(f010, f011, fz);
|
||||
float j1 = lerp(f100, f101, fz);
|
||||
float j2 = lerp(f110, f111, fz);
|
||||
|
||||
float w1 = lerp(i1, i2, fy);
|
||||
float w2 = lerp(j1, j2, fy);
|
||||
|
||||
return lerp(w1, w2, fx);
|
||||
}
|
||||
|
||||
// Does not compare channel count.
|
||||
inline bool sameLayout(const FloatImage * img0, const FloatImage * img1) {
|
||||
if (img0 == NULL || img1 == NULL) return false;
|
||||
return img0->width() == img1->width() && img0->height() == img1->height() && img0->depth() == img1->depth();
|
||||
}
|
||||
|
||||
|
||||
} // nv namespace
|
||||
|
||||
|
||||
|
@ -18,9 +18,9 @@ Image::Image() : m_width(0), m_height(0), m_format(Format_RGB), m_data(NULL)
|
||||
|
||||
Image::Image(const Image & img) : m_data(NULL)
|
||||
{
|
||||
allocate(img.m_width, img.m_height);
|
||||
allocate(img.m_width, img.m_height, img.m_depth);
|
||||
m_format = img.m_format;
|
||||
memcpy(m_data, img.m_data, sizeof(Color32) * m_width * m_height);
|
||||
memcpy(m_data, img.m_data, sizeof(Color32) * m_width * m_height * m_depth);
|
||||
}
|
||||
|
||||
Image::~Image()
|
||||
@ -30,19 +30,20 @@ Image::~Image()
|
||||
|
||||
const Image & Image::operator=(const Image & img)
|
||||
{
|
||||
allocate(img.m_width, img.m_height);
|
||||
allocate(img.m_width, img.m_height, m_depth);
|
||||
m_format = img.m_format;
|
||||
memcpy(m_data, img.m_data, sizeof(Color32) * m_width * m_height);
|
||||
memcpy(m_data, img.m_data, sizeof(Color32) * m_width * m_height * m_depth);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
void Image::allocate(uint w, uint h)
|
||||
void Image::allocate(uint w, uint h, uint d)
|
||||
{
|
||||
free();
|
||||
m_width = w;
|
||||
m_height = h;
|
||||
m_data = realloc<Color32>(m_data, w * h);
|
||||
m_depth = d;
|
||||
m_data = realloc<Color32>(m_data, w * h * d);
|
||||
}
|
||||
|
||||
bool Image::load(const char * name)
|
||||
@ -56,18 +57,20 @@ bool Image::load(const char * name)
|
||||
|
||||
swap(m_width, img->m_width);
|
||||
swap(m_height, img->m_height);
|
||||
swap(m_depth, img->m_depth);
|
||||
swap(m_format, img->m_format);
|
||||
swap(m_data, img->m_data);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Image::wrap(void * data, uint w, uint h)
|
||||
void Image::wrap(void * data, uint w, uint h, uint d)
|
||||
{
|
||||
free();
|
||||
m_data = (Color32 *)data;
|
||||
m_width = w;
|
||||
m_height = h;
|
||||
m_depth = d;
|
||||
}
|
||||
|
||||
void Image::unwrap()
|
||||
@ -75,6 +78,7 @@ void Image::unwrap()
|
||||
m_data = NULL;
|
||||
m_width = 0;
|
||||
m_height = 0;
|
||||
m_depth = 0;
|
||||
}
|
||||
|
||||
|
||||
@ -95,6 +99,11 @@ uint Image::height() const
|
||||
return m_height;
|
||||
}
|
||||
|
||||
uint Image::depth() const
|
||||
{
|
||||
return m_depth;
|
||||
}
|
||||
|
||||
const Color32 * Image::scanline(uint h) const
|
||||
{
|
||||
nvDebugCheck(h < m_height);
|
||||
@ -119,13 +128,13 @@ Color32 * Image::pixels()
|
||||
|
||||
const Color32 & Image::pixel(uint idx) const
|
||||
{
|
||||
nvDebugCheck(idx < m_width * m_height);
|
||||
nvDebugCheck(idx < m_width * m_height * m_depth);
|
||||
return m_data[idx];
|
||||
}
|
||||
|
||||
Color32 & Image::pixel(uint idx)
|
||||
{
|
||||
nvDebugCheck(idx < m_width * m_height);
|
||||
nvDebugCheck(idx < m_width * m_height * m_depth);
|
||||
return m_data[idx];
|
||||
}
|
||||
|
||||
@ -142,7 +151,7 @@ void Image::setFormat(Image::Format f)
|
||||
|
||||
void Image::fill(Color32 c)
|
||||
{
|
||||
const uint size = m_width * m_height;
|
||||
const uint size = m_width * m_height * m_depth;
|
||||
for (uint i = 0; i < size; ++i)
|
||||
{
|
||||
m_data[i] = c;
|
||||
|
@ -29,14 +29,15 @@ namespace nv
|
||||
const Image & operator=(const Image & img);
|
||||
|
||||
|
||||
void allocate(uint w, uint h);
|
||||
void allocate(uint w, uint h, uint d = 1);
|
||||
bool load(const char * name);
|
||||
|
||||
void wrap(void * data, uint w, uint h);
|
||||
void wrap(void * data, uint w, uint h, uint d = 1);
|
||||
void unwrap();
|
||||
|
||||
uint width() const;
|
||||
uint height() const;
|
||||
uint depth() const;
|
||||
|
||||
const Color32 * scanline(uint h) const;
|
||||
Color32 * scanline(uint h);
|
||||
@ -61,6 +62,7 @@ namespace nv
|
||||
private:
|
||||
uint m_width;
|
||||
uint m_height;
|
||||
uint m_depth;
|
||||
Format m_format;
|
||||
Color32 * m_data;
|
||||
};
|
||||
|
@ -275,9 +275,9 @@ bool nv::ImageIO::saveFloat(const char * fileName, Stream & s, const FloatImage
|
||||
{
|
||||
if (componentCount == 0)
|
||||
{
|
||||
componentCount = fimage->componentNum() - baseComponent;
|
||||
componentCount = fimage->componentCount() - baseComponent;
|
||||
}
|
||||
if (baseComponent + componentCount < fimage->componentNum())
|
||||
if (baseComponent + componentCount < fimage->componentCount())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -430,7 +430,7 @@ Image * nv::ImageIO::loadFreeImage(FREE_IMAGE_FORMAT fif, Stream & s)
|
||||
|
||||
|
||||
Image * image = new Image();
|
||||
image->allocate(w, h);
|
||||
image->allocate(w, h, 1); // freeimage can only load 2d images:
|
||||
|
||||
// Copy the image over to our internal format, FreeImage has the scanlines bottom to top though.
|
||||
for (int y=0; y < h; y++)
|
||||
@ -1575,7 +1575,7 @@ bool nv::ImageIO::saveFloatTIFF(const char * fileName, const FloatImage * fimage
|
||||
{
|
||||
nvCheck(fileName != NULL);
|
||||
nvCheck(fimage != NULL);
|
||||
nvCheck(base_component + num_components <= fimage->componentNum());
|
||||
nvCheck(base_component + num_components <= fimage->componentCount());
|
||||
|
||||
const int iW = fimage->width();
|
||||
const int iH = fimage->height();
|
||||
@ -1740,7 +1740,7 @@ bool nv::ImageIO::saveFloatEXR(const char * fileName, const FloatImage * fimage,
|
||||
{
|
||||
nvCheck(fileName != NULL);
|
||||
nvCheck(fimage != NULL);
|
||||
nvCheck(base_component + num_components <= fimage->componentNum());
|
||||
nvCheck(base_component + num_components <= fimage->componentCount());
|
||||
nvCheck(num_components > 0 && num_components <= 4);
|
||||
|
||||
const int w = fimage->width();
|
||||
|
@ -36,172 +36,172 @@ 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)
|
||||
{
|
||||
nvDebugCheck(kdu != NULL);
|
||||
nvDebugCheck(kdv != NULL);
|
||||
nvDebugCheck(img != NULL);
|
||||
|
||||
const uint w = img->width();
|
||||
const uint h = img->height();
|
||||
|
||||
AutoPtr<FloatImage> fimage(new FloatImage());
|
||||
fimage->allocate(4, w, h);
|
||||
|
||||
// Compute height and store in alpha channel:
|
||||
float * alphaChannel = fimage->channel(3);
|
||||
for(uint i = 0; i < w*h; i++)
|
||||
{
|
||||
Vector4 color = toVector4(img->pixel(i));
|
||||
alphaChannel[i] = dot(color, heightWeights);
|
||||
}
|
||||
|
||||
float heightScale = 1.0f / 16.0f; // @@ Use a user defined factor.
|
||||
|
||||
for(uint y = 0; y < h; y++)
|
||||
{
|
||||
for(uint x = 0; x < w; x++)
|
||||
{
|
||||
const float du = fimage->applyKernel(kdu, x, y, 3, wm);
|
||||
const float dv = fimage->applyKernel(kdv, x, y, 3, wm);
|
||||
|
||||
Vector3 n = normalize(Vector3(du, dv, heightScale));
|
||||
|
||||
fimage->pixel(x, y, 0) = 0.5f * n.x + 0.5f;
|
||||
fimage->pixel(x, y, 1) = 0.5f * n.y + 0.5f;
|
||||
fimage->pixel(x, y, 2) = 0.5f * n.z + 0.5f;
|
||||
}
|
||||
}
|
||||
|
||||
return fimage.release();
|
||||
nvDebugCheck(kdu != NULL);
|
||||
nvDebugCheck(kdv != NULL);
|
||||
nvDebugCheck(img != NULL);
|
||||
|
||||
const uint w = img->width();
|
||||
const uint h = img->height();
|
||||
|
||||
AutoPtr<FloatImage> fimage(new FloatImage());
|
||||
fimage->allocate(4, w, h);
|
||||
|
||||
// Compute height and store in alpha channel:
|
||||
float * alphaChannel = fimage->channel(3);
|
||||
for(uint i = 0; i < w * h; i++)
|
||||
{
|
||||
Vector4 color = toVector4(img->pixel(i));
|
||||
alphaChannel[i] = dot(color, heightWeights);
|
||||
}
|
||||
|
||||
float heightScale = 1.0f / 16.0f; // @@ Use a user defined factor.
|
||||
|
||||
for(uint y = 0; y < h; y++)
|
||||
{
|
||||
for(uint x = 0; x < w; x++)
|
||||
{
|
||||
const float du = fimage->applyKernelXY(kdu, x, y, 0, 3, wm);
|
||||
const float dv = fimage->applyKernelXY(kdv, x, y, 0, 3, wm);
|
||||
|
||||
Vector3 n = normalize(Vector3(du, dv, heightScale));
|
||||
|
||||
fimage->pixel(x, y, 0, 0) = 0.5f * n.x + 0.5f;
|
||||
fimage->pixel(x, y, 0, 1) = 0.5f * n.y + 0.5f;
|
||||
fimage->pixel(x, y, 0, 2) = 0.5f * n.z + 0.5f;
|
||||
}
|
||||
}
|
||||
|
||||
return fimage.release();
|
||||
}
|
||||
|
||||
|
||||
// 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);
|
||||
nvDebugCheck(kdu != NULL);
|
||||
nvDebugCheck(kdv != NULL);
|
||||
nvDebugCheck(img != NULL);
|
||||
|
||||
#pragma NV_MESSAGE("FIXME: 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 float heightScale = 1.0f / 16.0f;
|
||||
|
||||
const uint w = img->width();
|
||||
const uint h = img->height();
|
||||
const uint w = img->width();
|
||||
const uint h = img->height();
|
||||
|
||||
AutoPtr<FloatImage> img_out(new FloatImage());
|
||||
img_out->allocate(4, w, h);
|
||||
AutoPtr<FloatImage> 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);
|
||||
for (uint y = 0; y < h; y++)
|
||||
{
|
||||
for (uint x = 0; x < w; x++)
|
||||
{
|
||||
const float du = img->applyKernelXY(kdu, x, y, 0, 3, wm);
|
||||
const float dv = img->applyKernelXY(kdv, x, y, 0, 3, wm);
|
||||
|
||||
Vector3 n = normalize(Vector3(du, dv, heightScale));
|
||||
Vector3 n = normalize(Vector3(du, dv, heightScale));
|
||||
|
||||
img_out->pixel(x, y, 0) = n.x;
|
||||
img_out->pixel(x, y, 1) = n.y;
|
||||
img_out->pixel(x, y, 2) = n.z;
|
||||
}
|
||||
img_out->pixel(x, y, 0, 0) = n.x;
|
||||
img_out->pixel(x, y, 0, 1) = n.y;
|
||||
img_out->pixel(x, y, 0, 2) = n.z;
|
||||
}
|
||||
}
|
||||
|
||||
// Copy alpha channel.
|
||||
for (uint y = 0; y < h; y++)
|
||||
{
|
||||
for (uint x = 0; x < w; x++)
|
||||
{
|
||||
img_out->pixel(x, y, 3) = img->pixel(x, y, 3);
|
||||
}
|
||||
}
|
||||
// Copy alpha channel.
|
||||
for (uint y = 0; y < h; y++)
|
||||
{
|
||||
for (uint x = 0; x < w; x++)
|
||||
{
|
||||
img_out->pixel(x, y, 0, 3) = img->pixel(x, y, 0, 3);
|
||||
}
|
||||
}
|
||||
|
||||
return img_out.release();
|
||||
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*/)
|
||||
{
|
||||
nvDebugCheck(img != NULL);
|
||||
|
||||
// Init the kernels.
|
||||
Kernel2 * kdu = NULL;
|
||||
Kernel2 * kdv = NULL;
|
||||
nvDebugCheck(img != NULL);
|
||||
|
||||
switch(filter)
|
||||
{
|
||||
case NormalMapFilter_Sobel3x3:
|
||||
kdu = new Kernel2(3);
|
||||
break;
|
||||
case NormalMapFilter_Sobel5x5:
|
||||
kdu = new Kernel2(5);
|
||||
break;
|
||||
case NormalMapFilter_Sobel7x7:
|
||||
kdu = new Kernel2(7);
|
||||
break;
|
||||
case NormalMapFilter_Sobel9x9:
|
||||
kdu = new Kernel2(9);
|
||||
break;
|
||||
default:
|
||||
nvDebugCheck(false);
|
||||
};
|
||||
// Init the kernels.
|
||||
Kernel2 * kdu = NULL;
|
||||
Kernel2 * kdv = NULL;
|
||||
|
||||
kdu->initSobel();
|
||||
kdu->normalize();
|
||||
switch(filter)
|
||||
{
|
||||
case NormalMapFilter_Sobel3x3:
|
||||
kdu = new Kernel2(3);
|
||||
break;
|
||||
case NormalMapFilter_Sobel5x5:
|
||||
kdu = new Kernel2(5);
|
||||
break;
|
||||
case NormalMapFilter_Sobel7x7:
|
||||
kdu = new Kernel2(7);
|
||||
break;
|
||||
case NormalMapFilter_Sobel9x9:
|
||||
kdu = new Kernel2(9);
|
||||
break;
|
||||
default:
|
||||
nvDebugCheck(false);
|
||||
};
|
||||
|
||||
kdv = new Kernel2(*kdu);
|
||||
kdv->transpose();
|
||||
kdu->initSobel();
|
||||
kdu->normalize();
|
||||
|
||||
return ::createNormalMap(img, wm, heightWeights, kdu, kdv);
|
||||
kdv = new Kernel2(*kdu);
|
||||
kdv->transpose();
|
||||
|
||||
return ::createNormalMap(img, wm, heightWeights, kdu, kdv);
|
||||
}
|
||||
|
||||
|
||||
/// Create normal map combining multiple sobel filters.
|
||||
FloatImage * nv::createNormalMap(const Image * img, FloatImage::WrapMode wm, Vector4::Arg heightWeights, Vector4::Arg filterWeights)
|
||||
{
|
||||
nvDebugCheck(img != NULL);
|
||||
nvDebugCheck(img != NULL);
|
||||
|
||||
Kernel2 * kdu = NULL;
|
||||
Kernel2 * kdv = 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, heightWeights, kdu, kdv);
|
||||
kdu = new Kernel2(9);
|
||||
kdu->initBlendedSobel(filterWeights);
|
||||
kdu->normalize();
|
||||
|
||||
kdv = new Kernel2(*kdu);
|
||||
kdv->transpose();
|
||||
|
||||
return ::createNormalMap(img, wm, heightWeights, kdu, kdv);
|
||||
}
|
||||
|
||||
|
||||
FloatImage * nv::createNormalMap(const FloatImage * img, FloatImage::WrapMode wm, Vector4::Arg filterWeights)
|
||||
{
|
||||
nvDebugCheck(img != NULL);
|
||||
nvDebugCheck(img != NULL);
|
||||
|
||||
Kernel2 * kdu = NULL;
|
||||
Kernel2 * kdv = NULL;
|
||||
Kernel2 * kdu = NULL;
|
||||
Kernel2 * kdv = NULL;
|
||||
|
||||
kdu = new Kernel2(9);
|
||||
kdu->initBlendedSobel(filterWeights);
|
||||
kdu->normalize();
|
||||
kdu = new Kernel2(9);
|
||||
kdu->initBlendedSobel(filterWeights);
|
||||
kdu->normalize();
|
||||
|
||||
kdv = new Kernel2(*kdu);
|
||||
kdv->transpose();
|
||||
kdv = new Kernel2(*kdu);
|
||||
kdv->transpose();
|
||||
|
||||
return ::createNormalMap(img, wm, kdu, kdv);
|
||||
return ::createNormalMap(img, wm, kdu, kdv);
|
||||
}
|
||||
|
||||
|
||||
/// Normalize the given image in place.
|
||||
void nv::normalizeNormalMap(FloatImage * img)
|
||||
{
|
||||
nvDebugCheck(img != NULL);
|
||||
nvDebugCheck(img != NULL);
|
||||
|
||||
#pragma NV_MESSAGE("TODO: Pack and expand normals explicitly?")
|
||||
|
||||
img->expandNormals(0);
|
||||
img->normalize(0);
|
||||
img->packNormals(0);
|
||||
img->expandNormals(0);
|
||||
img->normalize(0);
|
||||
img->packNormals(0);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user