Refactored ColorProfile

This commit is contained in:
Michaël Lemaire 2013-11-19 12:51:26 +01:00 committed by Michael Lemaire
parent 82defc96f6
commit a108682b4d
14 changed files with 180 additions and 174 deletions

106
src/basics/ColorProfile.cpp Normal file
View file

@ -0,0 +1,106 @@
#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);
}
}

41
src/basics/ColorProfile.h Normal file
View file

@ -0,0 +1,41 @@
#ifndef COLORPROFILE_H
#define COLORPROFILE_H
#include "basics_global.h"
#include "Color.h"
namespace paysages {
namespace basics {
class BASICSSHARED_EXPORT ColorProfile
{
public:
typedef enum
{
TONE_MAPPING_UNCHARTED,
TONE_MAPPING_REIHNARD,
TONE_MAPPING_CLAMP
} ToneMappingOperator;
public:
ColorProfile();
ColorProfile(ToneMappingOperator tonemapper, double exposure);
void setToneMapping(ToneMappingOperator tonemapper, double exposure);
void save(PackStream* stream) const;
void load(PackStream* stream);
void copy(ColorProfile* destination) const;
Color apply(const Color &pixel) const;
private:
ToneMappingOperator mapper;
double exposure;
};
}
}
#endif // COLORPROFILE_H

View file

@ -27,7 +27,8 @@ SOURCES += \
ColorHSL.cpp \
BoundingBox.cpp \
Matrix4.cpp \
Curve.cpp
Curve.cpp \
ColorProfile.cpp
HEADERS +=\
basics_global.h \
@ -42,7 +43,8 @@ HEADERS +=\
ColorHSL.h \
BoundingBox.h \
Matrix4.h \
Curve.h
Curve.h \
ColorProfile.h
unix:!symbian {
maemo5 {

View file

@ -19,6 +19,7 @@ namespace basics {
class Color;
class NoiseGenerator;
class Curve;
class ColorProfile;
}
}
using namespace paysages::basics;

View file

@ -19,6 +19,7 @@
#include "tools.h"
#include "Scenery.h"
#include "ColorProfile.h"
static DialogRender* _current_dialog;
@ -219,7 +220,7 @@ void DialogRender::saveRender()
void DialogRender::toneMappingChanged()
{
renderSetToneMapping(_renderer->render_area, (ToneMappingOperator)_tonemapping_control->currentIndex(), ((double)_exposure_control->value()) * 0.01);
renderSetToneMapping(_renderer->render_area, ColorProfile((ColorProfile::ToneMappingOperator)_tonemapping_control->currentIndex(), ((double)_exposure_control->value()) * 0.01));
}
void DialogRender::loadLastRender()

View file

@ -5,10 +5,9 @@
#include "tools.h"
#include "SoftwareRenderer.h"
#include "BasePreview.h"
#include "tools/lighting.h"
#include "tools/color.h"
#include "CameraDefinition.h"
#include "ColorProfile.h"
#include "tools/lighting.h"
/***** Shared renderer *****/
MaterialPreviewRenderer::MaterialPreviewRenderer(SurfaceMaterial* material)
@ -27,13 +26,13 @@ MaterialPreviewRenderer::MaterialPreviewRenderer(SurfaceMaterial* material)
render_camera->setLocation(Vector3(0.0, 0.0, 10.0));
_color_profile = colorProfileCreate();
colorProfileSetToneMapping(_color_profile, TONE_MAPPING_UNCHARTED, 1.0);
_color_profile = new ColorProfile;
_color_profile->setToneMapping(ColorProfile::TONE_MAPPING_UNCHARTED, 1.0);
}
MaterialPreviewRenderer::~MaterialPreviewRenderer()
{
colorProfileDelete(_color_profile);
delete _color_profile;
}
void MaterialPreviewRenderer::bindEvent(BasePreview* preview)
@ -70,7 +69,7 @@ Color MaterialPreviewRenderer::getColor2D(double x, double y, double)
{
color.a = (1.0 - dist) / 0.05;
}
return colorProfileApply(_color_profile, color);
return _color_profile->apply(color);
}
}

View file

@ -2,6 +2,7 @@
#include <QImage>
#include <QGLWidget>
#include "ColorProfile.h"
#ifndef GL_CLAMP_TO_EDGE
#define GL_CLAMP_TO_EDGE 0x812F
@ -10,7 +11,7 @@
BaseExplorerChunk::BaseExplorerChunk(Renderer* renderer)
{
_renderer = renderer;
_color_profile = colorProfileCreate();
_color_profile = new ColorProfile;
priority = 0.0;
_reset_needed = false;
@ -25,7 +26,7 @@ BaseExplorerChunk::BaseExplorerChunk(Renderer* renderer)
BaseExplorerChunk::~BaseExplorerChunk()
{
_lock_data.lock();
colorProfileDelete(_color_profile);
delete _color_profile;
delete _texture;
_lock_data.unlock();
}
@ -57,7 +58,7 @@ bool BaseExplorerChunk::maintain()
if (_texture_current_size <= 1 || i % 2 != 0 || j % 2 != 0)
{
Color color = getTextureColor((double)i / (double)new_texture_size, 1.0 - (double)j / (double)new_texture_size);
color = colorProfileApply(_color_profile, color);
color = _color_profile->apply(color);
colorNormalize(&color);
new_image->setPixel(i, j, colorTo32BitBGRA(&color));
}

View file

@ -4,12 +4,11 @@
#include "opengl_global.h"
#include <QMutex>
#include "tools/color.h"
#include "Color.h"
class QImage;
class QGLWidget;
class Renderer;
class ColorProfile;
namespace paysages {
namespace opengl {
@ -27,7 +26,7 @@ public:
protected:
BaseExplorerChunk(Renderer* renderer);
inline Renderer* renderer() {return _renderer;};
inline Renderer* renderer() {return _renderer;}
void askReset();
void setMaxTextureSize(int size);

View file

@ -14,6 +14,7 @@
#include "PackStream.h"
#include "Base2dPreviewRenderer.h"
#include "PreviewOsd.h"
#include "ColorProfile.h"
/*************** PreviewChunk ***************/
class PreviewChunk
@ -406,7 +407,7 @@ DrawingWidget(parent)
_info->setStyleSheet("QLabel { background-color: white; color: black; }");
_hdr_enabled = false;
_hdr_profile = colorProfileCreate();
_hdr_profile = new ColorProfile;
this->alive = true;
@ -423,7 +424,7 @@ BasePreview::~BasePreview()
{
alive = false;
colorProfileDelete(_hdr_profile);
delete _hdr_profile;
_drawing_manager->removeChunks(this);
@ -643,7 +644,7 @@ QColor BasePreview::getPixelColor(int x, int y)
Color col = getColor((double) (x - _width / 2) * scaling + xoffset, (double) (y - _height / 2) * scaling + yoffset);
if (_hdr_enabled)
{
col = colorProfileApply(_hdr_profile, col);
col = _hdr_profile->apply(col);
}
col.normalize();
return QColor::fromRgbF(col.r, col.g, col.b, col.a);

View file

@ -1,8 +1,6 @@
#include "render.h"
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <cmath>
#include "renderer.h"
#include "CameraDefinition.h"
@ -11,6 +9,7 @@
#include "Mutex.h"
#include "System.h"
#include "Vector3.h"
#include "ColorProfile.h"
typedef struct
{
@ -112,7 +111,7 @@ RenderArea* renderCreateArea(Renderer* renderer)
result = new RenderArea;
result->renderer = renderer;
result->hdr_mapping = colorProfileCreate();
result->hdr_mapping = new ColorProfile;
result->params.width = 1;
result->params.height = 1;
result->params.antialias = 1;
@ -136,7 +135,7 @@ RenderArea* renderCreateArea(Renderer* renderer)
void renderDeleteArea(RenderArea* area)
{
colorProfileDelete(area->hdr_mapping);
delete area->hdr_mapping;
delete area->lock;
free(area->pixels);
free(area);
@ -171,9 +170,9 @@ void renderSetParams(RenderArea* area, RenderParams params)
renderClear(area);
}
void renderSetToneMapping(RenderArea* area, ToneMappingOperator tonemapper, double exposure)
void renderSetToneMapping(RenderArea* area, const ColorProfile &profile)
{
colorProfileSetToneMapping(area->hdr_mapping, tonemapper, exposure);
profile.copy(area->hdr_mapping);
_setAllDirty(area);
renderUpdate(area);
}
@ -275,7 +274,7 @@ static inline Color _getFinalPixel(RenderArea* area, int x, int y)
}
}
return colorProfileApply(area->hdr_mapping, result);
return area->hdr_mapping->apply(result);
}
static void _processDirtyPixels(RenderArea* area)

View file

@ -29,7 +29,7 @@ RENDERINGSHARED_EXPORT RenderArea* renderCreateArea(Renderer* renderer);
RENDERINGSHARED_EXPORT void renderDeleteArea(RenderArea* area);
RENDERINGSHARED_EXPORT void renderSetParams(RenderArea* area, RenderParams params);
RENDERINGSHARED_EXPORT void renderSetToneMapping(RenderArea* area, ToneMappingOperator tonemapper, double exposure);
RENDERINGSHARED_EXPORT void renderSetToneMapping(RenderArea* area, const ColorProfile &profile);
RENDERINGSHARED_EXPORT void renderSetBackgroundColor(RenderArea* area, const Color& col);
RENDERINGSHARED_EXPORT void renderClear(RenderArea* area);
RENDERINGSHARED_EXPORT void renderUpdate(RenderArea* area);

View file

@ -7,130 +7,6 @@
#include "PackStream.h"
#include "Curve.h"
/******************************** ColorProfile ********************************/
class ColorProfile
{
public:
double minvalue;
double maxvalue;
Color(*mapper)(Color col, double exposure);
double exposure;
};
ColorProfile* colorProfileCreate()
{
ColorProfile* profile;
profile = new ColorProfile;
colorProfileSetToneMapping(profile, TONE_MAPPING_UNCHARTED, 2.0);
colorProfileClear(profile);
return profile;
}
void colorProfileDelete(ColorProfile* profile)
{
delete profile;
}
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 Color _toneMappingUncharted(Color pixel, double exposure)
{
double W = 11.2;
double white_scale = 1.0 / _uncharted2Tonemap(W);
pixel.r = pow(_uncharted2Tonemap(pixel.r * exposure) * white_scale, 1.0 / 2.2);
pixel.g = pow(_uncharted2Tonemap(pixel.g * exposure) * white_scale, 1.0 / 2.2);
pixel.b = pow(_uncharted2Tonemap(pixel.b * exposure) * white_scale, 1.0 / 2.2);
return pixel;
}
static Color _toneMappingReinhard(Color pixel, double exposure)
{
pixel.r = (pixel.r * exposure) / (1.0 + pixel.r * exposure);
pixel.g = (pixel.g * exposure) / (1.0 + pixel.g * exposure);
pixel.b = (pixel.b * exposure) / (1.0 + pixel.b * exposure);
return pixel;
}
static Color _toneMappingClamp(Color pixel, double)
{
pixel.r = pixel.r > 1.0 ? 1.0 : pixel.r;
pixel.g = pixel.g > 1.0 ? 1.0 : pixel.g;
pixel.b = pixel.b > 1.0 ? 1.0 : pixel.b;
return pixel;
}
void colorProfileSetToneMapping(ColorProfile* profile, ToneMappingOperator tonemapper, double exposure)
{
switch (tonemapper)
{
case TONE_MAPPING_REIHNARD:
profile->mapper = _toneMappingReinhard;
break;
case TONE_MAPPING_UNCHARTED:
profile->mapper = _toneMappingUncharted;
break;
default:
profile->mapper = _toneMappingClamp;
}
profile->exposure = exposure;
}
void colorProfileSave(PackStream*, ColorProfile*)
{
/* TODO */
}
void colorProfileLoad(PackStream*, ColorProfile*)
{
/* TODO */
}
void colorProfileClear(ColorProfile* profile)
{
profile->minvalue = 0.0;
profile->maxvalue = 3.0;
}
int colorProfileCollect(ColorProfile* profile, Color pixel)
{
int changed = 0;
double value = pixel.r + pixel.g + pixel.b;
if (value < profile->minvalue)
{
profile->minvalue = value;
changed = 1;
}
if (value > profile->maxvalue)
{
profile->maxvalue = value;
changed = 1;
}
return changed;
}
Color colorProfileApply(ColorProfile* profile, Color pixel)
{
return profile->mapper(pixel, profile->exposure);
}
/******************************** ColorGradation ********************************/
struct ColorGradation
{

View file

@ -3,27 +3,6 @@
#include "../rendering_global.h"
/* HDR profile for tone-mapping */
class ColorProfile;
typedef enum
{
TONE_MAPPING_UNCHARTED,
TONE_MAPPING_REIHNARD,
TONE_MAPPING_CLAMP
} ToneMappingOperator;
RENDERINGSHARED_EXPORT ColorProfile* colorProfileCreate();
RENDERINGSHARED_EXPORT void colorProfileDelete(ColorProfile* profile);
RENDERINGSHARED_EXPORT void colorProfileSetToneMapping(ColorProfile* profile, ToneMappingOperator tonemapper, double exposure);
RENDERINGSHARED_EXPORT void colorProfileSave(PackStream* stream, ColorProfile* profile);
RENDERINGSHARED_EXPORT void colorProfileLoad(PackStream* stream, ColorProfile* profile);
RENDERINGSHARED_EXPORT void colorProfileClear(ColorProfile* profile);
RENDERINGSHARED_EXPORT int colorProfileCollect(ColorProfile* profile, Color pixel);
RENDERINGSHARED_EXPORT Color colorProfileApply(ColorProfile* profile, Color pixel);
/* ColorGradation */
typedef struct ColorGradation ColorGradation;

View file

@ -3,6 +3,7 @@
#include <cmath>
#include "renderer.h"
#include "CameraDefinition.h"
#include "ColorProfile.h"
#include "System.h"
static Color _postProcessFragment(Renderer*, Vector3 location, void*)
@ -36,7 +37,7 @@ TEST(Render, quad)
renderer->render_width = 800;
renderer->render_height = 600;
renderer->render_quality = 1;
renderSetToneMapping(renderer->render_area, TONE_MAPPING_CLAMP, 0.0);
renderSetToneMapping(renderer->render_area, ColorProfile(ColorProfile::TONE_MAPPING_CLAMP, 0.0));
renderer->render_camera->setLocationCoords(0.0, 0.5, 2.0);
renderer->render_camera->setTargetCoords(0.0, 0.5, 0.0);