From: Steinar H. Gunderson Date: Mon, 1 Oct 2012 16:20:35 +0000 (+0200) Subject: Output convenience uniforms per effect. Also, do not rely on the preprocessor support... X-Git-Tag: 1.0~472 X-Git-Url: https://git.sesse.net/?p=movit;a=commitdiff_plain;h=8f070dcdd579e19e092a6619115f4b084fbb2c33 Output convenience uniforms per effect. Also, do not rely on the preprocessor supporting token pasting anymore. --- diff --git a/effect.cpp b/effect.cpp index f89b1a9..927acd5 100644 --- a/effect.cpp +++ b/effect.cpp @@ -1,3 +1,4 @@ +#include #include #include #include "effect.h" @@ -47,3 +48,24 @@ void Effect::register_vec3(const std::string &key, float *values) params_vec3[key] = values; } +// Output convenience uniforms for each parameter. +// These will be filled in per-frame. +std::string Effect::output_convenience_uniforms() +{ + std::string output = ""; + for (std::map::const_iterator it = params_float.begin(); + it != params_float.end(); + ++it) { + char buf[256]; + sprintf(buf, "uniform float PREFIX(%s);\n", it->first.c_str()); + output.append(buf); + } + for (std::map::const_iterator it = params_vec3.begin(); + it != params_vec3.end(); + ++it) { + char buf[256]; + sprintf(buf, "uniform vec3 PREFIX(%s);\n", it->first.c_str()); + output.append(buf); + } + return output; +} diff --git a/effect.h b/effect.h index 623915b..c53a155 100644 --- a/effect.h +++ b/effect.h @@ -18,6 +18,8 @@ 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_convenience_uniforms(); virtual std::string output_glsl() = 0; // Neither of these take ownership. diff --git a/effect_chain.cpp b/effect_chain.cpp index 32ee2ce..50fe599 100644 --- a/effect_chain.cpp +++ b/effect_chain.cpp @@ -1,6 +1,7 @@ #define GL_GLEXT_PROTOTYPES 1 #include +#include #include #include @@ -68,6 +69,47 @@ Effect *EffectChain::add_effect(EffectId effect_id) return effect; } +// GLSL pre-1.30 doesn't support token pasting. Replace PREFIX(x) with _x. +std::string replace_prefix(const std::string &text, const std::string &prefix) +{ + std::string output; + size_t start = 0; + + while (start < text.size()) { + size_t pos = text.find("PREFIX(", start); + if (pos == std::string::npos) { + output.append(text.substr(start, std::string::npos)); + break; + } + + output.append(text.substr(start, pos - start)); + output.append(prefix); + output.append("_"); + + pos += strlen("PREFIX("); + + // Output stuff until we find the matching ), which we then eat. + int depth = 1; + size_t end_arg_pos = pos; + while (end_arg_pos < text.size()) { + if (text[end_arg_pos] == '(') { + ++depth; + } else if (text[end_arg_pos] == ')') { + --depth; + if (depth == 0) { + break; + } + } + ++end_arg_pos; + } + output.append(text.substr(pos, end_arg_pos - pos)); + ++end_arg_pos; + assert(depth == 0); + start = end_arg_pos; + } + return output; +} + void EffectChain::finalize() { std::string frag_shader = read_file("header.glsl"); @@ -77,9 +119,9 @@ void EffectChain::finalize() 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 += replace_prefix(effects[i]->output_convenience_uniforms(), effect_id); + frag_shader += replace_prefix(effects[i]->output_glsl(), effect_id); frag_shader += "#undef PREFIX\n"; frag_shader += "#undef FUNCNAME\n"; frag_shader += std::string("#define LAST_INPUT ") + effect_id + "\n";