Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /home/zhenxiangba/zhenxiangba.com/public_html/phproxy-improved-master/index.php on line 456
[go: Go Back, main page]

Should I keep company with "homogenize"?
2/9 同次座標とどこまでつきあうべきか





の座標


 僕がながいこと馴染めないでいる考え方のひとつに、同次座標系があります。

 3Dプログラミングを少し前から齧っている方ならお分かりのとおり、これは4×4行列でひとつの三次元座標系をあらわすやり方で、通常の、(x,y,z)ではなく、(x,y,z,1)という表記を用い、四次元数学的観点から、座標系のあらわしかたを簡略化しようというものでした。

 利点は明確です。まず、ひとつの行列で拡大・移動・回転の全てをあらわせること。もうひとつは一つの行列でほぼ全ての変換を行えてしまうことです。つまり、単純になると。

 ところがこれは非常に曲者です。

 まず、もともと姿勢表現のために必要なのは、単に3×3行列と一本ぶんの位置ベクトルがあれば、大抵の座標系は事足りるのです。そのぶん、いらない計算まで背負い込んでしまうことになります。

 これを人間が手で計算するときは0と書いてある部分は無視して飛ばすこともできましょうが、コンピュータにはどだい無理な話です。

 なによりも理解し難いのは、プロジェクション行列を使ったときの作用です。

 視野座標系から画面上の座標に変換するときに、なぜか同次座標は(x,y,z,w)であらわされ、そして信じがたいことに、実際のスクリーン座標を求めるためには(x/w,y/w,z/w)としなくてはならないのです。

 ただこのためだけに、4番目の要素Wが必要となります。

 しかし待ってください。スクリーン座標をもとめるのに、なにもWなどという新しい座標単位を求める必要があるのでしょうか。

 現実には、スクリーン座標を求めるためにはx,y座標をそれぞれzで割る方法がよく知られています。

 また、zバッファのためにスクリーン上のz座標を知るには、1/zを用いる方法なども知られています。

 ですから、必ずしもこの第4の座標に縛られる必要はないのです。

 Direct3Dと普通に付き合っているとき、この座標系の奇妙な性質について考える機会はそれほど多くありません。むしろ空気のような存在であるとさえいえます。しかし、ひとたび最適化を行おうとすると、真っ先に目につくのがこの余分におもえる要素wなのです。

 私の提案する、ベクトル化メッシュ描画のためには、MMXテクノロジを使用することが大きな成果をあげるであろうことは想像に難くありません。つまりなんとしてもMMXテクノロジを用いて最高の成果を上げたいと考えているのです。

 しかし、この第4の座標は、整数化しようとした段階でその牙を剥き出します。

 単純にいえば、この第4の要素に頼り切った計算を行うため、最後の最後まで・・・つまり、実際の画面座標を算出するまでにあまりにも莫大な数になってしまうのです。

 莫大な数になってしまうと、桁溢れがおきます。

 例えば整数行列演算専用のコプロセッサを持つ某コンシューマ機では、16ビット値で4096を基数とした固定小数点を用いるのが普通です。この場合、小数精度は12ビット固定ということになります。むろんこのマシンでは同次座標など用いません。

 ところがなんと、私がプログラムを書いてみると、愛すべき同次座標は、その程度の精度も持つことを許されないのです。試してみた限りでは、32ビット整数を使っても10ビット(1024を基数)が限界でした。

 10ビットの精度というのは、ご存知ない方のために申し上げますと、非常に低い精度と言わざるを得ません。もともと粗いと言われているコンシューマ機に比較して、さらに精度が1/4になってしまいます。これではパソコンの強みである高解像度のゲームはとてもではありませんが実現することは難しくなってしまいます。しかもコンシューマ機は16ビット整数で12ビットの精度を出せるのに対し、Pentiumでは32ビット整数を使ってやっと10ビットですから、その差は倍以上です。

 これは信じられないことです。それほどまでに同次座標系は効率を悪くしてしまうのでしょうか。

 最も簡単な対策は同次座標系を使うこと自体をあきらめてしまうことです。

 これは容易ですが、同時に別の問題も引き起こしてしまう可能性があります。

 それは、Direct3Dが要求するZバッファ用の値をなんとか算出しなくてはならないことです。この一点で、同時座標系はそうでないものよりもより便利でした。

 なにはともあれ、またひとつ障害に遭遇してしまった今日このごろです。

 これから取るべき道は三つ考えられます。ひとつは、MMX命令の使用をあきらめて浮動小数点法を使ってベクトル化メッシュをなんとしても実装すること・・・これはこれで有効でしょう。もうひとつは、なんとか同時座標系を切り捨てて、Zバッファの問題も解決すること・・・これでもいいと思います。三つ目は、MMXが浮動小数点をサポートするまで待つことです。・・・これはかなり気長な話となります。

 MMX命令を使うためだけにVisualC++5.0を購入した私としましては、とりあえず二つ目の方法を試してみたいと考えています。でなければ浮かばれませんからね(笑)。

 その後、そのほかの方法についても考えてみることにしましょう。まずはなによりZバッファ用のrhw値をどうやってもとめるかです。