0

I'm using LWJGL in Java, which has identical function names to the C++ OpenGL. Note that I'm forced to use OpenGL's "old" Fixed Function Pipeline.

I'm currently successfully drawing a Framebuffer's RGB contents to PixelBufferObjects using the following code:

//the initialization method
public void init(int width, int height) {
    //initializing the PBO
    pbo_id = glGenBuffers();
    // [...]

    //initializing the Framebuffer
    framebufferObject = glGenFramebuffers();
    framebufferTexture = glGenTextures();

    depthBuffer = glGenRenderbuffers();

    framebufferFilter = GL_NEAREST;

    glBindTexture(GL_TEXTURE_2D, framebufferTexture);

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameterf(GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL_CLAMP);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (ByteBuffer)null);
    glBindFramebuffer(GL_FRAMEBUFFER, framebufferObject);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, framebufferTexture, 0);

    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer);

    glBindTexture(GL_TEXTURE_2D, 0);
}

//this is called after the world was rendered to the framebuffer
public void capture() {
    //binding the PBO
    glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo_id);

    //binding the Framebuffer's texture
    glBindTexture(GL_TEXTURE_2D, framebuffer_id);

    //storing the Framebuffer's contents in the PBO
    glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);

    //unbinding the Framebuffer
    glBindTexture(GL_TEXTURE_2D, 0);

    //unbinding the PBO
    glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
}

How would I store the contents of the depth map (which I suppose is being initialized as depthBuffer) in the PBO instead of the "main" framebuffer contents?

UPDATE: This is the code which I'm using to read the depth map's contents to a PBO now:

public void captureDepthMap() {
    //binding the PBO
    glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo_id);

    glPixelStorei(GL_PACK_ALIGNMENT, 1);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

    //binding the FBO
    glBindFramebuffer(GL_FRAMEBUFFER, framebufferObject);

    //storing the Depth Map's contents in the PBO
    glReadPixels(0, 0, width, height, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT_24_8, 0);

    //unbinding the FBO
    glBindFramebuffer(GL_FRAMEBUFFER, 0);

    //unbinding the PBO
    glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
}

The resulting image is just black however. What may cause this? Did I possibly mess up some GL formats?

CrushedPixel
  • 1,152
  • 2
  • 13
  • 26
  • Use a depth texture attachment instead of a renderbuffer, and never use magic numbers like 33190. I have no idea what constant that is, and I'm not going to bother looking it up. – Andon M. Coleman Jan 13 '16 at 10:25
  • @AndonM.Coleman I've replaced the magic number with GL_DEPTH_COMPONENT24, which it resembles. – CrushedPixel Jan 13 '16 at 10:29
  • The canonical way to retrieve data from a framebuffer is `glReadPixels`. With a pixel pack buffer PBO bound passing a null pointer to the data parameter will make it read asynchronously to the PBO. Also be aware that glGetTexImage is supported only in (desktop) OpenGL but not available in the ES profile and thereby WebGL. So for the sake of forward compatibility you should not use glGetTexImage – datenwolf Jan 13 '16 at 11:23

1 Answers1

1

Binding the "framebuffer's texture" does not make a whole lot of sense. This texture only represents a single (color buffer) attachment. You can have multiple textures attached to your framebuffer and the depth buffer can be stored as a texture too.

If you use a depth texture attachment instead of renderbuffer, you can read it back the same way you read the color attachment. The only difference would be the format and data type: GL_DEPTH_COMPONENT and GL_UNSIGNED_INT_24_8.

Alternatively, you can use glReadPixels (...) to read from the attached renderbuffer. The API is a little more involved because you have to specify a rectangle to read.

Andon M. Coleman
  • 42,359
  • 2
  • 81
  • 106
  • This is how I currently use `glReadPixels` to read from the framebuffer's texture: `glReadPixels(0, 0, getFrameWidth(), getFrameHeight(), GL_RGB, GL_UNSIGNED_BYTE, 0);`, how would I go about reading from the Renderbuffer? How would I bind it first? – CrushedPixel Jan 13 '16 at 23:13
  • @CrushedPixel: You "bound" the renderbuffer as soon as you attached it to your Frambuffer Object. Framebuffers can only have a single depth attachment, so there is nothing fancy that you need to do. Simply have the FBO bound when you call `glReadPixels (...)` and use the correct format and data type. The example I gave above is a 32-bit packed data type, it is how a 24-bit depth buffer is stored natively on the GPU (the remaining 8-bits are either unused padding or the stencil buffer), so it should translate to a direct copy from your renderbuffer into the pixelbuffer with no data conversion. – Andon M. Coleman Jan 14 '16 at 00:39
  • Thanks. I've updated my post to show my current code based on your suggestion, however the resulting render does not look correct. – CrushedPixel Jan 14 '16 at 13:08