paysages3d/src/basics/ColorProfile.cpp

84 lines
2.4 KiB
C++

#include "ColorProfile.h"
#include "PackStream.h"
#include <cmath>
ColorProfile::ColorProfile() {
setToneMapping(TONE_MAPPING_UNCHARTED, 1.6);
}
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 = trunc_to_int(mapper);
stream->write(&imapper);
stream->write(&exposure);
}
void ColorProfile::load(PackStream *stream) {
int imapper = trunc_to_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);
}
}