フラグメントシェーダーで深度バッファーを描画したいのですが、これを行います。
頂点シェーダー:
varying vec4 position_;
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
position_ = gl_ModelViewProjectionMatrix * gl_Vertex;
フラグメントシェーダー:
float depth = ((position_.z / position_.w) + 1.0) * 0.5;
gl_FragColor = vec4(depth, depth, depth, 1.0);
しかし、私が印刷するのは白だけです、私は何が間違っているのですか?
どの空間に奥行きを描きたいですか?ウィンドウスペースの深さを描画する場合は、次のように実行できます。
gl_FragColor = vec4(gl_FragCoord.z);
ただし、ほとんどの数値は1.0に非常に近いため、これは特に有用ではありません。非常に近いオブジェクトのみが表示されます。これは、標準の透視投影を使用した深度バッファーの深度値の分布の性質です。
または、言い換えれば、それがあなたが白くなっている理由です。
これらの値を線形空間で使用する場合は、次のような操作を行う必要があります。
float ndcDepth = ndcPos.z =
(2.0 * gl_FragCoord.z - gl_DepthRange.near - gl_DepthRange.far) /
(gl_DepthRange.far - gl_DepthRange.near);
float clipDepth = ndcDepth / gl_FragCoord.w;
gl_FragColor = vec4((clipDepth * 0.5) + 0.5);
実際、フラグメントの「深さ」値は、クリップ空間のz値から読み取ることができます(つまり、すべての行列変換後)。それだけは正しいです。
ただし、問題はw
による除算にあります。 w
による除算は、パースペクティブ除算と呼ばれます。はい、透視投影が正しく機能する必要があります。
ただし。この場合、w
で除算すると、(これまで見てきたように)すべての値が1.0に非常に近くなります。これには正当な理由があります: 透視投影 、w= (some multiplier) *z
。つまり、z値(計算されたものは何でも)を元のz(の何らかの係数)で除算します。常に1.0に近い値が得られるのも不思議ではありません。あなたはほとんどzをそれ自体で分割しています。
これに対する非常に簡単な修正として、z
をfarPlaneで除算し、それをdepthとしてフラグメントシェーダーに送信してみてください。
頂点シェーダー
varying float DEPTH ;
uniform float FARPLANE ; // send this in as a uniform to the shader
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
DEPTH = gl_Position.z / FARPLANE ; // do not divide by w
フラグメントシェーダー:
varying float DEPTH ;
// far things appear white, near things black
gl_Color.rgb=vec3(DEPTH,DEPTH,DEPTH) ;
その結果、悪くはなく、非常に直線的に見えるフェードになります。