+ frag_shader += string("#define INPUT ") + phase->effect_ids[phase->effects.back()] + "\n";
+ frag_shader.append(read_version_dependent_file("footer", "frag"));
+
+ // Collect uniforms from all effects and output them. Note that this needs
+ // to happen after output_fragment_shader(), even though the uniforms come
+ // before in the output source, since output_fragment_shader() is allowed
+ // to register new uniforms (e.g. arrays that are of unknown length until
+ // finalization time).
+ // TODO: Make a uniform block for platforms that support it.
+ string frag_shader_uniforms = "";
+ for (unsigned i = 0; i < phase->effects.size(); ++i) {
+ Node *node = phase->effects[i];
+ Effect *effect = node->effect;
+ const string effect_id = phase->effect_ids[node];
+ for (unsigned j = 0; j < effect->uniforms_sampler2d.size(); ++j) {
+ phase->uniforms_sampler2d.push_back(effect->uniforms_sampler2d[j]);
+ phase->uniforms_sampler2d.back().prefix = effect_id;
+ frag_shader_uniforms += string("uniform sampler2D ") + effect_id
+ + "_" + effect->uniforms_sampler2d[j].name + ";\n";
+ }
+ for (unsigned j = 0; j < effect->uniforms_bool.size(); ++j) {
+ phase->uniforms_bool.push_back(effect->uniforms_bool[j]);
+ phase->uniforms_bool.back().prefix = effect_id;
+ frag_shader_uniforms += string("uniform bool ") + effect_id
+ + "_" + effect->uniforms_bool[j].name + ";\n";
+ }
+ for (unsigned j = 0; j < effect->uniforms_int.size(); ++j) {
+ phase->uniforms_int.push_back(effect->uniforms_int[j]);
+ phase->uniforms_int.back().prefix = effect_id;
+ frag_shader_uniforms += string("uniform int ") + effect_id
+ + "_" + effect->uniforms_int[j].name + ";\n";
+ }
+ for (unsigned j = 0; j < effect->uniforms_float.size(); ++j) {
+ phase->uniforms_float.push_back(effect->uniforms_float[j]);
+ phase->uniforms_float.back().prefix = effect_id;
+ frag_shader_uniforms += string("uniform float ") + effect_id
+ + "_" + effect->uniforms_float[j].name + ";\n";
+ }
+ for (unsigned j = 0; j < effect->uniforms_vec2.size(); ++j) {
+ phase->uniforms_vec2.push_back(effect->uniforms_vec2[j]);
+ phase->uniforms_vec2.back().prefix = effect_id;
+ frag_shader_uniforms += string("uniform vec2 ") + effect_id
+ + "_" + effect->uniforms_vec2[j].name + ";\n";
+ }
+ for (unsigned j = 0; j < effect->uniforms_vec3.size(); ++j) {
+ phase->uniforms_vec3.push_back(effect->uniforms_vec3[j]);
+ phase->uniforms_vec3.back().prefix = effect_id;
+ frag_shader_uniforms += string("uniform vec3 ") + effect_id
+ + "_" + effect->uniforms_vec3[j].name + ";\n";
+ }
+ for (unsigned j = 0; j < effect->uniforms_vec4.size(); ++j) {
+ phase->uniforms_vec4.push_back(effect->uniforms_vec4[j]);
+ phase->uniforms_vec4.back().prefix = effect_id;
+ frag_shader_uniforms += string("uniform vec4 ") + effect_id
+ + "_" + effect->uniforms_vec4[j].name + ";\n";
+ }
+ for (unsigned j = 0; j < effect->uniforms_vec2_array.size(); ++j) {
+ char buf[256];
+ phase->uniforms_vec2.push_back(effect->uniforms_vec2_array[j]);
+ phase->uniforms_vec2.back().prefix = effect_id;
+ snprintf(buf, sizeof(buf), "uniform vec2 %s_%s[%d];\n",
+ effect_id.c_str(), effect->uniforms_vec2_array[j].name.c_str(),
+ int(effect->uniforms_vec2_array[j].num_values));
+ frag_shader_uniforms += buf;
+ }
+ for (unsigned j = 0; j < effect->uniforms_vec4_array.size(); ++j) {
+ char buf[256];
+ phase->uniforms_vec4.push_back(effect->uniforms_vec4_array[j]);
+ phase->uniforms_vec4.back().prefix = effect_id;
+ snprintf(buf, sizeof(buf), "uniform vec4 %s_%s[%d];\n",
+ effect_id.c_str(), effect->uniforms_vec4_array[j].name.c_str(),
+ int(effect->uniforms_vec4_array[j].num_values));
+ frag_shader_uniforms += buf;
+ }
+ for (unsigned j = 0; j < effect->uniforms_mat3.size(); ++j) {
+ phase->uniforms_mat3.push_back(effect->uniforms_mat3[j]);
+ phase->uniforms_mat3.back().prefix = effect_id;
+ frag_shader_uniforms += string("uniform mat3 ") + effect_id
+ + "_" + effect->uniforms_mat3[j].name + ";\n";