【问题标题】:Convert OpenGL depth buffer to world-space z-distance from camera?将OpenGL深度缓冲区转换为相机的世界空间z距离?
【发布时间】:2011-12-30 19:06:18
【问题描述】:

我正在使用 Java OpenGL(JOGL 2.x,从 Git 源代码构建)。我正在将我的场景渲染到带有颜色和深度附件的帧缓冲区对象。我想将 [0,1] 深度缓冲区值转换为世界空间距离。我的深度附件定义如下:

    private void setupDepthFBOs(GL2 gl,
                            int width,
                            int height, 
                            int[] frameBufferIds,
                            int[] colorBufferIds,
                            int[] depthBufferIds) {        
    // based on
    // http://www.java2s.com/Code/Java/Advanced-Graphics/BloomOpenGL.htm
    //  generate a framebuffer object
    gl.glGenFramebuffers(1, frameBufferIds, 0);
    // bind the framebuffer
    gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, frameBufferIds[0]);

    // generate a texture in memory
    gl.glGenTextures(1, colorBufferIds,0);
    gl.glBindTexture(GL2.GL_TEXTURE_2D, colorBufferIds[0]);
    // this will be an RGBA texture (4 bpp) with width, height..
    gl.glTexImage2D(GL2.GL_TEXTURE_2D,      // target texture type
            0,          // mipmap LOD level
            GL2.GL_RGBA8,           // internal pixel format
            width,          // width of generated image
            height,         // height of generated image
            0,          // border of image
            GL2.GL_RGBA,        // external pixel format 
            GL2.GL_UNSIGNED_BYTE,   // datatype for each value
            null);  // buffer to store the texture in memory

    // set some texture parameters?
    gl.glTexParameteri(GL.GL_TEXTURE_2D, 
                       GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);

    // use the texture we just created in the framebuffer we just created
    gl.glFramebufferTexture2D(
            GL2.GL_FRAMEBUFFER,         // target texture type
            GL.GL_COLOR_ATTACHMENT0,    // attachment point
            GL.GL_TEXTURE_2D,           // texture target type
            colorBufferIds[0],          // on-gpu id for texture 
            0);                         // mipmap lod level

    gl.glGenTextures(1,depthBufferIds,0);
    gl.glBindTexture(GL.GL_TEXTURE_2D,depthBufferIds[0]);
    gl.glTexImage2D(GL2.GL_TEXTURE_2D,          // target texture type
            0,                          // mipmap LOD level
            GL2.GL_DEPTH_COMPONENT24,   // internal pixel format
                    //GL2.GL_DEPTH_COMPONENT
            width,                      // width of generated image
            height,                     // height of generated image
            0,                          // border of image
            GL2.GL_DEPTH_COMPONENT,     // external pixel format 
            GL2.GL_UNSIGNED_INT,        // datatype for each value
            null);  // buffer to store the texture in memory


    gl.glTexParameteri(GL.GL_TEXTURE_2D,
                       GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST);
    gl.glTexParameteri(GL.GL_TEXTURE_2D,
                       GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST);
    gl.glTexParameteri(GL.GL_TEXTURE_2D, 
                       GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_EDGE);
    gl.glTexParameteri(GL.GL_TEXTURE_2D, 
                       GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP_TO_EDGE);

    gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER,
                              GL.GL_DEPTH_ATTACHMENT,
                              GL.GL_TEXTURE_2D,
                              depthBufferIds[0],0);


    gl.glBindTexture(GL.GL_TEXTURE_2D, 0);

    int status = gl.glCheckFramebufferStatus(GL2.GL_FRAMEBUFFER);


    if (status == GL2.GL_FRAMEBUFFER_COMPLETE) {
        gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0);
    } else {
        throw new IllegalStateException("Frame Buffer Object not created. Status was: " + status);
    }

}

这成功创建了一个深度缓冲区,我可以将其作为纹理读取并渲染到屏幕,或用作着色器的输入(我的预期最终用例)。

几天前在 IRC 上进行了一些讨论后,我想出了以下公式,将投影矩阵(此处表示为 p)和深度缓冲区值与世界空间中屏幕上每个点的距离联系起来:

z = (p_33)/(p_34 + 深度)

(注意:我的投影矩阵/眼睛设置为 Z+ 方向)

这会产生几乎合理的 z 值,但到场景中已知点的距离与此等式返回的值之间存在很大的误差范围。

有什么想法我在这里可能做错了吗?

【问题讨论】:

  • 请说明如何使用实际值设置投影矩阵。另外,您确定要“世界空间”z 距离而不是“眼睛空间”z 距离吗?后者通常对你正在做的事情更有意义。

标签: java opengl jogl depth


【解决方案1】:

这是我的计算,我的结果与你的不同:

定义:

depth = out_z / out_w
out_z = in_z * p_33 + in_w * p_43
out_w = in_z * p_34 + in_w * p_44

已知:

in_w = 1, p_43 = -1, p_44 = 0

工作:

depth = (in_z * p_33 - 1) / (in_z * p_34)
depth = p_33 / p_34 - 1 / (in_z * p_34)
p_33 / p_34 - depth = 1 / (in_z * p_34)
1 / (p_33 / p_34 - depth) = in_z * p_34
1 / (p_33 / p_34 - depth) = in_z * p_34
1 / (p_33 - depth * p_34) = in_z

【讨论】:

    猜你喜欢
    • 2020-03-26
    • 2017-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多