+ // Construct the GLSL programs. We end a program every time we come
+ // to an effect marked as "needs many samples" (ie. "please let me
+ // sample directly from a texture, with no arithmetic in-between"),
+ // and of course at the end.
+ unsigned start = 0;
+ for (unsigned i = 0; i < effects.size(); ++i) {
+ if (effects[i]->needs_texture_bounce() && i != start) {
+ phases.push_back(compile_glsl_program(start, i));
+ start = i;
+ }
+ }
+ phases.push_back(compile_glsl_program(start, effects.size()));
+
+ // If we have more than one phase, we need intermediate render-to-texture.
+ // Construct an FBO, and then as many textures as we need.
+ if (phases.size() > 1) {
+ glGenFramebuffers(1, &fbo);
+
+ unsigned num_textures = std::max<int>(phases.size() - 1, 2);
+ glGenTextures(num_textures, temp_textures);
+
+ for (unsigned i = 0; i < num_textures; ++i) {
+ glBindTexture(GL_TEXTURE_2D, temp_textures[i]);
+ check_error();
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ check_error();
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ check_error();
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ check_error();
+ }
+ }
+
+ // Translate the input format to OpenGL's enums.
+ GLenum internal_format;