2013-04-21 12 views
5

私は、私のシーンのオブジェクトの奥行きマップを与える一対のGLSLシェーダを持っています。私が今取得するのは、各ピクセルからカメラまでの距離です。私が必要とするのは、ピクセルからカメラ面までの距離を得ることです。少し描いてみましょうGLSLのカメラの平面までの距離としての奥行

*   |--* 
/   | 
/   | 
C-----*  C-----* 
\   | 
    \   | 
    *   |--* 

3つのアスタリスクはピクセルで、Cはカメラです。アスタリスクからの線は「深さ」です。最初のケースでは、ピクセルからカメラまでの距離を取得します。次に、各ピクセルから飛行機までの距離を取得したいと思います。

いくつかの投影行列を使用してこれを行う方法が必要ですが、私は困惑しています。

ここに私が使用しているシェーダがあります。 eyePositionはcamera_position_object_spaceです。

バーテックスシェーダ:

void main() { 
    position = gl_Vertex.xyz; 
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; 
} 

ピクセルシェーダ:

uniform vec3 eyePosition; 
varying vec3 position; 


void main(void) { 
     vec3 temp = vec3(1.0,1.0,1.0); 
     float depth = (length(eyePosition - position*temp) - 1.0)/49.0; 
     gl_FragColor = vec4(depth, depth, depth, 1.0); 
} 
+0

どのような投影法を使用していますか?この場合、別のモデルビューと投影行列を使用する必要はありません。奥行きマップをレンダリングするときに正射投影を使用する場合は、何も計算せずに必要なものを得る必要があります。 – Ani

+0

私はレンダリング時に透視投影を行っていますが、正射影投影から深度値が必要です。 – Lucian

答えて

9

あなたは本当にこれを難しい方法でやろうとしています。物をカメラ空間に変換し、そこから作業するだけです。カメラ空間(すべてがカメラの位置/向きに対してある空間)で

varying float distToCamera; 

void main() 
{ 
    vec4 cs_position = glModelViewMatrix * gl_Vertex; 
    distToCamera = -cs_position.z; 
    gl_Position = gl_ProjectionMatrix * cs_position; 
} 

、頂点に平面の距離はZのちょうど負の座標である(より高い負Zが遠く離れています)。

フラグメントシェーダには、さらにeyePositionも必要ありません。 「深さ」は頂点シェーダから直接得られます。

+0

あなたは正しいです、私はそれをやり方でやり遂げていました。また、私は-cs.zが-cs_position.zであると仮定します。コードスニペットありがとう! – Lucian

1

何をほのめかしていることは正投影です。あなたは現在、透視投影を使用しています。実際には、ピクセルからカメラまでの真の距離はありませんが、錐台のピクセルのz位置です。レンダリングされたテクスチャ上では、[-1,1]の範囲内の最終z深度がレンダリングされ、NDC空間のz成分が記述されます。

あなたが理解しているように、あなたのすべての点は、透視投影を使用してカメラの方に向かって(実際には近い平面に)投影されます。あなたが望むのは、それらを近くの平面に直交して投影することです。 This linkは両方の射影行列を詳細に記述し、行列の最終結果は最下部にある。あなたのシェーダは新しい投影行列をうまく処理できるはずです。上記のようにMVP行列が計算されていることを確認してください。

注:正射投影は、レンダリングされたシーンの奥行きを表しているとは限りません。視点を透視投影でスクリーンにレンダリングしていて、各ピクセルを奥行きに合わせたい場合は、それに応じて同じ透視投影を使用する必要があります。したがって、正射投影を使用して深度をレンダリングするのは、シーンが同じ投影を使用している場合、または画面に表示されているシーンとは無関係な深さ情報が必要なアルゴリズムがある場合にのみ便利です。

さらに、廃止予定の機能(gl_Vertex、gl_ModelViewProjectionMatrixなど)を使用しているように見えるコアOpenGLプロファイル(3.x)をお勧めします。すべてのバッファーとシェーダーを自分で設定するのは若干手間がかかりますが、それは最終的には負担になります。

EDIT

は実際に、あなたのコメントの後に、私はあなたが望むものを理解しています。正投影があるよう

uniform mat4 orthographicMatrix; 
varying vec3 position; 

void main(void) { 
     vec4 clipSpace = orthographicMatrix * vec4(position, 1.0); 
     gl_FragColor = vec4(clipSpace.zzz, 1.0); 
} 

メモは、ワット除算を行う必要はありません:あなたが私はあなたのフラグメントシェーダではこのような何かを示唆このため、同じコールでそれらをレンダリングしたい明確ではありませんでした線形である(したがって、wは1に設定される)。

+0

詳細な応答をありがとう。透視投影法に従ってレンダリングしながら、正射影に対応する深さを得ることを試みている。これは奇妙に思えるかもしれませんが、私がしなければならないことです。 – Lucian

+0

ああ、私はあなたが何を意味したか理解していると思う。私の投稿を編集しました。 – Invalid

1

投影後のWコンポーネントには、シーンに直交する深さが含まれています。

varying float distToCamera; 

void main() 
{ 
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; 
    distToCamera = gl_Position.w; 
} 
+0

それは?それは 'gl_Position.z/gl_Position.w'ですか? – RecursiveExceptionException

関連する問題