Add tone mapping operators.
This commit is contained in:
parent
fa0800a24a
commit
2e9afac689
@ -52,7 +52,7 @@ static float solidAngleTerm(uint x, uint y, float inverseEdgeLength) {
|
|||||||
nvDebugCheck(v >= -1.0f && v <= 1.0f);
|
nvDebugCheck(v >= -1.0f && v <= 1.0f);
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
// Exact solid angle: @@ Not really exact when using seamless filtering...
|
// Exact solid angle:
|
||||||
float x0 = u - inverseEdgeLength;
|
float x0 = u - inverseEdgeLength;
|
||||||
float y0 = v - inverseEdgeLength;
|
float y0 = v - inverseEdgeLength;
|
||||||
float x1 = u + inverseEdgeLength;
|
float x1 = u + inverseEdgeLength;
|
||||||
@ -73,10 +73,10 @@ static float solidAngleTerm(uint x, uint y, float inverseEdgeLength) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static Vector3 texelDirection(uint face, uint x, uint y, int edgeLength, bool seamless)
|
static Vector3 texelDirection(uint face, uint x, uint y, int edgeLength, EdgeFixup fixupMethod)
|
||||||
{
|
{
|
||||||
float u, v;
|
float u, v;
|
||||||
if (seamless) {
|
if (fixupMethod == EdgeFixup_Stretch) {
|
||||||
// Transform x,y to [-1, 1] range, match up edges exactly.
|
// Transform x,y to [-1, 1] range, match up edges exactly.
|
||||||
u = float(x) * 2.0f / (edgeLength - 1) - 1.0f;
|
u = float(x) * 2.0f / (edgeLength - 1) - 1.0f;
|
||||||
v = float(y) * 2.0f / (edgeLength - 1) - 1.0f;
|
v = float(y) * 2.0f / (edgeLength - 1) - 1.0f;
|
||||||
@ -86,6 +86,14 @@ static Vector3 texelDirection(uint face, uint x, uint y, int edgeLength, bool se
|
|||||||
u = (float(x) + 0.5f) * (2.0f / edgeLength) - 1.0f;
|
u = (float(x) + 0.5f) * (2.0f / edgeLength) - 1.0f;
|
||||||
v = (float(y) + 0.5f) * (2.0f / edgeLength) - 1.0f;
|
v = (float(y) + 0.5f) * (2.0f / edgeLength) - 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fixupMethod == EdgeFixup_Warp) {
|
||||||
|
// Warp texel centers in the proximity of the edges.
|
||||||
|
float a = powf(float(edgeLength), 2.0f) / powf(float(edgeLength - 1), 3.0f);
|
||||||
|
u = a * powf(u, 3) + u;
|
||||||
|
v = a * powf(v, 3) + v;
|
||||||
|
}
|
||||||
|
|
||||||
nvDebugCheck(u >= -1.0f && u <= 1.0f);
|
nvDebugCheck(u >= -1.0f && u <= 1.0f);
|
||||||
nvDebugCheck(v >= -1.0f && v <= 1.0f);
|
nvDebugCheck(v >= -1.0f && v <= 1.0f);
|
||||||
|
|
||||||
@ -128,7 +136,7 @@ static Vector3 texelDirection(uint face, uint x, uint y, int edgeLength, bool se
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TexelTable::TexelTable(uint edgeLength, bool seamless) : size(edgeLength) {
|
TexelTable::TexelTable(uint edgeLength) : size(edgeLength) {
|
||||||
|
|
||||||
uint hsize = size/2;
|
uint hsize = size/2;
|
||||||
|
|
||||||
@ -147,12 +155,10 @@ TexelTable::TexelTable(uint edgeLength, bool seamless) : size(edgeLength) {
|
|||||||
for (uint f = 0; f < 6; f++) {
|
for (uint f = 0; f < 6; f++) {
|
||||||
for (uint y = 0; y < size; y++) {
|
for (uint y = 0; y < size; y++) {
|
||||||
for (uint x = 0; x < size; x++) {
|
for (uint x = 0; x < size; x++) {
|
||||||
directionArray[(f * size + y) * size + x] = texelDirection(f, x, y, edgeLength, seamless);
|
directionArray[(f * size + y) * size + x] = texelDirection(f, x, y, edgeLength, EdgeFixup_None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const Vector3 & TexelTable::direction(uint f, uint x, uint y) const {
|
const Vector3 & TexelTable::direction(uint f, uint x, uint y) const {
|
||||||
@ -376,9 +382,34 @@ Surface CubeSurface::unfold(CubeLayout layout) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float CubeSurface::average(int channel) const
|
||||||
|
{
|
||||||
|
const uint edgeLength = m->edgeLength;
|
||||||
|
m->allocateTexelTable();
|
||||||
|
|
||||||
|
float total = 0.0f;
|
||||||
|
float sum = 0.0f;
|
||||||
|
|
||||||
|
for (int f = 0; f < 6; f++) {
|
||||||
|
float * c = m->face[f].m->image->channel(channel);
|
||||||
|
|
||||||
|
for (uint y = 0; y < edgeLength; y++) {
|
||||||
|
for (uint x = 0; x < edgeLength; x++) {
|
||||||
|
float solidAngle = m->texelTable->solidAngle(f, x, y);
|
||||||
|
|
||||||
|
total += solidAngle;
|
||||||
|
sum += c[y * edgeLength + x] * solidAngle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sum / total;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#include "nvmath/SphericalHarmonic.h"
|
#include "nvmath/SphericalHarmonic.h"
|
||||||
|
|
||||||
CubeSurface CubeSurface::irradianceFilter(int size, bool seamless) const
|
CubeSurface CubeSurface::irradianceFilter(int size, EdgeFixup fixupMethod) const
|
||||||
{
|
{
|
||||||
m->allocateTexelTable();
|
m->allocateTexelTable();
|
||||||
|
|
||||||
@ -640,6 +671,7 @@ struct ApplyCosinePowerFilterContext {
|
|||||||
CubeSurface::Private * filteredCube;
|
CubeSurface::Private * filteredCube;
|
||||||
float coneAngle;
|
float coneAngle;
|
||||||
float cosinePower;
|
float cosinePower;
|
||||||
|
EdgeFixup fixupMethod;
|
||||||
};
|
};
|
||||||
|
|
||||||
void ApplyCosinePowerFilterTask(void * context, int id)
|
void ApplyCosinePowerFilterTask(void * context, int id)
|
||||||
@ -656,7 +688,7 @@ void ApplyCosinePowerFilterTask(void * context, int id)
|
|||||||
nvtt::Surface & filteredFace = ctx->filteredCube->face[f];
|
nvtt::Surface & filteredFace = ctx->filteredCube->face[f];
|
||||||
FloatImage * filteredImage = filteredFace.m->image;
|
FloatImage * filteredImage = filteredFace.m->image;
|
||||||
|
|
||||||
const Vector3 filterDir = texelDirection(f, x, y, size, ctx->filteredCube->seamless);
|
const Vector3 filterDir = texelDirection(f, x, y, size, ctx->fixupMethod);
|
||||||
|
|
||||||
// Convolve filter against cube.
|
// Convolve filter against cube.
|
||||||
Vector3 color = ctx->inputCube->applyCosinePowerFilter(filterDir, ctx->coneAngle, ctx->cosinePower);
|
Vector3 color = ctx->inputCube->applyCosinePowerFilter(filterDir, ctx->coneAngle, ctx->cosinePower);
|
||||||
@ -667,14 +699,13 @@ void ApplyCosinePowerFilterTask(void * context, int id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CubeSurface CubeSurface::cosinePowerFilter(int size, float cosinePower, bool seamless) const
|
CubeSurface CubeSurface::cosinePowerFilter(int size, float cosinePower, EdgeFixup fixupMethod) const
|
||||||
{
|
{
|
||||||
const uint edgeLength = m->edgeLength;
|
const uint edgeLength = m->edgeLength;
|
||||||
|
|
||||||
// Allocate output cube.
|
// Allocate output cube.
|
||||||
CubeSurface filteredCube;
|
CubeSurface filteredCube;
|
||||||
filteredCube.m->allocate(size);
|
filteredCube.m->allocate(size);
|
||||||
filteredCube.m->seamless = seamless;
|
|
||||||
|
|
||||||
// Texel table is stored along with the surface so that it's compute only once.
|
// Texel table is stored along with the surface so that it's compute only once.
|
||||||
m->allocateTexelTable();
|
m->allocateTexelTable();
|
||||||
@ -691,10 +722,10 @@ CubeSurface CubeSurface::cosinePowerFilter(int size, float cosinePower, bool sea
|
|||||||
for (uint y = 0; y < uint(size); y++) {
|
for (uint y = 0; y < uint(size); y++) {
|
||||||
for (uint x = 0; x < uint(size); x++) {
|
for (uint x = 0; x < uint(size); x++) {
|
||||||
|
|
||||||
const Vector3 filterDir = texelDirection(f, x, y, size, seamless);
|
const Vector3 filterDir = texelDirection(f, x, y, size, fixupMethod);
|
||||||
|
|
||||||
// Convolve filter against cube.
|
// Convolve filter against cube.
|
||||||
Vector3 color = m->applyCosinePowerFilter(filterDir, coneAngle, cosinePower, seamless);
|
Vector3 color = m->applyCosinePowerFilter(filterDir, coneAngle, cosinePower);
|
||||||
|
|
||||||
filteredImage->pixel(0, x, y, 0) = color.x;
|
filteredImage->pixel(0, x, y, 0) = color.x;
|
||||||
filteredImage->pixel(1, x, y, 0) = color.y;
|
filteredImage->pixel(1, x, y, 0) = color.y;
|
||||||
@ -708,10 +739,31 @@ CubeSurface CubeSurface::cosinePowerFilter(int size, float cosinePower, bool sea
|
|||||||
context.filteredCube = filteredCube.m;
|
context.filteredCube = filteredCube.m;
|
||||||
context.coneAngle = coneAngle;
|
context.coneAngle = coneAngle;
|
||||||
context.cosinePower = cosinePower;
|
context.cosinePower = cosinePower;
|
||||||
|
context.fixupMethod = fixupMethod;
|
||||||
|
|
||||||
nv::ParallelFor parallelFor(ApplyCosinePowerFilterTask, &context);
|
nv::ParallelFor parallelFor(ApplyCosinePowerFilterTask, &context);
|
||||||
parallelFor.run(6 * size * size);
|
parallelFor.run(6 * size * size);
|
||||||
|
|
||||||
|
// @@ Implement edge averaging.
|
||||||
|
if (fixupMethod == EdgeFixup_Average) {
|
||||||
|
for (uint f = 0; f < 6; f++) {
|
||||||
|
nvtt::Surface filteredFace = filteredCube.m->face[f];
|
||||||
|
FloatImage * filteredImage = filteredFace.m->image;
|
||||||
|
|
||||||
|
// For each component.
|
||||||
|
for (uint c = 0; c < 3; c++) {
|
||||||
|
// @@ For each corner, sample the two adjacent faces.
|
||||||
|
filteredImage->pixel(c, 0, 0, 0);
|
||||||
|
filteredImage->pixel(c, size-1, 0, 0);
|
||||||
|
filteredImage->pixel(c, 0, size-1, 0);
|
||||||
|
filteredImage->pixel(c, size-1, size-1, 0);
|
||||||
|
|
||||||
|
// @@ For each edge, sample the adjacent face.
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return filteredCube;
|
return filteredCube;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
namespace nvtt
|
namespace nvtt
|
||||||
{
|
{
|
||||||
struct TexelTable {
|
struct TexelTable {
|
||||||
TexelTable(uint edgeLength, bool seamless);
|
TexelTable(uint edgeLength);
|
||||||
|
|
||||||
float solidAngle(uint f, uint x, uint y) const;
|
float solidAngle(uint f, uint x, uint y) const;
|
||||||
const nv::Vector3 & direction(uint f, uint x, uint y) const;
|
const nv::Vector3 & direction(uint f, uint x, uint y) const;
|
||||||
@ -59,7 +59,6 @@ namespace nvtt
|
|||||||
nvDebugCheck( refCount() == 0 );
|
nvDebugCheck( refCount() == 0 );
|
||||||
|
|
||||||
edgeLength = 0;
|
edgeLength = 0;
|
||||||
seamless = false;
|
|
||||||
texelTable = NULL;
|
texelTable = NULL;
|
||||||
}
|
}
|
||||||
Private(const Private & p) : RefCounted() // Copy ctor. inits refcount to 0.
|
Private(const Private & p) : RefCounted() // Copy ctor. inits refcount to 0.
|
||||||
@ -67,7 +66,6 @@ namespace nvtt
|
|||||||
nvDebugCheck( refCount() == 0 );
|
nvDebugCheck( refCount() == 0 );
|
||||||
|
|
||||||
edgeLength = p.edgeLength;
|
edgeLength = p.edgeLength;
|
||||||
seamless = p.seamless;
|
|
||||||
for (uint i = 0; i < 6; i++) {
|
for (uint i = 0; i < 6; i++) {
|
||||||
face[i] = p.face[i];
|
face[i] = p.face[i];
|
||||||
}
|
}
|
||||||
@ -91,7 +89,7 @@ namespace nvtt
|
|||||||
void allocateTexelTable()
|
void allocateTexelTable()
|
||||||
{
|
{
|
||||||
if (texelTable == NULL) {
|
if (texelTable == NULL) {
|
||||||
texelTable = new TexelTable(edgeLength, seamless);
|
texelTable = new TexelTable(edgeLength);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,7 +97,6 @@ namespace nvtt
|
|||||||
nv::Vector3 applyCosinePowerFilter(const nv::Vector3 & dir, float coneAngle, float cosinePower);
|
nv::Vector3 applyCosinePowerFilter(const nv::Vector3 & dir, float coneAngle, float cosinePower);
|
||||||
|
|
||||||
uint edgeLength;
|
uint edgeLength;
|
||||||
bool seamless;
|
|
||||||
Surface face[6];
|
Surface face[6];
|
||||||
TexelTable * texelTable;
|
TexelTable * texelTable;
|
||||||
};
|
};
|
||||||
|
@ -1766,6 +1766,46 @@ void Surface::convolve(int channel, int kernelSize, float * kernelData)
|
|||||||
m->image->convolve(k, channel, (FloatImage::WrapMode)m->wrapMode);
|
m->image->convolve(k, channel, (FloatImage::WrapMode)m->wrapMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Surface::toneMap(ToneMapper tm, float exposure, float * parameters)
|
||||||
|
{
|
||||||
|
if (isNull()) return;
|
||||||
|
|
||||||
|
detach();
|
||||||
|
|
||||||
|
FloatImage * img = m->image;
|
||||||
|
float * r = img->channel(0);
|
||||||
|
float * g = img->channel(1);
|
||||||
|
float * b = img->channel(2);
|
||||||
|
const uint count = img->pixelCount();
|
||||||
|
|
||||||
|
if (tm == ToneMapper_Linear) {
|
||||||
|
// Clamp preserving the hue.
|
||||||
|
for (uint i = 0; i < count; i++) {
|
||||||
|
float m = max(r[i], g[i], b[i]);
|
||||||
|
if (m > 1.0f) {
|
||||||
|
r[i] *= 1.0f / m;
|
||||||
|
g[i] *= 1.0f / m;
|
||||||
|
b[i] *= 1.0f / m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (tm == ToneMapper_Reindhart) {
|
||||||
|
for (uint i = 0; i < count; i++) {
|
||||||
|
r[i] /= r[i] + 1;
|
||||||
|
g[i] /= g[i] + 1;
|
||||||
|
b[i] /= b[i] + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (tm == ToneMapper_Halo) {
|
||||||
|
for (uint i = 0; i < count; i++) {
|
||||||
|
r[i] = 1 - expf(-r[i]);
|
||||||
|
g[i] = 1 - expf(-g[i]);
|
||||||
|
b[i] = 1 - expf(-b[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
void Surface::blockLuminanceScale(float scale)
|
void Surface::blockLuminanceScale(float scale)
|
||||||
{
|
{
|
||||||
|
@ -413,6 +413,12 @@ namespace nvtt
|
|||||||
//NormalTransform_DualParaboloid,
|
//NormalTransform_DualParaboloid,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum ToneMapper {
|
||||||
|
ToneMapper_Linear,
|
||||||
|
ToneMapper_Reindhart,
|
||||||
|
ToneMapper_Halo,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// A surface is one level of a 2D or 3D texture.
|
// A surface is one level of a 2D or 3D texture.
|
||||||
// @@ It would be nice to add support for texture borders for correct resizing of tiled textures and constrained DXT compression.
|
// @@ It would be nice to add support for texture borders for correct resizing of tiled textures and constrained DXT compression.
|
||||||
@ -492,6 +498,8 @@ namespace nvtt
|
|||||||
NVTT_API void abs(int channel);
|
NVTT_API void abs(int channel);
|
||||||
NVTT_API void convolve(int channel, int kernelSize, float * kernelData);
|
NVTT_API void convolve(int channel, int kernelSize, float * kernelData);
|
||||||
|
|
||||||
|
NVTT_API void toneMap(ToneMapper tm, float exposure, float * parameters);
|
||||||
|
|
||||||
//NVTT_API void blockLuminanceScale(float scale);
|
//NVTT_API void blockLuminanceScale(float scale);
|
||||||
|
|
||||||
// Color quantization.
|
// Color quantization.
|
||||||
@ -535,6 +543,13 @@ namespace nvtt
|
|||||||
CubeLayout_LatitudeLongitude
|
CubeLayout_LatitudeLongitude
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum EdgeFixup {
|
||||||
|
EdgeFixup_None,
|
||||||
|
EdgeFixup_Stretch,
|
||||||
|
EdgeFixup_Warp,
|
||||||
|
EdgeFixup_Average,
|
||||||
|
};
|
||||||
|
|
||||||
// A CubeSurface is one level of a cube map texture.
|
// A CubeSurface is one level of a cube map texture.
|
||||||
struct CubeSurface
|
struct CubeSurface
|
||||||
{
|
{
|
||||||
@ -548,7 +563,6 @@ namespace nvtt
|
|||||||
NVTT_API bool isNull() const;
|
NVTT_API bool isNull() const;
|
||||||
NVTT_API int edgeLength() const;
|
NVTT_API int edgeLength() const;
|
||||||
NVTT_API int countMipmaps() const;
|
NVTT_API int countMipmaps() const;
|
||||||
NVTT_API bool isSeamless() const;
|
|
||||||
|
|
||||||
// Texture data.
|
// Texture data.
|
||||||
NVTT_API bool load(const char * fileName, int mipmap);
|
NVTT_API bool load(const char * fileName, int mipmap);
|
||||||
@ -570,8 +584,8 @@ namespace nvtt
|
|||||||
NVTT_API float average(int channel) const;
|
NVTT_API float average(int channel) const;
|
||||||
|
|
||||||
// Filtering.
|
// Filtering.
|
||||||
NVTT_API CubeSurface irradianceFilter(int size, bool seamless) const;
|
NVTT_API CubeSurface irradianceFilter(int size, EdgeFixup fixupMethod) const;
|
||||||
NVTT_API CubeSurface cosinePowerFilter(int size, float cosinePower, bool seamless) const;
|
NVTT_API CubeSurface cosinePowerFilter(int size, float cosinePower, EdgeFixup fixupMethod) const;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -50,7 +50,7 @@ int main(int argc, char *argv[])
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
envmap.toLinear(2.2f);
|
//envmap.toLinear(2.2f);
|
||||||
|
|
||||||
|
|
||||||
// Setup compression options.
|
// Setup compression options.
|
||||||
@ -59,19 +59,24 @@ int main(int argc, char *argv[])
|
|||||||
compressionOptions.setPixelType(nvtt::PixelType_Float);
|
compressionOptions.setPixelType(nvtt::PixelType_Float);
|
||||||
compressionOptions.setPixelFormat(16, 16, 16, 16);
|
compressionOptions.setPixelFormat(16, 16, 16, 16);
|
||||||
|
|
||||||
|
|
||||||
// Setup output options.
|
// Setup output options.
|
||||||
nvtt::OutputOptions outputOptions;
|
nvtt::OutputOptions outputOptions;
|
||||||
outputOptions.setFileName("filtered_envmap.dds");
|
outputOptions.setFileName("filtered_envmap.dds");
|
||||||
outputOptions.setSrgbFlag(true);
|
//outputOptions.setSrgbFlag(true);
|
||||||
|
|
||||||
|
|
||||||
const int MAX_MIPMAP_COUNT = 7; // nv::log2(64) + 1;
|
const int MAX_MIPMAP_COUNT = 7; // nv::log2(64) + 1;
|
||||||
//const int mipmapCount = MAX_MIPMAP_COUNT;
|
//const int mipmapCount = MAX_MIPMAP_COUNT;
|
||||||
const int mipmapCount = 4;
|
const int mipmapCount = 4;
|
||||||
//const int mipmapCount = 1;
|
//const int mipmapCount = 1;
|
||||||
|
const int firstMipmap = 0;
|
||||||
|
|
||||||
|
int topSize = 64;
|
||||||
|
float topPower = 64;
|
||||||
|
|
||||||
// Output header.
|
// Output header.
|
||||||
context.outputHeader(nvtt::TextureType_Cube, 64, 64, 1, mipmapCount, false, compressionOptions, outputOptions);
|
context.outputHeader(nvtt::TextureType_Cube, topSize >> firstMipmap, topSize >> firstMipmap, 1, mipmapCount-firstMipmap, false, compressionOptions, outputOptions);
|
||||||
|
|
||||||
nv::Timer timer;
|
nv::Timer timer;
|
||||||
timer.start();
|
timer.start();
|
||||||
@ -79,20 +84,20 @@ int main(int argc, char *argv[])
|
|||||||
nvtt::CubeSurface filteredEnvmap[mipmapCount];
|
nvtt::CubeSurface filteredEnvmap[mipmapCount];
|
||||||
|
|
||||||
// Output filtered mipmaps.
|
// Output filtered mipmaps.
|
||||||
for (int m = 0; m < mipmapCount; m++) {
|
for (int m = firstMipmap; m < mipmapCount; m++) {
|
||||||
int size = 64 / (1 << m); // 64, 32, 16, 8
|
int size = topSize >> m; // 64, 32, 16, 8
|
||||||
float cosine_power = float(64) / (1 << (2 * m)); // 64, 16, 4, 1
|
float cosine_power = topPower / (1 << (2 * m)); // 64, 16, 4, 1
|
||||||
cosine_power = nv::max(1.0f, cosine_power);
|
cosine_power = nv::max(1.0f, cosine_power);
|
||||||
|
|
||||||
printf("filtering step: %d/%d\n", m+1, mipmapCount);
|
printf("filtering step: %d/%d\n", m+1, mipmapCount);
|
||||||
|
|
||||||
filteredEnvmap[m] = envmap.cosinePowerFilter(size, cosine_power, false);
|
filteredEnvmap[m] = envmap.cosinePowerFilter(size, cosine_power, nvtt::EdgeFixup_Warp);
|
||||||
filteredEnvmap[m].toGamma(2.2f);
|
//filteredEnvmap[m].toGamma(2.2f);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int f = 0; f < 6; f++) {
|
for (int f = 0; f < 6; f++) {
|
||||||
for (int m = 0; m < mipmapCount; m++) {
|
for (int m = firstMipmap; m < mipmapCount; m++) {
|
||||||
context.compress(filteredEnvmap[m].face(f), f, m, compressionOptions, outputOptions);
|
context.compress(filteredEnvmap[m].face(f), f, m-firstMipmap, compressionOptions, outputOptions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user