- if (movit_debug_level == MOVIT_DEBUG_ON) {
- // Output shader to a temporary file, for easier debugging.
- static int compiled_shader_num = 0;
- char filename[256];
- sprintf(filename, "chain-%03d.frag", compiled_shader_num++);
- FILE *fp = fopen(filename, "w");
- if (fp == NULL) {
- perror(filename);
- exit(1);
- }
- fprintf(fp, "%s\n", frag_shader.c_str());
- fclose(fp);
- }
-
- GLuint glsl_program_num = glCreateProgram();
- GLuint vs_obj = compile_shader(read_file("vs.vert"), GL_VERTEX_SHADER);
- GLuint fs_obj = compile_shader(frag_shader, GL_FRAGMENT_SHADER);
- glAttachShader(glsl_program_num, vs_obj);
- check_error();
- glAttachShader(glsl_program_num, fs_obj);
- check_error();
- glLinkProgram(glsl_program_num);
- check_error();
-
- Phase *phase = new Phase;
- phase->glsl_program_num = glsl_program_num;
- phase->vertex_shader = vs_obj;
- phase->fragment_shader = fs_obj;
- phase->input_needs_mipmaps = input_needs_mipmaps;
- phase->inputs = true_inputs;
- phase->effects = sorted_effects;
-
- return phase;
+ // 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];
+ extract_uniform_declarations(effect->uniforms_sampler2d, "sampler2D", effect_id, &phase->uniforms_sampler2d, &frag_shader_uniforms);
+ extract_uniform_declarations(effect->uniforms_bool, "bool", effect_id, &phase->uniforms_bool, &frag_shader_uniforms);
+ extract_uniform_declarations(effect->uniforms_int, "int", effect_id, &phase->uniforms_int, &frag_shader_uniforms);
+ extract_uniform_declarations(effect->uniforms_float, "float", effect_id, &phase->uniforms_float, &frag_shader_uniforms);
+ extract_uniform_declarations(effect->uniforms_vec2, "vec2", effect_id, &phase->uniforms_vec2, &frag_shader_uniforms);
+ extract_uniform_declarations(effect->uniforms_vec3, "vec3", effect_id, &phase->uniforms_vec3, &frag_shader_uniforms);
+ extract_uniform_declarations(effect->uniforms_vec4, "vec4", effect_id, &phase->uniforms_vec4, &frag_shader_uniforms);
+ extract_uniform_array_declarations(effect->uniforms_vec2_array, "vec2", effect_id, &phase->uniforms_vec2, &frag_shader_uniforms);
+ extract_uniform_array_declarations(effect->uniforms_vec4_array, "vec4", effect_id, &phase->uniforms_vec4, &frag_shader_uniforms);
+ extract_uniform_declarations(effect->uniforms_mat3, "mat3", effect_id, &phase->uniforms_mat3, &frag_shader_uniforms);
+ }
+
+ frag_shader = frag_shader_header + frag_shader_uniforms + frag_shader;
+
+ string vert_shader = read_version_dependent_file("vs", "vert");
+ phase->glsl_program_num = resource_pool->compile_glsl_program(vert_shader, frag_shader);
+
+ // Collect the resulting location numbers for each uniform.
+ collect_uniform_locations(phase->glsl_program_num, &phase->uniforms_sampler2d);
+ collect_uniform_locations(phase->glsl_program_num, &phase->uniforms_bool);
+ collect_uniform_locations(phase->glsl_program_num, &phase->uniforms_int);
+ collect_uniform_locations(phase->glsl_program_num, &phase->uniforms_float);
+ collect_uniform_locations(phase->glsl_program_num, &phase->uniforms_vec2);
+ collect_uniform_locations(phase->glsl_program_num, &phase->uniforms_vec3);
+ collect_uniform_locations(phase->glsl_program_num, &phase->uniforms_vec4);
+ collect_uniform_locations(phase->glsl_program_num, &phase->uniforms_mat3);