7

私は遅延シェーダーを作成しており、gbuffer をより密にパックしようとしています。ただし、ビュー空間の深さを正しく指定すると、ビューの位置を計算できないようです

// depth -> (gl_ModelViewMatrix * vec4(pos.xyz, 1)).z; where pos is the model space position
// fov -> field of view in radians (0.62831855, 0.47123888)
// p -> ndc position, x, y [-1, 1]
vec3 getPosition(float depth, vec2 fov, vec2 p)
{
    vec3 pos;
    pos.x = -depth * tan( HALF_PI - fov.x/2.0 ) * (p.x);
    pos.y = -depth * tan( HALF_PI - fov.y/2.0 ) * (p.y);
    pos.z = depth;
    return pos;
}

計算された位置が間違っています。私はまだgbufferに正しい位置を保存していて、それを使ってテストしているので、これを知っています。

4

3 に答える 3

4

私は最終的にそれを機能させることができました、それは上記とは異なる方法なので、これを見る人が解決策を持っているようにそれを詳しく説明します。

  • パス1:ビュースペースの深度値をgbufferに格納します
  • 2番目のパスで(x、y、z)の位置を再作成するには、次のようにします。
  • ラジアン単位の水平および垂直視野をシェーダーに渡します。
  • シェーダーに近い平面距離(近く)を渡します。(カメラ位置から平面近くまでの距離)
  • カメラからフラグメント位置への光線を想像してみてください。この光線は、特定の位置Pで近平面と交差します。この位置は、ndc空間にあり、ビュー空間でこの位置を計算します。
  • これで、ビュースペースに必要なすべての値が得られました。同様の三角形の法則を使用して、実際のフラグメント位置P'を見つけることができます。

    P = P_ndc * near * tan(fov/2.0f) // computation is the same for x, y
    // Note that by law of similar triangles, P'.x / depth = P/near  
    P'.xy = P/near * -depth; // -depth because in opengl the camera is staring down the -z axis
    P'.z = depth;
    
于 2012-07-09T10:15:01.030 に答える
3

遅延シェーダーを作成し、このコードを使用して画面スペースの位置を再計算しました。

vec3 getFragmentPosition()
{
     vec4 sPos = vec4(gl_TexCoord[0].x, gl_TexCoord[0].y, texture2D(depthTex, gl_TexCoord[0].xy).x, 1.0);
     sPos.z = 2.0 * sPos.z - 1.0;
     sPos = invPersp * sPos;

     return sPos.xyz / sPos.w;
}

ここで、depthTexは深度情報を保持するテクスチャでinvPerspあり、事前に計算された逆透視行列です。画面のフラグメントの位置を取得し、逆遠近行列を掛けて、モデル ビュー座標を取得します。次に、で割り、同次w座標を取得します。2 の乗算と 1 の減算は、深度を [0, 1] (テクスチャに格納されているため) から [-1, 1] にスケーリングすることです。

また、使用している MRT の種類によっては、float の精度が失われるため、再計算された結果は格納された情報と正確に一致しません。

于 2012-06-30T21:31:51.660 に答える