From 06e169be17d6298bb443271c7defa8b1abf52b8d Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Mon, 1 Oct 2012 17:14:17 +0200 Subject: [PATCH] Add parameters and start the effect chain implementation. Rework some of the enums. --- main.cpp | 207 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 195 insertions(+), 12 deletions(-) diff --git a/main.cpp b/main.cpp index 974fe53..f81eaa8 100644 --- a/main.cpp +++ b/main.cpp @@ -5,11 +5,14 @@ #define HEIGHT 720 #define BUFFER_OFFSET(i) ((char *)NULL + (i)) +#include #include #include +#include #include #include +#include #include #include @@ -33,14 +36,26 @@ float lift_r = 0.0f, lift_g = 0.0f, lift_b = 0.0f; float gamma_r = 1.0f, gamma_g = 1.0f, gamma_b = 1.0f; float gain_r = 1.0f, gain_g = 1.0f, gain_b = 1.0f; -struct ImageFormat { - enum { FORMAT_RGB, FORMAT_RGBA } format; +enum PixelFormat { FORMAT_RGB, FORMAT_RGBA }; - // Note: sRGB and 709 use the same colorspace primaries. - enum { COLORSPACE_sRGB, COLORSPACE_REC_601_525, COLORSPACE_REC_601_625, COLORSPACE_REC_709 } color_space; +enum ColorSpace { + COLORSPACE_sRGB = 0, + COLORSPACE_REC_709 = 0, // Same as sRGB. + COLORSPACE_REC_601_525 = 1, + COLORSPACE_REC_601_625 = 2, +}; - // Note: Rec. 601 and 709 use the same gamma curve. - enum { LINEAR_LIGHT, GAMMA_sRGB, GAMMA_REC_601, GAMMA_REC_709 } gamma_curve; +enum GammaCurve { + GAMMA_LINEAR = 0, + GAMMA_sRGB = 1, + GAMMA_REC_601 = 2, + GAMMA_REC_709 = 2, // Same as Rec. 601. +}; + +struct ImageFormat { + PixelFormat pixel_format; + ColorSpace color_space; + GammaCurve gamma_curve; }; enum EffectId { @@ -58,19 +73,132 @@ public: virtual bool needs_srgb_primaries() { return true; } virtual bool needs_many_samples() { return false; } virtual bool needs_mipmaps() { return false; } - bool set_float(const std::string& key, float value); - bool set_float_array(const std::string&, const float *values, size_t num_values); + // Neither of these take ownership. + bool set_int(const std::string&, int value); + bool set_float(const std::string &key, float value); + bool set_vec3(const std::string &key, const float *values); + +protected: + // Neither of these take ownership. + void register_int(const std::string &key, int *value); + void register_float(const std::string &key, float *value); + void register_vec3(const std::string &key, float *values); + private: - bool register_float(const std::string& key, float value); - bool register_float_array(const std::string& key, float *values, size_t num_values); -}; + std::map params_int; + std::map params_float; + std::map params_vec3; +}; + +bool Effect::set_int(const std::string &key, int value) +{ + if (params_int.count(key) == 0) { + return false; + } + *params_int[key] = value; + return true; +} + +bool Effect::set_float(const std::string &key, float value) +{ + if (params_float.count(key) == 0) { + return false; + } + *params_float[key] = value; + return true; +} + +bool Effect::set_vec3(const std::string &key, const float *values) +{ + if (params_vec3.count(key) == 0) { + return false; + } + memcpy(params_vec3[key], values, sizeof(float) * 3); + return true; +} + +void Effect::register_int(const std::string &key, int *value) +{ + assert(params_int.count(key) == 0); + params_int[key] = value; +} + +void Effect::register_float(const std::string &key, float *value) +{ + assert(params_float.count(key) == 0); + params_float[key] = value; +} + +void Effect::register_vec3(const std::string &key, float *values) +{ + assert(params_vec3.count(key) == 0); + params_vec3[key] = values; +} + +// Can alias on a float[3]. +struct RGBTriplet { + RGBTriplet(float r, float g, float b) + : r(r), g(g), b(b) {} + + float r, g, b; +}; + +class GammaExpansionEffect : public Effect { +public: + GammaExpansionEffect() + : source_curve(GAMMA_LINEAR) + { + register_int("source_curve", (int *)&source_curve); + } + +private: + GammaCurve source_curve; +}; + +class ColorSpaceConversionEffect : public Effect { +public: + ColorSpaceConversionEffect() + : source_space(COLORSPACE_sRGB), + destination_space(COLORSPACE_sRGB) + { + register_int("source_space", (int *)&source_space); + register_int("destination_space", (int *)&destination_space); + } + +private: + ColorSpace source_space, destination_space; +}; + +class ColorSpaceConversionEffect; + +class LiftGammaGainEffect : public Effect { +public: + LiftGammaGainEffect() + : lift(0.0f, 0.0f, 0.0f), + gamma(1.0f, 1.0f, 1.0f), + gain(1.0f, 1.0f, 1.0f), + saturation(1.0f) + { + register_vec3("lift", (float *)&lift); + register_vec3("gamma", (float *)&gamma); + register_vec3("gain", (float *)&gain); + register_float("saturation", &saturation); + } + +private: + RGBTriplet lift, gamma, gain; + float saturation; +}; class EffectChain { public: - void set_size(unsigned width, unsigned height); + EffectChain(unsigned width, unsigned height); void add_input(const ImageFormat &format); + + // The pointer is owned by EffectChain. Effect *add_effect(EffectId effect); + void add_output(const ImageFormat &format); void render(unsigned char *src, unsigned char *dst); @@ -79,8 +207,63 @@ private: unsigned width, height; ImageFormat input_format, output_format; std::vector effects; + + ColorSpace current_color_space; + GammaCurve current_gamma_curve; }; +EffectChain::EffectChain(unsigned width, unsigned height) + : width(width), height(height) {} + +void EffectChain::add_input(const ImageFormat &format) +{ + input_format = format; + current_color_space = format.color_space; + current_gamma_curve = format.gamma_curve; +} + +void EffectChain::add_output(const ImageFormat &format) +{ + output_format = format; +} + +Effect *instantiate_effect(EffectId effect) +{ + switch (effect) { + case GAMMA_CONVERSION: + return new GammaExpansionEffect(); + case RGB_PRIMARIES_CONVERSION: + return new GammaExpansionEffect(); + case LIFT_GAMMA_GAIN: + return new LiftGammaGainEffect(); + } + assert(false); +} + +Effect *EffectChain::add_effect(EffectId effect_id) +{ + Effect *effect = instantiate_effect(effect_id); + + if (effect->needs_linear_light() && current_gamma_curve != GAMMA_LINEAR) { + GammaExpansionEffect *gamma_conversion = new GammaExpansionEffect(); + gamma_conversion->set_int("source_curve", current_gamma_curve); + effects.push_back(gamma_conversion); + current_gamma_curve = GAMMA_LINEAR; + } + + if (effect->needs_srgb_primaries() && current_color_space != COLORSPACE_sRGB) { + assert(current_gamma_curve == GAMMA_LINEAR); + ColorSpaceConversionEffect *colorspace_conversion = new ColorSpaceConversionEffect(); + colorspace_conversion->set_int("source_space", current_color_space); + colorspace_conversion->set_int("destination_space", COLORSPACE_sRGB); + effects.push_back(colorspace_conversion); + current_color_space = COLORSPACE_sRGB; + } + + effects.push_back(effect); + return effect; +} + GLhandleARB read_shader(const char* filename, GLenum type) { static char buf[131072]; -- 2.39.2