頂点削除 投稿者:
のぞく人 投稿日:2014/04/03(Thu) 21:17
No.8
※技術的な内容なのでどこに書こうかと思ったのですが、取り敢えずこちらに。
twitterで頂点削除を行うと何故描画が重くなるのかという会話を見かけたので、知ってることと推測を少々。
添付した画像は形状カスタムデータの圧縮部分を展開したものです。(例には変体紳士Pさんの超振動装備.wbsを使わせてもらいました。)MNameはメッシュ名、Vtx.Posは各頂点の座標(x,y,z)、Vtx.NVは頂点の法線ベクトルの座標(nx,ny,nz)になります。(メッシュ名のフィールド長が本当に260bytesなのかは知らないです、念のため。)
通常は座標、法線ベクトルとも適当な値の4bytesの浮動小数点数が入っているのですが(Vtx[0])、削除された頂点は値がNaN(Not a Number)になります(Vtx[3])。“FFC00000”というのがそうです。NaNというのは0/0の様に実数(数学的な意味での)として定義されてない値や√-1の様な虚数とかを表す値で、無限大ともまた違います。(ここでは単に意味の無い値だということを表してるだけでしょうが。)尚、Vtx[1]の様に法線ベクトルだけがNaNになっている場合がどうなのかはまだ調べてません。あと頂点座標が全部NaNになってない場合もありますが、これは削除頂点として扱って大丈夫なようです。
ここから推測ですが、これらの値はODFファイルから読み込んだ値に上書きされるだけで処理する頂点数としては変化が無い、要するに頂点が削除されてもポリゴン(面、ODFでは必ず三角形)の再設定などは行われないと思われます。通常ならDirectXの描画ルーチンに値をボンボン突っ込んでけばいいのですが、NaNを見つける度に分岐して「このポリゴンは成立してるの?」「このポリゴン非成立ならこの頂点も描けない?」とかいう判断をしていれば、その分描画に余計な時間が掛かるなあと自分は思いました。
もう一つDirectXにNaNをそのまま渡して「描けねえよ」と例外で突っ返されてるというのも考えました。これだと例外処理なので確実に重そうです。
因みにNaNを有効な値に書き換えてやれば、削除された頂点は復活します。
あとIntelのGPUで削除されたはずの頂点や面が下に向かってビヨーンと引き延ばされて表示されるのは、DirectXがGPUをNaNを扱えないものとして扱ってるからだと思われます。今のIntelのGPUはNaNをNaNとして扱う動作モードを持っているのですが、DirectX9の実装時点ではまだNaNを実数の最小値(だったと思う)に丸めるモードしか無かったんじゃないかと(未確認)。NaNを扱えないモードで動かしてるか、そもそもNaNを渡してないのだと思います。
Re: 頂点削除 - よねすけ 2014/04/03(Thu) 21:38 No.9
明らかに例外的な処理ですし仕方が無いですね。
頂点削除はカスタム画面で大量に消したときが極端に重くて、一度抜けてしまえばFPSが少し下がる程度で再度カスタム画面に入ってもほとんど影響無いのであまり気にしてなかったんですが、環境によっては結構重いようなので最近はできるだけ消さずに残してありますね。
法線ベクトルだけNaNってのは前に言ってたやつですね。孤立した頂点でしょうかね。
Re: 頂点削除 - のぞく人 2014/04/03(Thu) 23:56 No.10
>よねすけさん
なるほど、孤立頂点ですか。もしそうなら削除扱いで大丈夫そうですね。
一度カスタム画面を抜けると描画が軽くなるということは、そのタイミングで描くモノ描かないモノを多少はまとめ直してるのかもしれないですね。あとはデータのセーブ/ロード時あたりですか。
よく読んでみるとDirectXでNaNが例外になると言っておきながらIntelGPUのところではDirectXがNaNを処理してると言ってたりして、矛盾してますね。まあ、書いてる当人もその程度にしか理解してないということです。言い訳すれば、わかっているのはデータ構造だけなので、後は推測するしかありません。(でもDirectXがNaNを渡されて例外を発生させるか位は調べれば判ることか。)