assert(middle->incoming_links.size() == middle->effect->num_inputs());
}
+GLenum EffectChain::get_input_sampler(Node *node, unsigned input_num) const
+{
+ assert(node->effect->needs_texture_bounce());
+ assert(input_num < node->incoming_links.size());
+ assert(node->incoming_links[input_num]->bound_sampler_num >= 0);
+ assert(node->incoming_links[input_num]->bound_sampler_num < 8);
+ return GL_TEXTURE0 + node->incoming_links[input_num]->bound_sampler_num;
+}
+
void EffectChain::find_all_nonlinear_inputs(Node *node, vector<Node *> *nonlinear_inputs)
{
if (node->output_gamma_curve == GAMMA_LINEAR &&
for (unsigned i = 0; i < deps.size(); ++i) {
bool start_new_phase = false;
- // FIXME: If we sample directly from a texture, we won't need this.
- if (node->effect->needs_texture_bounce()) {
+ if (node->effect->needs_texture_bounce() &&
+ !deps[i]->effect->is_single_texture()) {
start_new_phase = true;
}
if (deps[i]->outgoing_links.size() > 1) {
- if (deps[i]->effect->num_inputs() > 0) {
+ if (!deps[i]->effect->is_single_texture()) {
// More than one effect uses this as the input,
// and it is not a texture itself.
// The easiest thing to do (and probably also the safest
// and then let the next passes read from that.
start_new_phase = true;
} else {
+ assert(deps[i]->effect->num_inputs() == 0);
+
// For textures, we try to be slightly more clever;
// if none of our outputs need a bounce, we don't bounce
// but instead simply use the effect many times.
}
const GLuint glsl_program_num = phases[phase]->glsl_program_num;
+ check_error();
glUseProgram(glsl_program_num);
check_error();
for (unsigned sampler = 0; sampler < phases[phase]->inputs.size(); ++sampler) {
glActiveTexture(GL_TEXTURE0 + sampler);
Node *input = phases[phase]->inputs[sampler];
+ input->bound_sampler_num = sampler;
glBindTexture(GL_TEXTURE_2D, output_textures[input->phase]);
check_error();
if (phases[phase]->input_needs_mipmaps) {
unsigned sampler_num = phases[phase]->inputs.size();
for (unsigned i = 0; i < phases[phase]->effects.size(); ++i) {
Node *node = phases[phase]->effects[i];
+ unsigned old_sampler_num = sampler_num;
node->effect->set_gl_state(glsl_program_num, phases[phase]->effect_ids[node], &sampler_num);
check_error();
+
+ if (node->effect->is_single_texture()) {
+ assert(sampler_num - old_sampler_num == 1);
+ node->bound_sampler_num = old_sampler_num;
+ } else {
+ node->bound_sampler_num = -1;
+ }
}
// Now draw!
float vertices[] = {
+ 0.0f, 1.0f,
0.0f, 0.0f,
- 1.0f, 0.0f,
1.0f, 1.0f,
- 0.0f, 1.0f
+ 1.0f, 0.0f
};
- int position_attrib = glGetAttribLocation(glsl_program_num, "position");
- assert(position_attrib != -1);
- glEnableVertexAttribArray(position_attrib);
+ GLuint vao;
+ glGenVertexArrays(1, &vao);
check_error();
- glVertexAttribPointer(position_attrib, 2, GL_FLOAT, GL_FALSE, 0, vertices);
+ glBindVertexArray(vao);
check_error();
- int texcoord_attrib = glGetAttribLocation(glsl_program_num, "texcoord");
- if (texcoord_attrib != -1) {
- glEnableVertexAttribArray(texcoord_attrib);
- check_error();
- glVertexAttribPointer(texcoord_attrib, 2, GL_FLOAT, GL_FALSE, 0, vertices); // Same as texcoords.
- check_error();
- }
+ GLuint position_vbo = fill_vertex_attribute(glsl_program_num, "position", 2, GL_FLOAT, sizeof(vertices), vertices);
+ GLuint texcoord_vbo = fill_vertex_attribute(glsl_program_num, "texcoord", 2, GL_FLOAT, sizeof(vertices), vertices); // Same as vertices.
- glDrawArrays(GL_QUADS, 0, 4);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
check_error();
+ cleanup_vertex_attribute(glsl_program_num, "position", position_vbo);
+ cleanup_vertex_attribute(glsl_program_num, "texcoord", texcoord_vbo);
+
glUseProgram(0);
check_error();
- glDisableVertexAttribArray(position_attrib);
- check_error();
- if (texcoord_attrib != -1) {
- glDisableVertexAttribArray(texcoord_attrib);
- check_error();
- }
for (unsigned i = 0; i < phases[phase]->effects.size(); ++i) {
Node *node = phases[phase]->effects[i];
node->effect->clear_gl_state();
}
+
+ glDeleteVertexArrays(1, &vao);
+ check_error();
}
for (map<Phase *, GLuint>::const_iterator texture_it = output_textures.begin();