#include "colorspace_conversion_effect.h"
+#include "util.h"
ColorSpaceConversionEffect::ColorSpaceConversionEffect()
: source_space(COLORSPACE_sRGB),
register_int("source_space", (int *)&source_space);
register_int("destination_space", (int *)&destination_space);
}
+
+std::string ColorSpaceConversionEffect::output_glsl()
+{
+ return read_file("todo.glsl");
+}
class ColorSpaceConversionEffect : public Effect {
public:
ColorSpaceConversionEffect();
+ std::string output_glsl();
private:
ColorSpace source_space, destination_space;
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);
+#define GL_GLEXT_PROTOTYPES 1
+
+#include <stdio.h>
#include <assert.h>
+#include <GL/gl.h>
+#include <GL/glext.h>
+
+#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)
{
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();
+}
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<Effect *> effects;
+ int glsl_program_num;
+ bool finalized;
+
+ // Used during the building of the effect chain.
ColorSpace current_color_space;
GammaCurve current_gamma_curve;
};
--- /dev/null
+void main()
+{
+ gl_FragColor = LAST_INPUT(tc);
+}
#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;
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)
#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");
+}
class GammaExpansionEffect : public Effect {
public:
GammaExpansionEffect();
+ std::string output_glsl();
private:
GammaCurve source_curve;
--- /dev/null
+uniform sampler2D input_tex;
+varying vec2 tc;
+
+vec4 read_input(vec2 tc)
+{
+ vec3 x = texture2D(input_tex, tc.st);
+}
+
+#define LAST_INPUT read_input
#include "lift_gamma_gain_effect.h"
+#include "util.h"
LiftGammaGainEffect::LiftGammaGainEffect()
: lift(0.0f, 0.0f, 0.0f),
register_vec3("gain", (float *)&gain);
register_float("saturation", &saturation);
}
+
+std::string LiftGammaGainEffect::output_glsl()
+{
+ return read_file("todo.glsl");
+}
class LiftGammaGainEffect : public Effect {
public:
LiftGammaGainEffect();
+ std::string output_glsl();
private:
RGBTriplet lift, gamma, gain;
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);
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();
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);
++frame;
+
draw_picture_quad(prog, frame);
glReadPixels(0, 0, WIDTH, HEIGHT, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, BUFFER_OFFSET(0));
--- /dev/null
+// Placeholder for effects that are not done yet.
+vec4 FUNCNAME(vec2 tc)
+{
+ return LAST_INPUT(tc);
+}
-#include <math.h>
+#define GL_GLEXT_PROTOTYPES 1
+
+#include <stdio.h>
+#include <assert.h>
+#include <GL/gl.h>
+#include <GL/glext.h>
+
+#include <math.h>
#include "util.h"
void hsv2rgb(float h, float s, float v, float *r, float *g, float *b)
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;
+}
+
#include <string>
+#include <GL/gl.h>
+
// 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()
#version 120
-varying vec4 tc;
+varying vec2 tc;
//varying vec3 lift, inv_gamma, gain;
//uniform vec3 gamma;
//varying vec3 inv_gamma;
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);