FBO woes

Started by
20 comments, last by medevilenemy 11 years, 10 months ago
After doing some sanity checking with a friend of mine, I determined that I was using glgenframebuffers wrong, so I have fixed that... so now instead of getting a quad with whatever the active color is, I now see... nothing at all. The updated version of the RTT code is as follows:


float bleh = 2 * ((double)screen_width/(double)screen_height);

// set rendering destination to FBO
glBindFramebuffer(GL_FRAMEBUFFER, fbonum);

glPushAttrib(GL_VIEWPORT_BIT | GL_ENABLE_BIT);

// clear buffers
//glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

//glDepthFunc(GL_EQUAL);
glClearDepth(0.0f);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
//glLoadIdentity();
glOrtho(-0.5 * bleh, 0.5*bleh, -1, 1, 1, 0);
//gluLookAt(Position.x,Position.y,Position.z,ViewPoint.x,ViewPoint.y,ViewPoint.z,UpVector.x,UpVector.y,UpVector.z);
glViewport(0,0,screen_width, screen_height);
glEnable(GL_BLEND);
glEnable(GL_DEPTH_TEST);

//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // function for blending
glBlendFunc(GL_ONE, GL_ONE); // function for blending
glColor4d(0.0, 1.0, 1.0, 0.0);
glBegin(GL_QUADS);
glVertex3d(0.0, 0.5, 0.0);
glVertex3d(0.5, 0.5, 0.0);
glVertex3d(0.5, -0.5, 0.5);
glVertex3d(0.0, -0.5, 0.5);
glEnd();

glColor4d(1.0, 0.0, 1.0, 1.0);
glBegin(GL_QUADS);
glVertex3d(0.1, 0.5, 0.0);
glVertex3d(0.6, 0.5, 0.0);
glVertex3d(0.6, -0.5, 0.0);
glVertex3d(0.1, -0.5, 0.0);
glEnd();

glPopAttrib();
glBindFramebuffer(GL_FRAMEBUFFER, 0);



glColor4d(1.0, 1.0, 0.0, 1.0);
//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBlendFunc(GL_ONE, GL_ONE);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, rttnum);

glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-0.3,-0.3,0.0); // Bottom-Left Vertex
glTexCoord2f(1.0f, 0.0f); glVertex3f(0.3,-0.3,0.0); // Bottom-Right Vertex
glTexCoord2f(1.0f, 1.0f); glVertex3f(0.3,0.3,0.01); // Top-Right Vertex
glTexCoord2f(0.0f, 1.0f); glVertex3f(-0.3,0.3,0.01); // Top-Left Vertex
glEnd();
glDisable(GL_TEXTURE_2D);


Apologies for the silly names and stuff... its just a proof of concept so I wasn't trying to use serious names in all places.
There was a saying we had in college: Those who walk into the engineering building are never quite the same when they walk out.
Advertisement
Some random ideas:

I believe there is a restriction, that a rendertarget texture can not be bound while the FBO is bound and the FBO in turn can not be bound while the texture is bound. I could be wrong though ^^.
Anyways, try doing a

glBindTexture(GL_TEXTURE_2D, 0);

after you used the texture and before you loop back to binding the FBO.


Also, glClear(...) only affects the current viewport so you should set the viewport before doing glClear(...).


Did you use glDrawBuffers to specifiy, which RT to clear/render to?



It would really help to see the full code, including FBO setup and all the states you set for rendering!
No effect. Moved glClear stuff around and unbound whatever texture might be active right before the FBO bind, but I still see nothing. I'm currently using glBlendFunc(GL_ONE,GL_ZERO) for both stages of blending (onto tex and tex onto scene) just for testing purposes, FYI. Not familiar with glDrawBuffers.

Here's the test code I'm using:

My init stuff...

GLenum err = glewInit();
if (GLEW_OK != err)
{
exit(0);
}
else
{
if (GLEW_ARB_framebuffer_object)
{
}
}

glEnable(GL_TEXTURE_2D);
glEnable(GL_COLOR_MATERIAL);
glGenTextures(1, &rttnum);

glBindTexture(GL_TEXTURE_2D, rttnum);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); // automatic mipmap
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, screen_width, screen_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);

glBindTexture(GL_TEXTURE_2D, 0);

// create a renderbuffer object to store depth info
GLuint rboId = 1;
glGenRenderbuffers(1, &rboId);

glBindRenderbuffer(GL_RENDERBUFFER, rboId);

glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, screen_width, screen_height);

// create a framebuffer object
glGenFramebuffers(1, &fbonum);

glBindFramebuffer(GL_FRAMEBUFFER, fbonum);

// attach the texture to FBO color attachment point
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rttnum, 0);

// attach the renderbuffer to depth attachment point
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboId);

// switch back to window-system-provided framebuffer
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);


And the rendering related stuff...

float bleh = 2 * ((double)screen_width/(double)screen_height);

// Unbind any texture that might currently be bound
glBindTexture(GL_TEXTURE_2D, 0);
// set rendering destination to FBO
glBindFramebuffer(GL_FRAMEBUFFER, fbonum);

glPushAttrib(GL_VIEWPORT_BIT | GL_ENABLE_BIT);

// clear buffers
//glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

//glDepthFunc(GL_EQUAL);
glOrtho(-0.5 * bleh, 0.5*bleh, -1, 1, 1, 0);
glViewport(0,0,screen_width, screen_height);
glClearDepth(0.0f);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
//glLoadIdentity();
glEnable(GL_BLEND);
glEnable(GL_DEPTH_TEST);

//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // function for blending
//glBlendFunc(GL_ONE, GL_ONE); // function for blending
glBlendFunc(GL_ONE, GL_ZERO);
glColor4d(0.0, 1.0, 1.0, 1.0);
glBegin(GL_QUADS);
glVertex3d(0.0, 0.5, 0.0);
glVertex3d(0.5, 0.5, 0.0);
glVertex3d(0.5, -0.5, 0.5);
glVertex3d(0.0, -0.5, 0.5);
glEnd();

glColor4d(1.0, 0.0, 1.0, 1.0);
glBegin(GL_QUADS);
glVertex3d(0.1, 0.5, 0.0);
glVertex3d(0.6, 0.5, 0.0);
glVertex3d(0.6, -0.5, 0.0);
glVertex3d(0.1, -0.5, 0.0);
glEnd();

glPopAttrib();
glBindFramebuffer(GL_FRAMEBUFFER, 0);



glColor4d(1.0, 1.0, 0.0, 1.0);
//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBlendFunc(GL_ONE, GL_ZERO);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, rttnum);

glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-0.3,-0.3,0.0); // Bottom-Left Vertex
glTexCoord2f(1.0f, 0.0f); glVertex3f(0.3,-0.3,0.0); // Bottom-Right Vertex
glTexCoord2f(1.0f, 1.0f); glVertex3f(0.3,0.3,0.01); // Top-Right Vertex
glTexCoord2f(0.0f, 1.0f); glVertex3f(-0.3,0.3,0.01); // Top-Left Vertex
glEnd();
glDisable(GL_TEXTURE_2D);


glBindTexture(GL_TEXTURE_2D, 0);


[edit] Just attempted glDrawBuffer(GL_COLOR_ATTACHMENT0); right after binding the framebuffer and before drawing to it... no effect.
There was a saying we had in college: Those who walk into the engineering building are never quite the same when they walk out.
ok, so I got it working, but without automatic mipmap generation. There might be a bug in NVidia's driver implementation (see http://www.opengl.or...AP-bug-(nVidia)) but I don't have the time to look into that right now. Do you actually need that?

Here is my code. Note, that I switched the depth interval (it confused the hell out of me ^^) and removed some stuff.
I think the two important changes are proper setup of the projection matrix (you were accumulating glOrthos) and removal of automatic mipmap generation.

GLuint rttnum;
glEnable(GL_TEXTURE_2D);
glEnable(GL_COLOR_MATERIAL);
glGenTextures(1, &rttnum);
glBindTexture(GL_TEXTURE_2D, rttnum);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);//GL_LINEAR_MIPMAP_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
//glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); // automatic mipmap
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 800, 600, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
CHECKGLERROR(__FILE__, __LINE__)
glBindTexture(GL_TEXTURE_2D, 0);
// create a renderbuffer object to store depth info
GLuint rboId = 1;
glGenRenderbuffers(1, &rboId);
glBindRenderbuffer(GL_RENDERBUFFER, rboId);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, 800, 600);
GLuint fbonum;
// create a framebuffer object
glGenFramebuffers(1, &fbonum);
glBindFramebuffer(GL_FRAMEBUFFER, fbonum);
// attach the texture to FBO color attachment point
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rttnum, 0);
// attach the renderbuffer to depth attachment point
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboId);
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
std::cout << "incomplete: " << std::hex << status << std::endl;
// switch back to window-system-provided framebuffer
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
CHECKGLERROR(__FILE__, __LINE__)
bool shutdown = false;
while (!shutdown) {
// Unbind any texture that might currently be bound
glBindTexture(GL_TEXTURE_2D, 0);
// set rendering destination to FBO
glBindFramebuffer(GL_FRAMEBUFFER, fbonum);
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
std::cout << "incomplete: " << std::hex << status << std::endl;
glViewport(0,0,800, 600);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1, 1, -1, 1, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glEnable(GL_DEPTH_TEST);

glColor4d(0.0, 1.0, 1.0, 1.0);
glBegin(GL_QUADS);
glVertex3d(0.0, 0.5, 0.5);
glVertex3d(0.5, 0.5, 0.5);
glVertex3d(0.5, -0.5, 0.5);
glVertex3d(0.0, -0.5, 0.5);
glEnd();
glColor4d(1.0, 0.0, 1.0, 1.0);
glBegin(GL_QUADS);
glVertex3d(0.1, 0.5, 0.0);
glVertex3d(0.6, 0.5, 0.0);
glVertex3d(0.6, -0.5, 0.0);
glVertex3d(0.1, -0.5, 0.0);
glEnd();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
CHECKGLERROR(__FILE__, __LINE__)

glViewport(0,0,800, 600);
glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1, 1, -1, 1, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glColor4d(1.0, 1.0, 1.0, 1.0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, rttnum);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-0.3,-0.3,0.0); // Bottom-Left Vertex
glTexCoord2f(1.0f, 0.0f); glVertex3f(0.3,-0.3,0.0); // Bottom-Right Vertex
glTexCoord2f(1.0f, 1.0f); glVertex3f(0.3,0.3,0.01); // Top-Right Vertex
glTexCoord2f(0.0f, 1.0f); glVertex3f(-0.3,0.3,0.01); // Top-Left Vertex
glEnd();
glDisable(GL_TEXTURE_2D);
CHECKGLERROR(__FILE__, __LINE__)
glBindTexture(GL_TEXTURE_2D, 0);
SDL_Event event;
while (SDL_PollEvent(&event)) {
switch( event.type ) {
case SDL_QUIT:
shutdown = true;
break;
}
}
SDL_GL_SwapBuffers();
}
Thanks for the suggestion! I've tried adapting your approach to my context, with no effect. I think what is preventing it from working is my drawing of the underlying scene... Here's the code for the gameplay screen as I have it after trying to adapt your approach... This should let you see the context of the scene rendering happening so we can get them to mesh together. The setup stuff actually happens in a different source file outside the main loop. On the upside... the matrix mode changes have prevented bleedover and weirdness back into my menu screen... never really understood what modelview did before.


float bleh = 2 * ((double)screen_width/(double)screen_height);

// Unbind any texture that might currently be bound
glBindTexture(GL_TEXTURE_2D, 0);

// set rendering destination to FBO
glBindFramebuffer(GL_FRAMEBUFFER, fbonum);

// Set stuff up
glViewport(0,0,screen_width, screen_height);
glClearDepth(0.0f);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-0.5 * bleh, 0.5*bleh, -1, 1, 1, 0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

//glTranslatef(0.0, 0.0, 0.0);

//glLoadIdentity();
glEnable(GL_ALPHA_TEST);
glEnable(GL_BLEND);
glEnable(GL_DEPTH_TEST);

//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // function for blending
//glBlendFunc(GL_ONE, GL_ONE); // function for blending
//glBlendFunc(GL_ONE, GL_ZERO);
glColor4d(0.0, 1.0, 1.0, 1.0);
glBegin(GL_QUADS);
glVertex3d(0.0, 0.5, 0.0);
glVertex3d(0.5, 0.5, 0.0);
glVertex3d(0.5, -0.5, 0.0);
glVertex3d(0.0, -0.5, 0.0);
glEnd();

glColor4d(1.0, 0.0, 1.0, 1.0);
glBegin(GL_QUADS);
glVertex3d(0.1, 0.5, 0.0);
glVertex3d(0.6, 0.5, 0.0);
glVertex3d(0.6, -0.5, 0.0);
glVertex3d(0.1, -0.5, 0.0);
glEnd();

glBindFramebuffer(GL_FRAMEBUFFER, 0);


// DRAW MAIN SCENE STARTING HERE
glViewport(0,0,screen_width,screen_height);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearDepth(1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
float width = 2 * ((double)screen_width/(double)screen_height);
glOrtho(-0.5 * width, 0.5*width, -1, 1, 1, 0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND); // allows blending (transparency)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // function for blending
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH); // allows smooth shading (gradients)
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.0);

//glLoadIdentity();
Camera.Render();

// FOR REFERENCE: Less Z = Closer to camera, Bigger Z = farther away
glColor4d(0.0, 1.0, 0.0, 1.0);
if(player != NULL)
{
glRasterPos3d(Camera.GetX() - 1.0, Camera.GetY() - 0.9, 0.01);
DrawString(listBase[5], "FPS: %g, PLAYER POSITION: %g, %g MESSAGES: %i", fps, player->Get_X(), player->Get_Y(), msthissec);
}
if(interactable_nearby)
{
glColor4d(0.2, 0.2, 1.0, 0.9);
glRasterPos3d(Camera.GetX()-0.05, Camera.GetY() - 0.85, 0.01);
DrawString(listBase[2], "Press [%c] key to interact", interaction_key);
}

AudioHandler();
SceneryHandler();
SpriteHandler();
PlayerHandler();
triggers.Update();
ScriptHandler();


glColor4d(1.0, 1.0, 0.0, 1.0);
//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBlendFunc(GL_ONE, GL_ZERO);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, rttnum);

glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-0.3,-0.3,0.01); // Bottom-Left Vertex
glTexCoord2f(1.0f, 0.0f); glVertex3f(0.3,-0.3,0.01); // Bottom-Right Vertex
glTexCoord2f(1.0f, 1.0f); glVertex3f(0.3,0.3,0.01); // Top-Right Vertex
glTexCoord2f(0.0f, 1.0f); glVertex3f(-0.3,0.3,0.01); // Top-Left Vertex
glEnd();
glDisable(GL_TEXTURE_2D);


glBindTexture(GL_TEXTURE_2D, 0);


Once we get this working, I can take the method and adapt it to practical use for the effect I want, but for now I have it all in one function for ease of fiddling.
There was a saying we had in college: Those who walk into the engineering building are never quite the same when they walk out.
Your z interval goes from 1.0f to 0.0f and you draw your quads at 0.0f. This may lead to them being culled by the far plane. Maybe you can draw them at 0.5f?
You will also need glDepthFunc(GEQUAL); because of the inverted depth interval.

BTW: Your comment
// FOR REFERENCE: Less Z = Closer to camera, Bigger Z = farther away

is not correct. The way you set up your projection matrix a z value of 1.0f is as close to the camera as possible, while a z value of 0.0f is as far away as possible (Ignoring for now, that for orthogonal projections this rather depends on the depth test, then on some actual "positioning").

I already asked this in a previous post, but are you sure that you want an inverted depth interval? This is so uncommon, that I have never seen this before.
For the Gl ortho call for the fbo, I swapped the Z planes around and then set the depth func to LEQUAL. it now seems to draw to the texture such that I can see it. However, anything drawn at a z position greater than 0 is invisible, and when I draw the boxes such that they overlap even in the slightest, only the box drawn later is visible (with the one being drawn first becoming completely invisible). We're making progress! Though we're not quite there yet.

[edit] For now, I'm going to leave the main scene ortho the way it is, as it has always worked before. I wonder if the reason it works the way I expect is because of the camera view angle. Anyway, that's unimportant at the moment.
There was a saying we had in college: Those who walk into the engineering building are never quite the same when they walk out.
That sounds good! With the normal z buffer setup you need to set glClearDepth(1.0f); before glClear-ing the depth buffer. Then it should work.

So for glOrtho(..., 0.0f, 1.0f): (I prefer this ^^)
glClearDepth(1.0f); // before glClear(... | GL_DEPTH_BUFFER_BIT)
glDepthFunc(GL_LEQUAL);

and for glOrtho(... 1.0f, 0.0f);
glClearDepth(0.0f); // before glClear(... | GL_DEPTH_BUFFER_BIT)
glDepthFunc(GL_GEQUAL);


I wonder if the reason it works the way I expect is because of the camera view angle.[/quote]

Yes, that is what I meant to hint in the previous post. If you look at a picture with perspective projection, you automatically assume the camera to be located at the focal point and if the depth test is the wrong way around, the image just feels wrong. For orthogonal projections however, where you don't have a view angle and thus no focal point, the camera could be located at either end of the view frustrum and the only thing that decides it for the human eye is the depth test.

You can of course stick with the inverted depth interval, but keep in mind that some aspects of the fixed function pipeline (for example fog) might not work as intended.
Switching the depth clear had no effect, I still only see the box drawn second. FYI I have blend func within the context set to GL_ONE, GL_ZERO, but changing that has no apparant effect. I'll probably stick with the inverted depth interval for now, because I'd rather not have to flip around everything I'm rendering, but I'll consider doing so if it ever causes a problem.
There was a saying we had in college: Those who walk into the engineering building are never quite the same when they walk out.
<bump?>
There was a saying we had in college: Those who walk into the engineering building are never quite the same when they walk out.

This topic is closed to new replies.

Advertisement