PDA

View Full Version : using gldrawpixels to fill an fbo depth attachment



regnirpsj
02-12-2008, 02:18 PM
hi,

i'm having problems filling a depth texture attached to an fbo with gldrawpixels. what do i do?

i have a bunch of buffers (obtained from an mrt pass on another machine) and want to apply them within an fbo that has the same setup as the one the buffers were read from. for several reasons i'd like to stick to gldrawpixels and that is working fine for the color attachments. workflow looks like this:

fbo.bind()
glDrawPixels(..., GL_DEPTH_COMPONENT, ...)

glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT)
glDrawPixels(..., GL_RGBA, ...)

glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT)
glDrawPixels(..., GL_RGBA, ...)
:
fbo.unbind()
clear_color_depth_stencil()
full_screen_quad(using the fbo attachments as textures)

i get the correct values from the color attachments in the full-screen pass (verified by assigning them to gl_FragColor) but the depth attachment of the fbo does only contain zeros. i verified too that the depth buffer written with gldrawpixels does contain the correct values (by using gldrawpixel between the clear command and the full-screen quad).

i've read through the docs and the only thing i came up with was question (10) in the EXT_framebuffer_object spec explicitely stating that
Since the group decided supporting an "initialization" image for a "renderbuffer" was too much overlapping functionality with DrawPixels, RenderbufferStorage was chosen.

so, my question: is what i'm doing covered by the spec?

i appreciate any suggestions.

(platform is linux 32bit, nvidia g80, driver rev. 169.09)

regnirpsj
02-12-2008, 10:14 PM
problem solved, although it smells like a (driver) bug. drawing the depth last produces the correct result, i.e.

fbo.bind()
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT)
glDrawPixels(..., GL_RGBA, ...)

glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT)
glDrawPixels(..., GL_RGBA, ...)
:
glDrawPixels(..., GL_DEPTH_COMPONENT, ...)
fbo.unbind()
clear_color_depth_stencil()
full_screen_quad(using the fbo attachments as textures)

it seems like the drawpixel calls for the color attachments also clear the depth attachment.

though, i would still like to know if the original sequence should have worked?

Relic
02-13-2008, 04:46 AM
That's not a bug. Read the OpenGL specs on glDrawPixels.
When writing color buffers it renders depth values taken from the current glRasterPos if depth test and depth write are enabled.

regnirpsj
02-13-2008, 11:18 AM
thank you for answering.

i think i found the place in the spec (3.6.4, para "Conversion to Fragments"). however, i would interpret it in a way that, when i write depth and then color, the color write would use the exisisting depth value, which should be in the depth texture of the fbo (at least that's what i would expect). but i'm certainly wrong about that and do confuse the just written depth values with what exists at the raster position. where would i find that covered in the spec (or some extension spec)?

because 3.6.4, para "Conversion to Fragments" does not convey anything about depth testing and writing i would also like to know where i would find this relationship explained?

arekkusu
02-13-2008, 05:37 PM
DrawPixels can draw color, depth, and stencil data. But only one at a time; the other two are picked up the current raster state, unconditionally.

The operation is orthogonal to all raster tests. So if you want to draw depth data without modifiying color, ColorMask(0,0,0,0). Or color data without depth writes, DepthMask(0), or Disable(DEPTH_TEST).

regnirpsj
02-14-2008, 02:35 AM
yes, i understand this. my question is: where does the depth value come from if i do a color write within an fbo? i.e. given the following sequence:

fbo.bind()
glDrawPixels(..., GL_DEPTH_COMPONENT, ...) // #1
glDrawPixels(..., GL_RGBA, ...) // #2
fbo.unbind()

does #2 pick the depth value from what was written by #1 or from somewhere else? if #2 picks the depth value from somewhere else, what would "somewhere else" be?

skynet
02-14-2008, 05:15 AM
Just another tip on a pitfall I encountered lately:
If you're using clipping planes and glDrawPixels at the same time, be aware that glRasterPos() is sensitive to clipping by user defined clipping planes! That means, if the vertex position that is specified with glRasterPos() got clipped away by any clipping plane, any subsequent glDrawPixels() will be ignored. So, if in doubt, disable any clipping plane before issuing glRasterPos().

V-man
02-14-2008, 09:07 AM
yes, i understand this. my question is: where does the depth value come from if i do a color write within an fbo? i.e. given the following sequence:

fbo.bind()
glDrawPixels(..., GL_DEPTH_COMPONENT, ...) // #1
glDrawPixels(..., GL_RGBA, ...) // #2
fbo.unbind()

does #2 pick the depth value from what was written by #1 or from somewhere else? if #2 picks the depth value from somewhere else, what would "somewhere else" be?


The depth value comes from the current raster position. I think you are forgetting to call glRasterPos3f.
That is like a GL_POINT and it needs to be in your window. If it is outside, or getting clipped, nothing gets rendered.

You should disable depth testing and writing with glDisable(GL_DEPTH_TEST) and glDepthMask(GL_FALSE) when you call
glDrawPixels(..., GL_RGBA, ...)

You can disable depth testing glDisable(GL_DEPTH_TEST) for
glDrawPixels(..., GL_DEPTH_COMPONENT, ...)

I'm not exactly clear on the behavior when you doing
glDrawPixels(..., GL_DEPTH_COMPONENT, ...)
so I'll let someone correct me if need be.

regnirpsj
02-18-2008, 12:42 AM
hi, to conclude this discussion: disabling other buffer parts does indeed fix the "problem." (partial) code looks like this:



glPushAttrib(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
{
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

if (color_enabled) {
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDepthMask(GL_FALSE);
glWindowPos2i(x, y);
glDrawPixels(w, h, cformat, ctype, &(cbuf[0]));
}

if (do_depth_write || do_stencil_write) {
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);

if (do_depth_write) {
glDepthMask(GL_TRUE);
glDepthFunc(GL_ALWAYS);
glWindowPos2i(x, y);
glDrawPixels(w, h, GL_DEPTH_COMPONENT, dtype, &(dbuf[0]));
}

if (do_stencil_write) {
glDepthMask(GL_FALSE);
glWindowPos2i(x, y);
glDrawPixels(w, h, GL_STENCIL_INDEX, stype, &(sbuf[0]));
}
}
}
glPopClientAttrib();
glPopAttrib(); // GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT


this allows for writing either one, either two, or all three of the buffers. the only unsafe thing is the stencil buffer; the opengl spec's description is rather lengthy, so i postponed this part of the implementation.

thanks to everyone for helping.