描画の最適化を考える

前の記事で書いたダンジョンゲーの画面を大きくしたやつをうちのノートで動かすと30fpsとかになった。
このノートは遅いからしょうがないのかもしれないが、描画負荷を全く考えてないサンプルをベースにしているから、そのへんにも原因がある。


ダンジョンゲーの描画はサンプルと同様にダンジョン全体を一つのメッシュにして描画している。理論的にはそれで問題なく描画はできる。
うちのノートで遅い原因は、描画するピクセルが必要以上に多いからではないかと考えている。
つまり、奥の絵を描画してから手前の絵を上書きすることで、描かなくてもいいピクセルを大量に描いている、ということだ。
この問題を解消する手としては、簡単に考えてみた感じでは2つ。
(a) メッシュに登録する頂点の順番を変更する。
(b) メッシュを分解して描画する順番を変更する。


(a)の手は、無造作にメッシュに登録しているから、奥→手前で描画するパターンが発生しているのが原因であると見て、それを解消する方法だ。
現状のDXRuby1.1.12devでは最適化により頂点の順番を入れ替えてしまうから、それを抑制する必要はある。
んで、2次元マップを考えたときに、下向きの面は下から順に、上向きの面は上から順に並べる。左右もそう。
これで、どの位置からどの方向を見ても、描画する面は(正面を向いているものに限って)手前から順になる。
メッシュを作る場合のアルゴリズムを工夫する必要があって、ちょっと骨が折れる。


(b)は例えばブロック単位にメッシュを分けて、描画優先順位に視点からの距離を指定する。DXRubyのソート機能により近いほうから順に描画してもらう。
これは描画負荷こそ減るがRuby側の負荷が増えるから、効果があるかどうかはマップの規模にもよってくるかもしれない。
ダンジョンゲーの場合はリアルタイムでやる処理が少ないし、意外に効果がありそうな気もする。
この方法を採用するにはメッシュ生成・描画のロジックを全面書き換えする必要がある。


一昔前のノートPCで厳しいという現状は、3Dゲーの負荷の高さと、それを作る場合にパフォーマンス面に細心の注意を払う必要性を物語っている。
DXRubyは描画の速さでRubyの遅さを補うのを売りの一つとしているが、ダンジョンゲーの場合はRubyの処理などほとんどない。遅いのは3D描画であって、ほとんどがDirectX APIの時間、GPUの処理時間なのだ。いままでやってきた2D描画とは次元が違う。
ユーザーにそれを考えろというのは簡単であり、ライブラリ側でそれを何とかしようというのは無茶だ。特にDXRubyは描画の基本機能のみを提供するものだから、データ構造を規定してそのようにデータを作れば高速描画できます、というのはちょっと違う気がする。
言うなれば、3D描画を初心者が気楽に作れるほどPCの性能が余っているわけではない、ということだ。開発者がテクニックを駆使してパフォーマンスを上げなければならない。残念ながらまだPCの最低性能はそこまで上がっていない。


なかなか厳しい状況なのだが、俺にできることはというと。
・3D描画は効率を考えなければ重いということをアピールする。
・んで、描画効率のよいサンプルの提供。
っつーことになるのではないかと。
要するに今のメッシュ1つでテキトーにポリゴンを構成してダンジョンを描画しよう、というアプローチが根本的に間違っているわけだ。
そりゃそうか。
反省。