Jump to content
  • Advertisement
Sign in to follow this  
KarimIO

OpenGL OpenGL: Depth Attachment breaks Framebuffer

This topic is 565 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I need a fresh pair of eyes. While working on rewriting my engine, I stumbled upon this issue while writing the Deferred Rendering path. The framebuffer displays only if I don't use a depth attachment, which means that the rendering is faulty, but if I do, all the outputs are blank. I wrote a lot of graphics handling classes but I broke down the code here:

Initialization:

glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_CULL_FACE);
glClearColor(0, 0, 0, 1);
glViewport(0, 0, 1024, 768);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
ShaderPreparation();

numBuffer = 3;
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
numBuffers = numBuffer;
targetBuffer = 0;
textures = new unsigned int[numBuffers];
glGenTextures(numBuffers, textures);

 

This is done three times:

glBindTexture(GL_TEXTURE_2D, textures[targetBuffer]);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, colorType, width, height, 0, colorFormat, colorDataType, NULL);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + targetBuffer, GL_TEXTURE_2D, textures[targetBuffer], 0);
targetBuffer++;

Then I create the Depth Attachment:

glGenTextures(1, &renderBuffer);
glBindTexture(GL_TEXTURE_2D, renderBuffer);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, renderBuffer, 0);

 

Forgot the last bit of the FBO:

GLenum *DrawBuffers = new GLenum[numBuffers];
for (size_t i = 0; i < numBuffers; i++)
DrawBuffers = GL_COLOR_ATTACHMENT0 + i;

glDrawBuffers(numBuffers, DrawBuffers);

// Report errors
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
fprintf(stderr, "Framebuffer Error. Status 0x%x\n", status);
}

// Unbind
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);

 

Finally, my drawing (all calculations for geometry shader happens before this):

geometryShader->Use();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
graphicsWrapper->render(Geometry);

int val[3] = { 0,1,2 };
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
deferredShader->Use();

glActiveTexture(GL_TEXTURE0 + 0);
glBindTexture(GL_TEXTURE_2D, textures[0]);
glActiveTexture(GL_TEXTURE0 + 1);
glBindTexture(GL_TEXTURE_2D, textures[1]);
glActiveTexture(GL_TEXTURE0 + 2);
glBindTexture(GL_TEXTURE_2D, textures[2]);

// I use this system so it's compatible with Uniform Buffer
// Objects and the rendering code of other graphics languages
deferredShader->PassData(&val);
deferredShader->SetInteger();
deferredShader->SetInteger();
deferredShader->SetInteger();

glClear(GL_COLOR_BUFFER_BIT);

vaoQuad->Bind();
graphicsWrapper->DrawVertexArray(4);
vaoQuad->Unbind();

Note that my code is much more object oriented than this, and I had to take a lot of this code out of context. My question is, why does attaching the depth attachment to the framebuffer cause the framebuffer to blank, while removing it works, and how do I fix it?

I know that it's not a renderbuffer, I just called the depth texture that because it USED to be a renderbuffer, and I forgot to change the name.

Share this post


Link to post
Share on other sites
Advertisement

no no no baby you dont attach depthbuffer to fbo like that: first of all after creating fbo you create RBO (render buffer object), you attach depthbuff tex to rbo, and then you define that glFramebufferTexture2D thing, also remember that your framebuffer doesn't have depth testing and depth equation defined, so you do (base gl setting)

glBindFramebuffer(GL_FRAMEBUFFER, FBO_ID);

glDepthFunc(GL_LEQUAL);

glEnable(GL_DEPTH_TEST);

//draw

glDisable(GL_DEPTH_TEST);

glBindFramebuffer(GL_FRAMEBUFFER, 0);

 

also you can set depth testing only once (while fbo binded) and you wont have to call depthfunc and glenable every frame.

int w = 512;
int h = 512;

	unsigned int FBO_TEX;
	unsigned int FBO_DEPTH;
	unsigned int FBO_ID;
	unsigned int RBO_ID;


                        glGenTextures(1, &FBO_TEX);
			glBindTexture(GL_TEXTURE_2D, FBO_TEX);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);


			glGenTextures(1, &FBO_DEPTH);
			glBindTexture(GL_TEXTURE_2D, FBO_DEPTH);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
			glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);

			glGenFramebuffers(1, &FBO_ID);
			glGenRenderbuffers(1, &RBO_ID);
			glBindRenderbuffer(GL_RENDERBUFFER, RBO_ID);
			glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 512, 512);
			glBindFramebuffer(GL_FRAMEBUFFER, FBO_ID);
			glBindTexture(GL_TEXTURE_2D, FBO_TEX);
			glFramebufferRenderbuffer(GL_FRAMEBUFFER,
			                          GL_DEPTH_ATTACHMENT,
			                          GL_RENDERBUFFER,
									  RBO_ID);
			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, FBO_TEX, 0);
			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, FBO_DEPTH, 0);
			glBindFramebuffer(GL_FRAMEBUFFER, 0);

just be sure to set GL_DEPTH_COMPONENT correct i mean use only one that your device is using for your app

 

the code is a part of OGL ES 2.0 so i use GL_RGBA and GL_DEPTH_COMPONENT16 for texture

Edited by WiredCat

Share this post


Link to post
Share on other sites

no no no baby you dont attach depthbuffer to fbo like that: first of all after creating fbo you create RBO (render buffer object), you attach depthbuff tex to rbo, and then you define that glFramebufferTexture2D thing, also remember that your framebuffer doesn't have depth testing and depth equation defined, so you do (base gl setting)

glBindFramebuffer(GL_FRAMEBUFFER, FBO_ID);

glDepthFunc(GL_LEQUAL);

glEnable(GL_DEPTH_TEST);

//draw

glDisable(GL_DEPTH_TEST);

glBindFramebuffer(GL_FRAMEBUFFER, 0);

 

also you can set depth testing only once (while fbo binded) and you wont have to call depthfunc and glenable every frame.

int w = 512;
int h = 512;

	unsigned int FBO_TEX;
	unsigned int FBO_DEPTH;
	unsigned int FBO_ID;
	unsigned int RBO_ID;


                        glGenTextures(1, &FBO_TEX);
			glBindTexture(GL_TEXTURE_2D, FBO_TEX);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);


			glGenTextures(1, &FBO_DEPTH);
			glBindTexture(GL_TEXTURE_2D, FBO_DEPTH);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
			glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);

			glGenFramebuffers(1, &FBO_ID);
			glGenRenderbuffers(1, &RBO_ID);
			glBindRenderbuffer(GL_RENDERBUFFER, RBO_ID);
			glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 512, 512);
			glBindFramebuffer(GL_FRAMEBUFFER, FBO_ID);
			glBindTexture(GL_TEXTURE_2D, FBO_TEX);
			glFramebufferRenderbuffer(GL_FRAMEBUFFER,
			                          GL_DEPTH_ATTACHMENT,
			                          GL_RENDERBUFFER,
									  RBO_ID);
			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, FBO_TEX, 0);
			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, FBO_DEPTH, 0);
			glBindFramebuffer(GL_FRAMEBUFFER, 0);

just be sure to set GL_DEPTH_COMPONENT correct i mean use only one that your device is using for your app

 

the code is a part of OGL ES 2.0 so i use GL_RGBA and GL_DEPTH_COMPONENT16 for texture

But aren't renderbuffers simply framebuffer textures that are never displayed and instead used for calculations? So hypothetically the depth buffer could be in either a GL_TEXTURE_2D OR a RenderBuffer?

 

Also I did enable GL_DEPTH_TEST albeit outside FBOs, as well as set the DepthFunc to GL_LESS. http://stackoverflow.com/questions/2213030/whats-the-concept-of-and-differences-between-framebuffer-and-renderbuffer-in

 

EDIT: I simply added the depth testing within the FBO Binds and it appears to work. I did not have to modify the FBO Buffer Creation, but can't figure out how to make the depth testing automatically bound, as you said before.

Edited by KarimIO

Share this post


Link to post
Share on other sites

Render Buffers do NOT have texture attachments. Render Buffer are offscreen buffers managed by OpenGL that can be used as framebuffer attachment points ( if one could say that ). Just wanted to add that clarification, as per the question, the posted code is somewhat confusing ( had a hard time following the layout ), so can't give a firm answer. Are you checking to make sure all FBO are complete prior to using them ?

Share this post


Link to post
Share on other sites

 

 

EDIT: I simply added the depth testing within the FBO Binds and it appears to work. I did not have to modify the FBO Buffer Creation, but can't figure out how to make the depth testing automatically bound, as you said before.

 

 

after creating framebuffer object you just 

glDepthFunc(GL_LEQUAL);

glEnable(GL_DEPTH_TEST

 

and you disable framebuff

glBindFrameBuffer(GL_FRAMEBUFFER, 0);

 

 

 

 

now whenever you call 

glBindFrameBuffer(GL_FRAMEBUFFER, dat_framebuff_with_depth_enabled);

 

you should have depth working

Share this post


Link to post
Share on other sites

no no no baby you dont attach depthbuffer to fbo like that: first of all after creating fbo you create RBO (render buffer object), you attach depthbuff tex to rbo
 

Aren't you mistaken here?

You either bind depth texture to fbo, or renderbuffer with depth format storage. You go with texture if later you'll need to sample rendered depth surface, and you go with renderbuffer if you don't need actual result.

In your example you create depth texture, but it's not used anywhere. You set renderbuffer as depth attachment, allocating new storage for that buffer with glRenderbufferStorage. Created earlier depth texture (FBO_DEPTH object) is left unused.

Share this post


Link to post
Share on other sites

Aren't you mistaken here?

Yes he is.

As per the question, since you are only binding a depth buffer and not a depth-stencil buffer, ensure that stencil operations are disabled.
Check the framebuffer status after creation always.
Use RenderDoc or gDEBugger to debug your OpenGL state.


L. Spiro

Share this post


Link to post
Share on other sites

Render Buffers do NOT have texture attachments. Render Buffer are offscreen buffers managed by OpenGL that can be used as framebuffer attachment points ( if one could say that ). Just wanted to add that clarification, as per the question, the posted code is somewhat confusing ( had a hard time following the layout ), so can't give a firm answer. Are you checking to make sure all FBO are complete prior to using them ?

 

Yeah that's what I understood, which is why WireCat's code confused me a bit! As I said, the two things that fixed my code was when I cleared (after binding), and enabling depth after binding as opposed to for the default (unbound) framebuffer, so he did help me there.

 

L. Spiro, I had already solved the issue (there was no error report when checking the status though, as I think it was technically legal). I usually only use gDEBugger when I need to, and try to rely on internal error checking instead.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!