From a108682b4d0b4f010119018caac903ddabd7b938 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Tue, 19 Nov 2013 12:51:26 +0100 Subject: [PATCH] Refactored ColorProfile --- src/basics/ColorProfile.cpp | 106 ++++++++++++++++++ src/basics/ColorProfile.h | 41 +++++++ src/basics/basics.pro | 6 +- src/basics/basics_global.h | 1 + src/interface/desktop/dialogrender.cpp | 3 +- src/interface/desktop/previewmaterial.cpp | 13 ++- src/render/opengl/BaseExplorerChunk.cpp | 7 +- src/render/opengl/BaseExplorerChunk.h | 5 +- src/render/preview/BasePreview.cpp | 7 +- src/rendering/render.cpp | 15 ++- src/rendering/render.h | 2 +- src/rendering/tools/color.cpp | 124 ---------------------- src/rendering/tools/color.h | 21 ---- src/tests/Render_Test.cpp | 3 +- 14 files changed, 180 insertions(+), 174 deletions(-) create mode 100644 src/basics/ColorProfile.cpp create mode 100644 src/basics/ColorProfile.h diff --git a/src/basics/ColorProfile.cpp b/src/basics/ColorProfile.cpp new file mode 100644 index 0000000..25c2ff3 --- /dev/null +++ b/src/basics/ColorProfile.cpp @@ -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); + } +} diff --git a/src/basics/ColorProfile.h b/src/basics/ColorProfile.h new file mode 100644 index 0000000..0f84445 --- /dev/null +++ b/src/basics/ColorProfile.h @@ -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 diff --git a/src/basics/basics.pro b/src/basics/basics.pro index 7282e01..decec0d 100644 --- a/src/basics/basics.pro +++ b/src/basics/basics.pro @@ -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 { diff --git a/src/basics/basics_global.h b/src/basics/basics_global.h index 2f0d6bf..e6830b6 100644 --- a/src/basics/basics_global.h +++ b/src/basics/basics_global.h @@ -19,6 +19,7 @@ namespace basics { class Color; class NoiseGenerator; class Curve; + class ColorProfile; } } using namespace paysages::basics; diff --git a/src/interface/desktop/dialogrender.cpp b/src/interface/desktop/dialogrender.cpp index 83030f0..7ce2b82 100644 --- a/src/interface/desktop/dialogrender.cpp +++ b/src/interface/desktop/dialogrender.cpp @@ -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() diff --git a/src/interface/desktop/previewmaterial.cpp b/src/interface/desktop/previewmaterial.cpp index a36ebe7..820a010 100644 --- a/src/interface/desktop/previewmaterial.cpp +++ b/src/interface/desktop/previewmaterial.cpp @@ -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); } } diff --git a/src/render/opengl/BaseExplorerChunk.cpp b/src/render/opengl/BaseExplorerChunk.cpp index cfd8a16..8d709bb 100644 --- a/src/render/opengl/BaseExplorerChunk.cpp +++ b/src/render/opengl/BaseExplorerChunk.cpp @@ -2,6 +2,7 @@ #include #include +#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)); } diff --git a/src/render/opengl/BaseExplorerChunk.h b/src/render/opengl/BaseExplorerChunk.h index 3483037..2e34cce 100644 --- a/src/render/opengl/BaseExplorerChunk.h +++ b/src/render/opengl/BaseExplorerChunk.h @@ -4,12 +4,11 @@ #include "opengl_global.h" #include -#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); diff --git a/src/render/preview/BasePreview.cpp b/src/render/preview/BasePreview.cpp index 8635685..f88ced3 100644 --- a/src/render/preview/BasePreview.cpp +++ b/src/render/preview/BasePreview.cpp @@ -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); diff --git a/src/rendering/render.cpp b/src/rendering/render.cpp index 0b93c0b..e554e8d 100644 --- a/src/rendering/render.cpp +++ b/src/rendering/render.cpp @@ -1,8 +1,6 @@ #include "render.h" -#include -#include -#include +#include #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) diff --git a/src/rendering/render.h b/src/rendering/render.h index 0961453..981eddf 100644 --- a/src/rendering/render.h +++ b/src/rendering/render.h @@ -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); diff --git a/src/rendering/tools/color.cpp b/src/rendering/tools/color.cpp index 7b802f2..9359f3b 100644 --- a/src/rendering/tools/color.cpp +++ b/src/rendering/tools/color.cpp @@ -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 { diff --git a/src/rendering/tools/color.h b/src/rendering/tools/color.h index 60d4a0d..af49b60 100644 --- a/src/rendering/tools/color.h +++ b/src/rendering/tools/color.h @@ -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; diff --git a/src/tests/Render_Test.cpp b/src/tests/Render_Test.cpp index 43ea64e..fc94f9c 100644 --- a/src/tests/Render_Test.cpp +++ b/src/tests/Render_Test.cpp @@ -3,6 +3,7 @@ #include #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);