paysages3d/src/basics/ColorProfile.cpp

106 lines
2.5 KiB
C++

#include "ColorProfile.h"
#include "PackStream.h"
ColorProfile::ColorProfile()
{
setToneMapping(TONE_MAPPING_UNCHARTED, 2.0);
}
ColorProfile::ColorProfile(ToneMappingOperator tonemapper, double exposure)
{
setToneMapping(tonemapper, exposure);
}
static inline double _uncharted2Tonemap(double x)
{
double A = 0.15;
double B = 0.50;
double C = 0.10;
double D = 0.20;
double E = 0.02;
double F = 0.30;
return ((x * (A * x + C * B) + D * E) / (x * (A * x + B) + D * F)) - E / F;
}
static inline Color _toneMappingUncharted(const Color &pixel, double exposure)
{
static const double W = 11.2;
static const double white_scale = 1.0 / _uncharted2Tonemap(W);
static const double factor = 1.0 / 2.2;
Color result(
pow(_uncharted2Tonemap(pixel.r * exposure) * white_scale, factor),
pow(_uncharted2Tonemap(pixel.g * exposure) * white_scale, factor),
pow(_uncharted2Tonemap(pixel.b * exposure) * white_scale, factor),
pixel.a
);
return result;
}
static inline Color _toneMappingReinhard(const Color &pixel, double exposure)
{
Color result(
(pixel.r * exposure) / (1.0 + pixel.r * exposure),
(pixel.g * exposure) / (1.0 + pixel.g * exposure),
(pixel.b * exposure) / (1.0 + pixel.b * exposure),
pixel.a
);
return result;
}
static inline Color _toneMappingClamp(const Color &pixel)
{
Color result(
pixel.r > 1.0 ? 1.0 : pixel.r,
pixel.g > 1.0 ? 1.0 : pixel.g,
pixel.b > 1.0 ? 1.0 : pixel.b,
pixel.a
);
return result;
}
void ColorProfile::setToneMapping(ToneMappingOperator tonemapper, double exposure)
{
this->mapper = tonemapper;
this->exposure = exposure;
}
void ColorProfile::save(PackStream* stream) const
{
int imapper = (int)mapper;
stream->write(&imapper);
stream->write(&exposure);
}
void ColorProfile::load(PackStream* stream)
{
int imapper = (int)mapper;
stream->read(&imapper);
stream->read(&exposure);
mapper = (ToneMappingOperator)imapper;
}
void ColorProfile::copy(ColorProfile* destination) const
{
destination->mapper = mapper;
destination->exposure = exposure;
}
Color ColorProfile::apply(const Color &pixel) const
{
switch (mapper)
{
case TONE_MAPPING_REIHNARD:
return _toneMappingReinhard(pixel, exposure);
case TONE_MAPPING_UNCHARTED:
return _toneMappingUncharted(pixel, exposure);
default:
return _toneMappingClamp(pixel);
}
}