2011-11-16 93 views
0

我正在使用Java OpenGL(JOGL 2.x,由Git源構建)。我使用顏色和深度附件將場景渲染爲幀緩衝區對象。我想將[0,1]深度緩衝區值轉換爲世界空間距離。我的深度附件被定義如下:將OpenGL深度緩衝區轉換爲相機的世界空間z距離?

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值,但與場景中已知點的距離與此方程返回的值之間存在明顯的誤差範圍。

任何想法,我可能會在這裏做錯嗎?

+0

請說明如何用實際值設置投影矩陣。另外,您確定要「世界空間」z距離而不是「眼睛空間」z距離嗎?後者通常對你正在做的事情更有意義。 – bernie

回答

2

這裏是我的計算,我的結果是不同的,以你的:

定義:

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