視錐台
簡単のためスクリーン=nearプレーンとされる。
nearのz値をN
farのz値をF
とすると
$$
\frac{x'}{x}=\frac{y'}{y}=\frac{z'}{z}=\frac{N}{z}
$$
である。ここで
(x, y, z)はパース変換すべき3Dモデルの頂点座標。
(x', y', z')はx, yを焼き付けたい平面上の座標であり、
焼き付けるべき平面がスクリーン(=nearプレーン)であるならば
(x', y', N)である。
であるからしてすなわち上述の式から
$$
x'=N\frac{x}{z}\\
y'=N\frac{y}{z}
$$
MAP
なにやら適当な数値を[min, max]範囲内において[0, +1]に収めることを考えると、その変換式は
$$
(value-min)/(max-min)
$$
戻す時は
$$
min + (max-min)*t \quad (0 \leq t \leq 1)
$$
[-1, +1]に収めるならば
$$
2*(value-min)/(max-min) - 1
$$
戻す時は
$$
min + (max-min)*\frac{(t+1)}{2} \quad (-1 \leq t \leq 1)
$$
ここで[0, +1]に収めるだの[-1, +1]に収めるだのは、
変換後の値を等間隔に出力させることを暗に意味している。
そういう等間隔に出力させるのは線形変換であって、1次関数の仕事である。
例えば
$${(value-min)/(max-min)}$$や$${2*(value-min)/(max-min) - 1}$$
の場合、
$$
value*A + B
$$
なる形に強引に変換できて、出力範囲が[0, +1]の場合、これが
value=min の時、出力0
value=maxの時、出力1
となれば良い訳だから
$$
min*A+B=0\\
max*A+B=1
$$
なる連立方程式が立つ。
これを解くと
$$
A=\frac{1}{max-min}\\
B=\frac{-min}{max-min}
$$
となって、
$$
value*A + B
$$
に戻すと
$$
(value-min)/(max-min)
$$
であることが分かる。
透視射影
参考
ゲームプログラミングのための3Dグラフィックス数学 単行本(ソフトカバー) – 2002/10/25 Eric Lengyel (著), 狩野 智英 (著)
ここでx', y' を[-1, +1]の範囲に収めることを考える。
$$
x''=(x'-left)\frac{2}{right-left}-1\\
y''=(y'-bottom)\frac{2}{top-bottom}-1
$$
x' やy' (スクリーン座標)をx, y (3Dモデルの座標)で表すと
$$
x''=\frac{2N}{right-left}(-\frac{x}{z})-\frac{right+left}{right-left}\\
y''=\frac{2N}{top-bottom}(-\frac{y}{z})-\frac{top+bottom}{top-bottom}\\
$$
ついでだから全部文字にすると
$$
x''=\frac{2near}{right-left}(-\frac{x}{z})-\frac{right+left}{right-left}\\
y''=\frac{2near}{top-bottom}(-\frac{y}{z})-\frac{top+bottom}{top-bottom}\\
$$
深度
ここでx' y' に対応付いたz' を考え、これを深度とみなす。
この深度という値は、あると便利だから作られる。また、便利なので深度の範囲は[-1,+1]や[0, +1]に収められる。
MAPの項で記述したとおり、素朴に線形に変換するのなら
$$
z'' = A * z' + B
$$
であり、
z' = -1 = min ,
z' = +1 = max
として連立方程式を立てれば良いのであるが、
$$
z'' = A * \frac{1}{z'} + B
$$
とすることが推奨される。便利だからである。
1/zによる連立方程式は
$$
-1=\frac{A}{N}+B\\
1=\frac{A}{F}+B
$$
であるから
$$
A=\frac{-2FN}{F-N}
B=\frac{F+N}{F-N}
$$
ゆえに3Dモデルの頂点座標zに応じた深度z''は
$$
z'' = \frac{-2FN}{F-N}(\frac{1}{z})+\frac{F+N}{F-N}
$$
z'' を図示すると反比例のグラフを成す。
x' y' に対応付いていることが重要で、元々異なるx,y 座標値を持っていても、パース変換を経て、スクリーン座標上で同一のx' y' を有することがある。その場合、あらかじめz' を計算しておけば表示をするしないを選択できる。
この場合、スクリーン上の全てのピクセルにおいてz'値が比較テストされる。
まず、スクリーンのピクセル個分のデータ格納領域であるZバッファを用意する。これはプログラム的にはスクリーンのピクセル個分の要素を持つ配列あるいは2重配列であり、CPUなりGPUなりにハード的に実装されたメモリ領域であったりする。
スクリーン描画時に描画座標(x', y')に対応するz' 値を確認し、まだ何も描画されていないのであればz' を記録。すでにz' が記録されているならばz' を比較した後に描画座標(x', y')に描画するかしないかを決める。すなわち後ろに隠れている物は描画する必要がない。
元々のz値を使えないのか
おそらく使えると思われるが、利便性のために[-1, +1]あるいは[0, +1]の範囲に正規化されると思われる。
クリッピングも同時に行われる。
Zバッファ情報を用いてオブジェクトに影を付けることができる(シャドウマッピング)
陰面消去
Zソート(画家のアルゴリズム)
ポリゴンを後ろから順番に描画していく。
ポリゴン同士が交差している場合、ポリゴンを分割するなどの迂回策が必要となる。(Newell's algorithmなど)
Zバッファ(深度バッファ、デプスバッファ)
深度の項を参照。
この記事が気に入ったらサポートをしてみませんか?