0

それに応じて目の空間の位置をテクスチャに保存する遅延レンダリングを使用しています。

バーテックス:

gl_Position = vec4(vertex_position, 1.0);

ジオメトリ:

vertexOut.position = vec3(viewMatrix * modelMatrix * gl_in[i].gl_Position);

断片:

positionOut = vec3(vertexIn.position);

次に、2 番目のパス (ライティング パス) で、この vec4 から計算された UV 座標を使用して、シャドウ マップをサンプリングしようとしています。

vec4 lightSpacePos = lightProjectionMatrix * lightViewMatrix * lightModelMatrix * vec4(position, 1.0);

使用される位置は、位置テクスチャから保存およびサンプリングされた位置と同じです。この計算を行う前に、逆カメラ ビュー マトリックスを使用して位置を変換する必要がありますか? それをワールド空間に戻すには、どうすればよいですか?

4

1 に答える 1

0

通常、シャドウ マッピングは、現在のフラグメントとライトのウィンドウ空間の Z 座標 (深度テクスチャが保存するもの) を比較することによって行われます。これは、共通の参照方向を使用して行う必要があるため、ライトの視点から現在のフラグメントの位置を再投影する必要があります。

現在のビュー空間の位置は、現在のカメラに対して相対的であり、特に有用ではありません。これを効果的に行うには、ワールド空間の位置が必要です。逆ビュー行列でビュー空間の位置を変換すると、それを得ることができます。

ワールド空間の位置を指定して、ライトの視点からクリップ空間に変換します。

// This will be in clip-space
vec4 lightSpacePos = lightProjectionMatrix * lightViewMatrix * vec4 (worldPos);

// Transform it into NDC-space by dividing by w
lightSpacePos /= lightSpacePos.w;

// Range is now [-1.0, 1.0], but you need [0.0, 1.0]
lightSpacePos = lightSpacePos * vec4 (0.5) + vec4 (0.5);

デフォルトの深度範囲を想定すると、lightSpacePosすぐに使用できます。xyシャドウ マップからサンプリングするテクスチャ座標とz、比較に使用する深度が含まれています。

詳細な説明については、次の回答を参照してください。


ちなみに、適切なパフォーマンスを実現するために、G バッファーから位置テクスチャを削除する必要があります。深さと射影行列とビュー行列だけがあれば、ワールド空間またはビュー空間の位置を再構築するのは非常に簡単で、関連する演算は追加のテクスチャ フェッチよりもはるかに高速です。3D 空間での位置を表すのに適切な精度で追加のテクスチャを保存すると、フレームごとに大量のメモリ帯域幅が消費されるため、まったく不要です。

OpenGL Wiki のこの記事では、これを行う方法について説明しています。さらに一歩進んで、ビュー空間よりも望ましいワールド空間に戻ることができます。適切な精度を得るために深度バッファを少し調整する必要があるかもしれませんが、それでも位置を個別に保存するよりも高速です。

于 2015-03-16T21:30:54.450 に答える