OpenGL:读取帧缓冲区的深度纹理

问题描述:

我在Java中使用LWJGL,它具有与C++ OpenGL相同的函数名称。请注意,我不得不使用OpenGL的“旧”固定功能管线。OpenGL:读取帧缓冲区的深度纹理

//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); 
} 

我怎么会深度图的内容(我想被初始化为深度缓存)存储在:

我目前正在成功地使用下面的代码绘制帧缓冲区的RGB内容PixelBufferObjects PBO而不是“主”帧缓冲区内容?

UPDATE: 这是我使用的阅读深度图的内容,现在PBO该代码:

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); 
} 

产生的图像仅仅是黑色的但是。 这可能是什么原因造成的?我可能搞砸了一些GL格式吗?

+0

使用深度纹理附件而不是渲染缓冲区,并且从不使用像33190这样的幻数。我不知道常量是什么,我也不打算查看它。 –

+0

@ AndonM.Coleman我用GL_DEPTH_COMPONENT24代替了它的幻数,它与此类似。 – CrushedPixel

+0

从帧缓冲区检索数据的规范方法是'glReadPixels'。使用像素包缓冲区PBO绑定的方式将空指针传递给数据参数将使其与PBO异步读取。另请注意,glGetTexImage仅在(桌面)OpenGL中受支持,但在ES配置文件中并不支持WebGL。所以为了前向兼容性,你不应该使用glGetTexImage – datenwolf

绑定“framebuffer的纹理”并没有什么意义。此纹理仅表示一个(颜色缓冲区)附件。您可以将多个纹理附加到帧缓冲区,深度缓冲区也可以作为纹理进行存储。

如果您使用深度纹理附件而不是渲染缓冲区,则可以按照读取颜色附件的相同方式进行读取。唯一的区别是格式和数据类型:GL_DEPTH_COMPONENTGL_UNSIGNED_INT_24_8

或者,您可以使用glReadPixels (...)从附加的渲染缓冲区读取。由于您必须指定一个矩形才能读取,因此API涉及更多一点。

+0

这就是我目前使用'glReadPixels'从framebuffer的纹理读取:'glReadPixels(0,0,getFrameWidth(),getFrameHeight(),GL_RGB,GL_UNSIGNED_BYTE,0) ;',我将如何去阅读Renderbuffer?我会如何将其绑定? – CrushedPixel

+0

@CrushedPixel:只要将它附加到Frambuffer对象上,就可以“绑定”渲染缓冲区。帧缓冲区只能有一个深度附件,所以你不需要做任何事情。当您调用'glReadPixels(...)'时,只需使用FBO即可,并使用正确的格式和数据类型。我上面给出的例子是一个32位打包数据类型,它是如何在GPU上本地存储24位深度缓冲区(其余的8位是未使用的填充或模板缓冲区),所以它应该转换为从渲染缓冲区直接复制到没有数据转换的pixelbuffer。 –

+0

谢谢。我更新了我的帖子,根据您的建议显示了我的当前代码,但是结果渲染看起来不正确。 – CrushedPixel