1. "Render off screen (with FBO and RenderBuffer) and pixel transfer of color, depth,and stencil"
Key Words: Render-Off-Screen; FBO; RenderBufer; Pixel-Transfer;
...
The depth.. I'm expecting a white image with a gradient gray triangle..
Your code doesn't suggest that.
uchar *pixels;
pixels = new uchar[width * height * 4];
This creates an array of integers. It's also a memory leak; use
std::vector<uchar>
instead.glReadPixels( 0,0, width, height, GL_DEPTH_COMPONENT, GL_FLOAT, pixels);
This tells OpenGL to write floats to your array of integers. So OpenGL will treat
pixels
as an array of GLfloat
s when writing.QImage qi = QImage(pixels, width, height, QImage::Format_ARGB32);
I'll assume that this is going to interpret this as some kind of 8-bit-per-component integer image format. So you're interpreting
float
s as 8-bit integers. There's no reason to expect this to behave rationally.- You should either be reading the depth buffer as floats and converting that to your pixel colors in a more reasonable way,
- or you should be reading the depth buffer as an integer value, letting OpenGL do the greyscale conversion for you.
- Also, you should always be using a combined depth/stencil image, not two separate renderbuffers.
glReadPixels( 0,0, width, height, GL_DEPTH24_STENCIL8, GL_UNSIGNED_BYTE, pixels.data());
You don't seem to understand how pixel transfers work.
- First, the pixel transfer format specifies which components that you're reading. It does not specify their sizes.
GL_DEPTH24_STENCIL8
is an image format, not a pixel transfer format. - If you want to read the depth and stencil from an image, you use
GL_DEPTH_STENCIL
. Pixel transfer formats don't have sizes.
So this function is just giving you an OpenGL error.
- The size comes from the second parameter, the pixel transfer type.
- In this case
GL_UNSIGNED_BYTE
means that it will read the depth and stencil, convert each into an unsigned, 8-bit value, and store two of those per-pixel intopixels.data()
.
- Depth buffers only store 1 value per pixel. Depth/stencil only store 2.
- You cannot copy them into a 4-component-per-pixel format with OpenGL.
- Therefore, however you build your QImage later, it must me some method that takes 1 or 2 values per pixel.
Generally speaking, if you want to read the depth buffer, and you want the depth buffer's data to actually be meaningful, you do this:
std::vector<GLuint> pixels(width * height); //std::vector value-initializes its elements.
glBindFramebuffer(GL_FRAMEBUFFER, fboId);
glReadPixels( 0,0, width, height, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, pixels.data());
How you put those in a QImage for visualization is up to you. But this gets you an array of unsigned ints, where the high 24 bits are the depth component, and the low 8 bits are the stencil.
...
No comments:
Post a Comment