clipspace.xy = FragCoord.xy / viewport * 2.0 - 1.0;
これは命名法に関して間違っています。「クリップ スペース」は、頂点シェーダー (または最後の頂点処理ステージが何であれ) が出力するスペースです。クリップ スペースとウィンドウ スペースの間には、正規化されたデバイス座標 (NDC) スペースがあります。NDC 空間は、クリップ空間の W 座標で割ったクリップ空間です。
vec3 ndcspace = clipspace.xyz / clipspace.w;
したがって、最初のステップは、ウィンドウ空間座標を取得し、NDC 空間座標を取得することです。これは簡単です:
vec3 ndcspace = vec3(FragCoord.xy / viewport * 2.0 - 1.0, depth);
ここで、値が適切な NDC 空間の深さであると仮定します。depth
深度テクスチャから値をフェッチし、レンダリングされた深度範囲の近/遠値を使用して [-1, 1] 範囲にマップすると想定しています。そうでない場合は、そうする必要があります。
では、 が得られたのでndcspace
、どうやって を計算するのclipspace
でしょうか? まあ、それは明らかです:
vec4 clipspace = vec4(ndcspace * clipspace.w, clipspace.w);
明らかで... ないので役に立ちませんclipspace.w
。では、どうやってそれを得るのですか?
これを取得するにclipspace
は、最初に がどのように計算されたかを見る必要があります。
vec4 clipspace = Proj * cameraspace;
これは、 の 4 行目でそれを内積clipspace.w
することによって が計算されることを意味します。cameraspace
Proj
まあ、それはあまり役に立ちません。の 4 行目を実際に見てみると、さらに役に立ちますProj
。確かに、任意の射影行列を使用できます。典型的な射影行列を使用していない場合、この計算はより困難になります (不可能になる可能性があります)。
典型的な射影行列を使用したの 4 行目はProj
、実際には次のとおりです。
[0, 0, -1, 0]
これは、clipspace.w
が本当にただの であることを意味し-cameraspace.z
ます。それは私たちにどのように役立ちますか?
これを覚えておくと役立ちます:
ndcspace.z = clipspace.z / clipspace.w;
ndcspace.z = clipspace.z / -cameraspace.z;
それはいいことですが、未知のものを別のものと交換するだけです。まだ 2 つの未知数 (clipspace.z
とcameraspace.z
) を含む方程式があります。しかし、私たちは別のことを知っています:射影行列の3clipspace.z
行目の内積から来ています。従来の射影行列の 3 行目は次のようになります。cameraspace
[0, 0, T1, T2]
ここで、T1 と T2 はゼロ以外の数値です。当分の間、これらの数値が何であるかは無視します。したがって、clipspace.z
は本当に ですT1 * cameraspace.z + T2 * cameraspace.w
。が 1.0 であることがわかっている場合cameraspace.w
(通常はそうです)、それを削除できます。
ndcspace.z = (T1 * cameraspace.z + T2) / -cameraspace.z;
ですから、まだ問題があります。実際、私たちはしません。なんで?この真正方程式には未知数が 1 つしかないからです。覚えておいてください:私たちはすでに知っていndcspace.z
ます. したがって、ndcspace.z を使用して を計算できますcameraspace.z
。
ndcspace.z = -T1 + (-T2 / cameraspace.z);
ndcspace.z + T1 = -T2 / cameraspace.z;
cameraspace.z = -T2 / (ndcspace.z + T1);
T1
投影マトリックス (シーンが最初にレンダリングされたもの) からすぐにT2
出てきます。そして、私たちはすでに持っていますndcspace.z
。したがって、計算できcameraspace.z
ます。そして、次のことがわかっています。
clispace.w = -cameraspace.z;
したがって、これを行うことができます:
vec4 clipspace = vec4(ndcspace * clipspace.w, clipspace.w);
clipspace.w
明らかに、リテラル コードではなくfloat for が必要になりますが、私の言いたいことはわかります。を取得したらclipspace
、カメラ スペースを取得するには、逆投影行列を掛けます。
vec4 cameraspace = InvProj * clipspace;