PDA

View Full Version : GLSL multitexturing question with FBO



marmots
06-13-2011, 02:36 PM
I am having difficulty performing the following tasks (highlights are what I have issues with):
1. Creating three textures (we'll say a,b, and c)
2. Create a depth buffer
3. Binding those three textures and the depth buffer to a fbo
4. Loading data into the three textures (really only need to load into a and b)
5. Rendering two textures (say 'a' and 'b') two the third texture c - for this I use a FS
6. Now render texture c on screen


The following is my source (following the above outline):

1. Texture creation (texName is actually replaced by t1, t2,t3. data in "image" is a black and white checkerboard that is renderable - I have rendered a single texture with the standard pipeline and it displays as I expect it to):

GLuint texName;
glGenTextures(1, &texName);
glBindTexture(GL_TEXTURE_2D, texName);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, 64,
64, 0, GL_RGBA, GL_FLOAT, image);


2. Depth Buffer :

glGenRenderbuffersEXT(1, &depthBuffer);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthBuffer);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, 64, 64);


3. Frame buffer creation and binding:

glGenFramebuffersEXT(1,&fbo);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, depthBuffer);

// Bind the texture to the FBO
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,GL_CO LOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D,t1,0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,GL_CO LOR_ATTACHMENT1_EXT,
GL_TEXTURE_2D,t2,0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,GL_CO LOR_ATTACHMENT2_EXT,
GL_TEXTURE_2D,t3,0);

4. Specifying the 'draw texture' and binding the 'source' textures

glDrawBuffer(GL_COLOR_ATTACHMENT2_EXT);

glBindTexture(GL_TEXTURE_2D,t1);
glBindTexture(GL_TEXTURE_2D,t2);
//GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); returns no error here - the buffer is created correctly


5. Rendering t1 and t2 to t3 -this section does not work

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);

glDrawBuffer(GL_COLOR_ATTACHMENT2_EXT);

glPushAttrib(GL_VIEWPORT_BIT);
glViewport(0,0,64, 64);

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.0f,0.0f,0.0f,0.5f);

glLoadIdentity();


glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D,t1);
glEnable(GL_TEXTURE_2D);

glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D,t2);
glEnable(GL_TEXTURE_2D);

glUseProgram(program);


glBegin(GL_QUADS);
//lower left
glTexCoord2f(0, 0);
glVertex2f(-1.0, -1.0);
//upper left
glTexCoord2f(0, 1.0);
glVertex2f(-1.0, 1.0);
//upper right
glTexCoord2f(1.0, 1.0);
glVertex2f(1.0, 1.0);
//lower right
glTexCoord2f(1.0, 0);
glVertex2f(1.0, -1.0);
glEnd();

glDisable(GL_TEXTURE_2D);

glUseProgram(0);

glPopAttrib();
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);



6. Rendering t3 (now that we have rendered t1 and t2 to it

glClearColor(0.0f,0.0f,0.0f,0.5f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
//glUseProgram(program);
glEnable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, t3);

glBegin(GL_QUADS);
//lower left
glTexCoord2f(0, 0);
glVertex2f(-1.0, -1.0);
//upper left
glTexCoord2f(0, 1.0);
glVertex2f(-1.0, 1.0);
//upper right
glTexCoord2f(1.0, 1.0);
glVertex2f(1.0, 1.0);
//lower right
glTexCoord2f(1.0, 0);
glVertex2f(1.0, -1.0);
glEnd();

glDisable(GL_TEXTURE_2D);


This is my FS:



uniform sampler2D tex1;
uniform sampler2D tex2;
uniform sampler2D tex3;
void main() {
vec4 s1 = texture2D(tex1, gl_TexCoord[0].st);
vec4 s2 = texture2D(tex2, gl_TexCoord[0].st + vec2(0.03125, 0.03125));
gl_FragColor = mix(vec4(1, s1.g, s1.b, 0.5), vec4(s2.r, s2.g, 1, 0.5), 0.5);
}


and how I set the uniforms ( which I assume if they do not vary at any time during the lifetime, can be set once):


glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,t1);
GLuint t1Location = glGetUniformLocation(program, "tex1");

glActiveTexture(GL_TEXTURE1);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,t2);
GLuint t2Location = glGetUniformLocation(program, "tex2");

glActiveTexture(GL_TEXTURE2);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,t3);
GLuint t3Location = glGetUniformLocation(program, "tex3");

glUniform1i(t1Location, 0);
glUniform1i(t2Location, 1);
glUniform1i(t3Location, 2);


This is the *correct* product if I 'glUseProgram(program)' on the rendering pass referenced in section 6 (instead of trying to render to t3 in one pass, and then render t3 directly in the second pass):
http://imgur.com/UImzn

When I try to render to t3 and then render t3 to the screen I get a black screen.

Thank you for listening and hopefully someone can yell at me for using a glEnable() where I wasn't and everything will work.

marmots
06-13-2011, 07:16 PM
I have solved this problem by modifying sections 5 and 6 - I followed instructions found on this page (http://www.flashbang.se/archives/48) and was able to render how I wanted. The only thing I need to fix is the positioning, but this is trivial compared to the other task.

Fixes:

Section 5:


glViewport(0,0,64,64);

glBindTexture(GL_TEXTURE_2D,0);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);

glClearColor(0.0f,0.0f,0.0f,0.5f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glLoadIdentity();

glUseProgram(program);


glBegin(GL_QUADS);
//lower left
glTexCoord2f(0, 0);
glVertex2f(-1.0, -1.0);
//upper left
glTexCoord2f(0, 1.0);
glVertex2f(-1.0, 1.0);
//upper right
glTexCoord2f(1.0, 1.0);
glVertex2f(1.0, 1.0);
//lower right
glTexCoord2f(1.0, 0);
glVertex2f(1.0, -1.0);
glEnd();

glUseProgram(0);

glEnable(GL_TEXTURE_2D);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);


and...

Section 6 :



glClearColor(0.0f,0.0f,0.0f,0.5f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glBindTexture(GL_TEXTURE_2D, t3);

glViewport(0,0,width,height);

glLoadIdentity();

glBegin(GL_QUADS);
//lower left
glTexCoord2f(0, 0);
glVertex2f(-1.0, -1.0);
//upper left
glTexCoord2f(0, 1.0);
glVertex2f(-1.0, 1.0);
//upper right
glTexCoord2f(1.0, 1.0);
glVertex2f(1.0, 1.0);
//lower right
glTexCoord2f(1.0, 0);
glVertex2f(1.0, -1.0);
glEnd();

glDisable(GL_TEXTURE_2D);

glutSwapBuffers();


So it did kind of come down to a bad glEnable placement! I hope this helps someone in the future.