From a592c55caca0fb654bad4ec43b84c46abcee21c2 Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Mon, 1 Oct 2012 17:57:26 +0200 Subject: [PATCH] Start actually piecing together the GLSL shaders from the effect chain. --- colorspace_conversion_effect.cpp | 6 +++++ colorspace_conversion_effect.h | 1 + effect.h | 1 + effect_chain.cpp | 42 ++++++++++++++++++++++++++++++- effect_chain.h | 13 ++++++++-- footer.glsl | 4 +++ fs.glsl | 4 +-- gamma_expansion_effect.cpp | 6 +++++ gamma_expansion_effect.h | 1 + header.glsl | 9 +++++++ lift_gamma_gain_effect.cpp | 6 +++++ lift_gamma_gain_effect.h | 1 + main.cpp | 43 ++++++++++++-------------------- todo.glsl | 5 ++++ util.cpp | 33 +++++++++++++++++++++++- util.h | 3 +++ vs.glsl | 4 +-- 17 files changed, 147 insertions(+), 35 deletions(-) create mode 100644 footer.glsl create mode 100644 header.glsl create mode 100644 todo.glsl diff --git a/colorspace_conversion_effect.cpp b/colorspace_conversion_effect.cpp index fe8119a..8a0199e 100644 --- a/colorspace_conversion_effect.cpp +++ b/colorspace_conversion_effect.cpp @@ -1,4 +1,5 @@ #include "colorspace_conversion_effect.h" +#include "util.h" ColorSpaceConversionEffect::ColorSpaceConversionEffect() : source_space(COLORSPACE_sRGB), @@ -7,3 +8,8 @@ ColorSpaceConversionEffect::ColorSpaceConversionEffect() register_int("source_space", (int *)&source_space); register_int("destination_space", (int *)&destination_space); } + +std::string ColorSpaceConversionEffect::output_glsl() +{ + return read_file("todo.glsl"); +} diff --git a/colorspace_conversion_effect.h b/colorspace_conversion_effect.h index bf3583b..e487d70 100644 --- a/colorspace_conversion_effect.h +++ b/colorspace_conversion_effect.h @@ -7,6 +7,7 @@ class ColorSpaceConversionEffect : public Effect { public: ColorSpaceConversionEffect(); + std::string output_glsl(); private: ColorSpace source_space, destination_space; diff --git a/effect.h b/effect.h index a7b0e4b..623915b 100644 --- a/effect.h +++ b/effect.h @@ -18,6 +18,7 @@ public: virtual bool needs_srgb_primaries() { return true; } virtual bool needs_many_samples() { return false; } virtual bool needs_mipmaps() { return false; } + virtual std::string output_glsl() = 0; // Neither of these take ownership. bool set_int(const std::string&, int value); diff --git a/effect_chain.cpp b/effect_chain.cpp index 05adfd8..32ee2ce 100644 --- a/effect_chain.cpp +++ b/effect_chain.cpp @@ -1,12 +1,19 @@ +#define GL_GLEXT_PROTOTYPES 1 + +#include #include +#include +#include + +#include "util.h" #include "effect_chain.h" #include "gamma_expansion_effect.h" #include "lift_gamma_gain_effect.h" #include "colorspace_conversion_effect.h" EffectChain::EffectChain(unsigned width, unsigned height) - : width(width), height(height) {} + : width(width), height(height), finalized(false) {} void EffectChain::add_input(const ImageFormat &format) { @@ -53,7 +60,40 @@ Effect *EffectChain::add_effect(EffectId effect_id) current_color_space = COLORSPACE_sRGB; } + // not handled yet + assert(!effect->needs_many_samples()); + assert(!effect->needs_mipmaps()); + effects.push_back(effect); return effect; } +void EffectChain::finalize() +{ + std::string frag_shader = read_file("header.glsl"); + + for (unsigned i = 0; i < effects.size(); ++i) { + char effect_id[256]; + sprintf(effect_id, "eff%d", i); + + frag_shader += "\n"; + frag_shader += std::string("#define PREFIX(x) ") + effect_id + "_ ## x\n"; + frag_shader += std::string("#define FUNCNAME ") + effect_id + "\n"; + frag_shader += effects[i]->output_glsl(); + frag_shader += "#undef PREFIX\n"; + frag_shader += "#undef FUNCNAME\n"; + frag_shader += std::string("#define LAST_INPUT ") + effect_id + "\n"; + frag_shader += "\n"; + } + printf("%s\n", frag_shader.c_str()); + + glsl_program_num = glCreateProgram(); + GLhandleARB vs_obj = compile_shader(read_file("vs.glsl"), GL_VERTEX_SHADER); + GLhandleARB fs_obj = compile_shader(frag_shader, GL_FRAGMENT_SHADER); + glAttachObjectARB(glsl_program_num, vs_obj); + check_error(); + glAttachObjectARB(glsl_program_num, fs_obj); + check_error(); + glLinkProgram(glsl_program_num); + check_error(); +} diff --git a/effect_chain.h b/effect_chain.h index c8fe11e..9622abc 100644 --- a/effect_chain.h +++ b/effect_chain.h @@ -31,20 +31,29 @@ struct ImageFormat { class EffectChain { public: EffectChain(unsigned width, unsigned height); + + // input, effects, output, finalize need to come in that specific order. + void add_input(const ImageFormat &format); - // The pointer is owned by EffectChain. + // The returned pointer is owned by EffectChain. Effect *add_effect(EffectId effect); void add_output(const ImageFormat &format); + void finalize(); - void render(unsigned char *src, unsigned char *dst); + //void render(unsigned char *src, unsigned char *dst); + void render_to_screen(unsigned char *src); private: unsigned width, height; ImageFormat input_format, output_format; std::vector effects; + int glsl_program_num; + bool finalized; + + // Used during the building of the effect chain. ColorSpace current_color_space; GammaCurve current_gamma_curve; }; diff --git a/footer.glsl b/footer.glsl new file mode 100644 index 0000000..0a742a3 --- /dev/null +++ b/footer.glsl @@ -0,0 +1,4 @@ +void main() +{ + gl_FragColor = LAST_INPUT(tc); +} diff --git a/fs.glsl b/fs.glsl index 2637869..25f20db 100644 --- a/fs.glsl +++ b/fs.glsl @@ -1,6 +1,6 @@ #version 120 uniform sampler2D tex; -varying vec4 tc; +varying vec2 tc; uniform vec3 lift, gain; uniform vec3 gain_pow_inv_gamma, inv_gamma_22; uniform float saturation; @@ -40,7 +40,7 @@ vec3 from_linear(vec3 x) { void main() { - vec3 x = texture2D(tex, tc.st, -30.0f).rgb; + vec3 x = texture2D(tex, tc).rgb; x = to_linear(x); // do lift in nonlinear space (the others don't care) diff --git a/gamma_expansion_effect.cpp b/gamma_expansion_effect.cpp index cef1416..1748ae9 100644 --- a/gamma_expansion_effect.cpp +++ b/gamma_expansion_effect.cpp @@ -1,7 +1,13 @@ #include "gamma_expansion_effect.h" +#include "util.h" GammaExpansionEffect::GammaExpansionEffect() : source_curve(GAMMA_LINEAR) { register_int("source_curve", (int *)&source_curve); } + +std::string GammaExpansionEffect::output_glsl() +{ + return read_file("todo.glsl"); +} diff --git a/gamma_expansion_effect.h b/gamma_expansion_effect.h index 497a38c..d161c92 100644 --- a/gamma_expansion_effect.h +++ b/gamma_expansion_effect.h @@ -7,6 +7,7 @@ class GammaExpansionEffect : public Effect { public: GammaExpansionEffect(); + std::string output_glsl(); private: GammaCurve source_curve; diff --git a/header.glsl b/header.glsl new file mode 100644 index 0000000..274cb90 --- /dev/null +++ b/header.glsl @@ -0,0 +1,9 @@ +uniform sampler2D input_tex; +varying vec2 tc; + +vec4 read_input(vec2 tc) +{ + vec3 x = texture2D(input_tex, tc.st); +} + +#define LAST_INPUT read_input diff --git a/lift_gamma_gain_effect.cpp b/lift_gamma_gain_effect.cpp index 5c83854..eef04d5 100644 --- a/lift_gamma_gain_effect.cpp +++ b/lift_gamma_gain_effect.cpp @@ -1,4 +1,5 @@ #include "lift_gamma_gain_effect.h" +#include "util.h" LiftGammaGainEffect::LiftGammaGainEffect() : lift(0.0f, 0.0f, 0.0f), @@ -11,3 +12,8 @@ LiftGammaGainEffect::LiftGammaGainEffect() register_vec3("gain", (float *)&gain); register_float("saturation", &saturation); } + +std::string LiftGammaGainEffect::output_glsl() +{ + return read_file("todo.glsl"); +} diff --git a/lift_gamma_gain_effect.h b/lift_gamma_gain_effect.h index ae71448..26eb583 100644 --- a/lift_gamma_gain_effect.h +++ b/lift_gamma_gain_effect.h @@ -6,6 +6,7 @@ class LiftGammaGainEffect : public Effect { public: LiftGammaGainEffect(); + std::string output_glsl(); private: RGBTriplet lift, gamma, gain; diff --git a/main.cpp b/main.cpp index 8c28c8f..4054636 100644 --- a/main.cpp +++ b/main.cpp @@ -38,31 +38,6 @@ 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; -GLhandleARB read_shader(const char* filename, GLenum type) -{ - std::string shader_src = read_file(filename); - - GLhandleARB obj = glCreateShaderObjectARB(type); - const GLchar* source[] = { shader_src.data() }; - const GLint length[] = { shader_src.size() }; - glShaderSource(obj, 1, source, length); - glCompileShader(obj); - - GLchar info_log[4096]; - GLsizei log_length = sizeof(info_log) - 1; - glGetShaderInfoLog(obj, log_length, &log_length, info_log); - info_log[log_length] = 0; - printf("shader compile log: %s\n", info_log); - - GLint status; - glGetShaderiv(obj, GL_COMPILE_STATUS, &status); - if (status == GL_FALSE) { - exit(1); - } - - return obj; -} - void draw_picture_quad(GLint prog, int frame) { glUseProgramObjectARB(prog); @@ -251,6 +226,19 @@ int main(int argc, char **argv) check_error(); load_texture("blg_wheels_woman_1.jpg"); + + EffectChain chain(WIDTH, HEIGHT); + + ImageFormat inout_format; + inout_format.pixel_format = FORMAT_RGB; + inout_format.color_space = COLORSPACE_sRGB; + inout_format.gamma_curve = GAMMA_sRGB; + + chain.add_input(inout_format); + Effect *lift_gamma_gain_effect = chain.add_effect(LIFT_GAMMA_GAIN); + chain.add_output(inout_format); + chain.finalize(); + //glGenerateMipmap(GL_TEXTURE_2D); //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 4); //check_error(); @@ -306,8 +294,8 @@ int main(int argc, char **argv) update_hsv(); int prog = glCreateProgram(); - GLhandleARB vs_obj = read_shader("vs.glsl", GL_VERTEX_SHADER); - GLhandleARB fs_obj = read_shader("fs.glsl", GL_FRAGMENT_SHADER); + GLhandleARB vs_obj = compile_shader(read_file("vs.glsl"), GL_VERTEX_SHADER); + GLhandleARB fs_obj = compile_shader(read_file("fs.glsl"), GL_FRAGMENT_SHADER); glAttachObjectARB(prog, vs_obj); check_error(); glAttachObjectARB(prog, fs_obj); @@ -344,6 +332,7 @@ int main(int argc, char **argv) ++frame; + draw_picture_quad(prog, frame); glReadPixels(0, 0, WIDTH, HEIGHT, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, BUFFER_OFFSET(0)); diff --git a/todo.glsl b/todo.glsl new file mode 100644 index 0000000..a428697 --- /dev/null +++ b/todo.glsl @@ -0,0 +1,5 @@ +// Placeholder for effects that are not done yet. +vec4 FUNCNAME(vec2 tc) +{ + return LAST_INPUT(tc); +} diff --git a/util.cpp b/util.cpp index b427625..c18f009 100644 --- a/util.cpp +++ b/util.cpp @@ -1,5 +1,12 @@ -#include +#define GL_GLEXT_PROTOTYPES 1 + +#include +#include +#include +#include + +#include #include "util.h" void hsv2rgb(float h, float s, float v, float *r, float *g, float *b) @@ -57,3 +64,27 @@ std::string read_file(const std::string &filename) return std::string(buf, len); } + +GLhandleARB compile_shader(const std::string &shader_src, GLenum type) +{ + GLhandleARB obj = glCreateShaderObjectARB(type); + const GLchar* source[] = { shader_src.data() }; + const GLint length[] = { shader_src.size() }; + glShaderSource(obj, 1, source, length); + glCompileShader(obj); + + GLchar info_log[4096]; + GLsizei log_length = sizeof(info_log) - 1; + glGetShaderInfoLog(obj, log_length, &log_length, info_log); + info_log[log_length] = 0; + printf("shader compile log: %s\n", info_log); + + GLint status; + glGetShaderiv(obj, GL_COMPILE_STATUS, &status); + if (status == GL_FALSE) { + exit(1); + } + + return obj; +} + diff --git a/util.h b/util.h index 3957b86..a6ca0e8 100644 --- a/util.h +++ b/util.h @@ -6,10 +6,13 @@ #include +#include + // assumes h in [0, 2pi> or [-pi, pi> void hsv2rgb(float h, float s, float v, float *r, float *g, float *b); std::string read_file(const std::string &filename); +GLhandleARB compile_shader(const std::string &shader_src, GLenum type); #ifdef NDEBUG #define check_error() diff --git a/vs.glsl b/vs.glsl index b6db3cb..4d79aaf 100644 --- a/vs.glsl +++ b/vs.glsl @@ -1,5 +1,5 @@ #version 120 -varying vec4 tc; +varying vec2 tc; //varying vec3 lift, inv_gamma, gain; //uniform vec3 gamma; //varying vec3 inv_gamma; @@ -15,7 +15,7 @@ vec3 to_linear(vec3 x) { void main() { - tc = gl_MultiTexCoord0; + tc = gl_MultiTexCoord0.st; //lift = to_linear(vec3(rgba.r, 0.0, 0.0)); //lift = vec3(rgba.r, 0.0, 0.0); -- 2.39.2