2016-11-02 5 views
7

logarithmic depth bufferを使用するように現在の遅延レンダラーを変更した後、私の人生のために、奥行きバッファー値からワールドスペースの奥行きを再構築する方法ができません。対数奥行きバッファからのワールドスペース位置

私はOpenGLのデフォルトのz/wの深さを書きましたが、私はこの値をウィンドウ空間からNDC空間に変換して逆投影変換を行うことで簡単に計算できました。

私は、全ての第2のパスフラグメントシェーダでこれをやった:

uniform sampler2D depth_tex; 

uniform mat4 inv_view_proj_mat; 

in vec2 uv_f; 

vec3 reconstruct_pos(){ 
    float z = texture(depth_tex, uv_f).r; 
    vec4 pos = vec4(uv_f, z, 1.0) * 2.0 - 1.0; 
    pos = inv_view_proj_mat * pos; 

    return pos.xyz/pos.w; 
} 

とかなり正しい見えた結果だ:

Cube rendered with correct world-space position reconstruction

をしかし、今、簡単なz値への道がありますそれほど簡単ではありません(それほど難しいとは思われません)。

ログ深さと私の最初の通過のための私の頂点シェーダ:

#version 330 core 
#extension GL_ARB_shading_language_420pack : require 

layout(location = 0) in vec3 pos; 
layout(location = 1) in vec2 uv; 

uniform mat4 mvp_mat; 

uniform float FC; 

out vec2 uv_f; 
out float logz_f; 
out float FC_2_f; 

void main(){ 
    gl_Position = mvp_mat * vec4(pos, 1.0); 

    logz_f = 1.0 + gl_Position.w; 

    gl_Position.z = (log2(max(1e-6, logz_f)) * FC - 1.0) * gl_Position.w; 

    FC_2_f = FC * 0.5; 
} 

そして、私のフラグメントシェーダ:

#version 330 core 
#extension GL_ARB_shading_language_420pack : require 

// other uniforms and output variables 

in vec2 uv_f; 
in float FC_2_f; 

void main(){ 
    gl_FragDepth = log2(logz_f) * FC_2_f; 
} 

私は、正しくz位置を取り戻すために、いくつかの異なるアプローチを試してみましたすべて失敗している。

私はreconstruct_pos 2パス目があることを再定義する場合:

vec3 reconstruct_pos(){ 
    vec4 pos = vec4(uv_f, get_depth(), 1.0) * 2.0 - 1.0; 
    pos = inv_view_proj_mat * pos; 

    return pos.xyz/pos.w; 
} 

これは、再構築するZで私の現在の試みです:

uniform float FC; 

float get_depth(){ 
    float log2logz_FC_2 = texture(depth_tex, uv_f).r; 
    float logz = pow(2, log2logz_FC_2/(FC * 0.5)); 
    float pos_z = log2(max(1e-6, logz)) * FC - 1.0; // pos.z 
    return pos_z; 
} 

はの説明:

log2logz_FC_2:書き込まれた値奥行きバッファまで、log2(1.0 + gl_Position.w) * (FC/2)

logz:単に1.0 + gl_Position.w

pos_z:視点の前gl_Position.zの値が

戻り値devide:もちろんgl_Position.z

、それはちょうど私の作業です。私は、これらの値が最終的に実際に保持されているかどうかはわかりません。なぜなら、私は数学の一部を台無しにしたか、

この対数奥行きバッファからワールドスペースZ位置を取得する正しい方法はありますか?

答えて

0

最後に私はこのすべてを間違っていました。バックログバッファを使用してワールド空間位置を取得する方法は次のとおりです。

  1. は、テクスチャ
  2. 再構築gl_Positionからの深さを取得します。

    in vec2 uv_f; 
    
    uniform float nearz; 
    uniform float farz; 
    
    uniform mat4 inv_view_proj_mat; 
    
    float linearize_depth(in float depth){ 
        float a = farz/(farz - nearz); 
        float b = farz * nearz/(nearz - farz); 
        return a + b/depth; 
    } 
    
    float reconstruct_depth(){ 
        float depth = texture(depth_tex, uv_f).r; 
        return pow(2.0, depth * log2(farz + 1.0)) - 1.0; 
    } 
    
    vec3 reconstruct_world_pos(){ 
        vec4 wpos = 
         inv_view_proj_mat * 
         (vec4(uv_f, linearize_depth(reconstruct_depth()), 1.0) * 2.0 - 1.0); 
    
        return wpos.xyz/wpos.w; 
    } 
    

    私が使っていたときのように(より良い精度で)私に同じ結果を与える:

  3. リニアライズ再構築された深さwが

はここでGLSLの私の実装のワールド空間に変換しますデフォルトのOpenGLデプスバッファです。