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]

Mesh Optimization[VIII]
2/15 メッシュの最適化[VIII]/技術的臨界点





まず不可能なのはなにかを考える



 こんにちわ。

 ずっと以前にみためっくす氏からお手紙を貰っていたのですが敢えて紹介しなかったものを紹介しましょう。



			<前半略>

 僕が表示しようとしていたのは国土地理院の標高地図(ランドスケープ)なの
で、すべての座標が等間隔に並んでいたわけです。だからZX平面上の座標は単なる加算で求められるわけです。ZX平面上の座標は、

zx.x+=plus.x;
zx.y+=plus.y;
zx.z+=plus.z;

ってかんじで、3回の加算で求まるはず。
あとは、このZX平面にY座標をはやしてやればいいわけです。ZX平面に対す
る法線ベクトル(Y軸)に、高さをかけてやればOK.

y.x*=height;
y.y*=height;
y.z*=height;

で、最終的な座標は

a.x=zx.x+y.x;
a.y=zx.y+y.y;
a.z=zx.z+y.z;

になって、スクリーン座標に変換する時は、やっぱり割ます。

v.x=a.x/a.z;
v.y=a.y/a.z;


というわけで、加算6回、乗算3回で絶対座標が求まります。スクリーン座標に
直す時に除算2回と加算をいれたきゃ入れてもいい。というぐあいに、結構お得
になります。
 この当時は数十万頂点ぐらい1フレームに表示してアニメーションさせられる
と本気で信じていたおばかさんだったので、こういう無茶な方法を考えました。
また、その当時はDirectX5を入手できておらず、OpenGLで作って
いたので、この計算の恩恵にあずかることはまったくできませんでした。このこ
とから、私はOpenGLに見切りをつけDirect3D−IMへの道へと入っ
ていったのです。
 ちなみに、必要に迫られて、Direct3D−IMとOpenGLの両方で
動くX2TrueApex3Dエンジンが、やっとできそうです。今までは計画
倒れでしたが、今回はちゃんと動いています。お仕事用なので公開できないでし
ょうけどね。


とか書いてきたら、最新のぷれじゃでぃすでTLVERTEXの件に触れてますね。実際
のところ速さはどうなるんでしょうねぇ? 残念ながら、現在3Dとは別の仕事
をしているので清水さんの結果だけ期待してます(^ ^;
 ではでは。

みためっくす
mitamex@sf-design.com

 これは彼がランドスケープを高速に描画しようと研究していたときのやり方などを説明してくれたものです。

 さて、ここで気になるのは次の一文です。

この当時は数十万頂点ぐらい1フレームに表示してアニメーションさせられる
と本気で信じていたおばかさんだったので、こういう無茶な方法を考えました。

 この文章を思い出して、「これだっ」と思ったわけです。つまりソフトウェアをハードウェアに宿る霊魂とするならば、どんなに最適化してもハードウェアの限界以上のことは絶対にできないのです。

 前回までのようなコーディング上の工夫を凝らしていく作業は、どことなく生協で夕飯のお買い物をする奥様の心理に通じるものがあります。

 10円でも1円でも安く、日々の夕飯をこしらえれば、その10円や1円の差が何十年もの長いスパンでみるととんでもなく大きく跳ね返ってくることを彼女たちは知っているのです。

 プログラマがコーディング上の工夫を凝らすときもこれと似たようなものです。「栄養(組み合わせ)」を考え、「値段(クロック数)」を安くしあげるのにエネルギーを使います。

 しかし、どんなに奥様が血眼になって安い店を探しバーゲンに通ったとしても、1円で1kgの米を買うことはできません。つねに限界があるわけです。

 奥様をソフトウェアとすればスーパーマーケットを含む流通機構はハードウェアです。その制約によって、奥様はある一定額よりも安い米を買うことはできません。

 コンピュータにも同じ事がいえます。

 例えばどんなに工夫しても、それが変数対変数の割り算で或限り、一定クロック以下では処理できません。

 特に浮動小数点方式を採用するともなれば、それはなお更のことでしょう。

 私がやろうとしているのは頂点の相対ベクトル化による変換計算の削減ですから、どうしても削れないある決まった処理があるわけです。

 この場合、それはスクリーン変換とベクトルの加算処理です。どんなに最適化しようとこれを省くわけにはいきません。

 そこで、実際にそれを行うコードをC++言語で書き、VisualC++5.0を使って「最大限の最適化」をかけてみることにしました。

 その結果、クロック数は次のようになりました。

ベクトル加算+スクリーン変換    77クロック
普通の行列計算+スクリーン変換   140クロック

 つまりどんなに最適化しても2倍以下しか速くならないということです。

 ただし、メモリアクセスは相対ベクトル加算の方が少なくなるはずなので有利です。
 しかし最も理想的なのは、全ての頂点が少なくともL2キャッシュに入るようにプログラムを組むことでしょう。もっともDirect3Dが内部的にどのくらいのメモリアクセスを必要とするかわからないので正確にそれを行うのは不可能に近いことです。

 どうでしょう。雲行きが怪しくなってきました。つまりいまのプロセッサではどんなに工夫してもシャアにはなれないことが確定してしまったのです。




次に不可能を可能にするのはなにかを考える



 私が自分の授業で説く高速化の鉄則のひとつに、「あきらめる」というものがあります。

 人生、諦めが肝心です。どんなに高速化しても、シャアにはなれないのです。こうなったら目指すのは連邦の白い奴しかないでしょう。

 三倍とはいかないけれども、なんだか知らないが強い。それが白い奴です。

 もう正攻法では太刀打ちできません。

 あきらめるべきことはいくつかありますが、最大のものは「ポリゴン描画をあきらめる」ことでしょう。どう考えても、ポリゴン数が変動しない限り、従来のやり方に圧倒的な差をつけるのは困難です。

 しかしライバルであるDirect3D Retained Modeには、既にそのような工夫があります。いわゆる「Progressive Mesh」という奴です。

 しかし、嬉しいことに、Progressive Meshはそのままでは普通のメッシュよりも遅いという噂があります。この差を相対ベクトル化によって埋め、なおかつ今のProgressiveMeshとRMの組み合わせでは不可能なことを実現すれば、勝機はあるかもしれません。

 RMのProgressive Meshのすごいところは、無段階ディティールを実現していることです。実際のポリゴン数の何割を描画させるかを指定するだけで、勝手にポリゴンが減ります。

 原理もそれほど複雑ではありません。

 基本的には、フラクタル的な考え方で、例えば二つの三角形があったら、その頂点を一致させ、ひとつの三角形にまとめてしまうというやりかたを採用しています。

 Progressive Meshの欠点は、大きくて複雑すぎる物体には最初から役に立たないことでしょう。

 つまり、いまのProgressive Meshは全体としてのディティールをいじることはできても、物体が巨大な場合、物体の遠くにある部分は疎に、近くにある部分は密にといった設定ができません(原理からいけば当然ですが)。

 では果たしてこのようなことは不可能でしょうか。実は可能です。

 原理的には、このコーナーでとりあげたことのあるフラクタルを利用したProgressive Landscapeと同じものです。

 ですから、巨大なメッシュのうち、視点に近いほうは再帰的に詳細度を上げ、遠いほうは詳細度を落とすといったことが可能です。

 このやり方が便利なのは、例えば今までは分割しなければならなかった超巨大戦艦などをひとつのメッシュとして扱えることです。また、やりようによっては従来のように近づいたら単純に切り替える方法よりも違和感なくポリゴン数を制御することが可能になります。

 しかしまぁ、これは少し行き過ぎた例でしょうか。

 他の可能性について考えてみましょう。

 Direct3DのRMがもっている機能のうち貧弱なのは、メッシュ描画よりもむしろアニメーション機能だといえます。

 テクスチャアニメーションはもとより、単純な組み合わせアニメすら作れません。また、ワンスキンアニメーションもInterpolateを使うしか方法がありません。

 しかも、アニメーションの場合はMIP-MAPが使えませんし、そのほか不具合多数です。

 しかし近年の3Dゲームにおいて、キャラクタのアニメーションは不可欠で最も重要視されるポイントになってきています。

 ですから、アニメーションと高度に融合したメッシュ描画ルーチンがどうしても必要になってきます。

 RMのようにアニメーション機能とメッシュ描画機能を切り離すよりも、一体化させてしまうほうがより高効率をねらえるのではないでしょうか。


 さて、整理して考えてみます。

 もともとこのシリーズのテーマは新しい、そして現状よりも高速なメッシュ描画アルゴリズムを考えるというところにありました。

 しかし、とりあえず考えてみた相対ベクトルの単純加算による高速化では早くも限界が見えています(それでもやらないよりはマシだと思いますが)。

 残念なことに、現在、メッシュ描画のボルトネックとなっているのは殆どの場合3Dカードまたはバスの性能であって、計算ではないということです。つまり計算が1.5倍速くなったからといって全体が高速化するわけではありません。

 それでもなお、現状以上のパフォーマンスを望むのならば、それなりの工夫・・というか妥協が必要になってきます。

 その一つの回答が距離に応じてポリゴン数を増減するProgressibe Meshであるわけです。

 また、さらなる高効率を目指すとき、それはメッシュ描画のみならずアニメーション管理についても根底から考え直す必要があります。繋ぎ目のない人体モデルや、組み替え自由なモデルを作るにはどうすれば良いのか、問題は複数あります。

 ということで、ここからさきはじっくり腰を据えて考えてみないことには話が進まないようです。

 なにかご意見ご感想があればお気軽にお寄せください。