PDA

View Full Version : Feedback effect using FBO, textures and shaders



Jose Maria
09-19-2011, 10:56 AM
Hi!

I am trying to make a feedback loop using a FBO with three textures attached to it, and a couple of shaders. But all I get is a black screen...

The idea is to render the "final texture" to the first two textures, one of them rotated and scaled. Then actually create the "final texture" with a mixture of the previous two, this done thanks to a GLSL program.

Here I initialize the GLSL program, the textures and the FBO. I also get the locations to the two textures. There seems to be no problem in this piece of code, I think.



void Initialization()
{
program_texture = LoadShader ("texture.vert", "texture.frag");
printProgramInfoLog (program_texture);

loc_tex[0] = glGetUniformLocation (program_texture, "tex_0");
loc_tex[1] = glGetUniformLocation (program_texture, "tex_1");

glEnable(GL_TEXTURE_2D);
glGenTextures(1, &texture[0]);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_FLOAT, NULL);

glGenTextures(1, &texture[1]);
glBindTexture(GL_TEXTURE_2D, texture[1]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_FLOAT, NULL);

glGenTextures(1, &texture[2]);
glBindTexture(GL_TEXTURE_2D, texture[2]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_FLOAT, NULL);

glBindTexture (GL_TEXTURE_2D, 0);

glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[0], 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, texture[1], 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, texture[2], 0);

glBindFramebuffer(GL_FRAMEBUFFER, 0);
}


Then, I render as follows:



void Rendering()
{
glUseProgram(0);

glBindFramebuffer (GL_FRAMEBUFFER, fbo);

glDrawBuffer (GL_COLOR_ATTACHMENT0);

glClear (GL_COLOR_BUFFER_BIT);

glLoadIdentity();

glBindTexture(GL_TEXTURE_2D, texture[2]);

glPushMatrix();
glScalef(scale, scale, 1.0);
glRotatef(angle, 0.0, 0.0, 1.0);
glColor3f(brightness, brightness, brightness);
glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0); glVertex2f(-1.0, -1.0);
glTexCoord2f(1.0, 0.0); glVertex2f(1.0, -1.0);
glTexCoord2f(1.0, 1.0); glVertex2f(1.0, 1.0);
glTexCoord2f(0.0, 1.0); glVertex2f(-1.0, 1.0);
glEnd();
glPopMatrix();

glBindTexture (GL_TEXTURE_2D, 0);

glDrawBuffer (GL_COLOR_ATTACHMENT1);

glClear (GL_COLOR_BUFFER_BIT);

glLoadIdentity();

glBindTexture(GL_TEXTURE_2D, texture[2]);

glPushMatrix();
glColor3f (1.0, 1.0, 1.0);
glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0); glVertex2f(-1.0, -1.0);
glTexCoord2f(1.0, 0.0); glVertex2f(1.0, -1.0);
glTexCoord2f(1.0, 1.0); glVertex2f(1.0, 1.0);
glTexCoord2f(0.0, 1.0); glVertex2f(-1.0, 1.0);
glEnd();
glPopMatrix();

glBindTexture (GL_TEXTURE_2D, 0);

glDrawBuffer (GL_COLOR_ATTACHMENT2);

glClear (GL_COLOR_BUFFER_BIT);

glLoadIdentity();

glUseProgram (program_texture);

glActiveTexture (GL_TEXTURE0);
glBindTexture (GL_TEXTURE_2D, texture[0]);
glUniform1i (loc_tex[0], 0);
glActiveTexture (GL_TEXTURE1);
glBindTexture (GL_TEXTURE_2D, texture[1]);
glUniform1i (loc_tex[1], 1);

glPushMatrix();
glBegin(GL_QUADS);
glVertex2f (-1.0, -1.0);
glVertex2f (1.0, -1.0);
glVertex2f (1.0, 1.0);
glVertex2f (-1.0, 1.0);
glEnd();
glPopMatrix();

glUseProgram(0);

if (drawGen){ DrawGenerator(); drawGen = false; }

glBindFramebuffer (GL_FRAMEBUFFER, 0);

glClear (GL_COLOR_BUFFER_BIT);

glLoadIdentity();

glBindTexture (GL_TEXTURE_2D, texture[2]);

glPushMatrix();
glColor3f (1.0, 1.0, 1.0);
glBegin(GL_QUADS);
glTexCoord2f (0.0, 0.0); glVertex2f (-1.0, -1.0);
glTexCoord2f (1.0, 0.0); glVertex2f (1.0, -1.0);
glTexCoord2f (1.0, 1.0); glVertex2f (1.0, 1.0);
glTexCoord2f (0.0, 1.0); glVertex2f (-1.0, 1.0);
glEnd();
glPopMatrix();

glBindTexture (GL_TEXTURE_2D, 0);

glfwSwapBuffers();
}


And the shaders are:



// Vertex shader

void main()
{
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_TexCoord[1] = gl_MultiTexCoord1;
gl_Position = gl_ProjectionMatrix*gl_Vertex;
}



// Fragment shader

uniform sampler2D tex_0;
uniform sampler2D tex_1;

void main()
{
vec4 color_0 = texture2D (tex_0, gl_TexCoord[0].st);
vec4 color_1 = texture2D (tex_1, gl_TexCoord[1].st);

gl_FragColor = 0.5*(color_0+color_1);
}


There is a call in the rendering to a function named DrawGenerator(), which is supposed to give a first input to the loop. If I comment out the line that calls the GLSL program and the next six lines then the generator gets drawn, so I guess the problem is related to GLSL.

Perhaps I am wrongly assuming that by drawing a quad it will get the colors as described in the fragment shader?

Can you help me, or tell me another way of achieving this effect?