Saturday, October 8, 2016

Notion(3-1): FBO, RenderBuffer, and Pixel Transfer .. This is cited from the www.stackoverflow.com, followed passage will examine the related notions..

[References]
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 GLfloats 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 floats 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.


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_BYTEmeans that it will read the depth and stencil, convert each into an unsigned, 8-bit value, and store two of those per-pixel into pixels.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.
shareedit
...

...

No comments:

Post a Comment