2Dと3Dとマップ描画処理

DirectXの描画にはDrawPrimitiveとDrawPrimitiveUPがある。どっちが速いのか、どう使い分けるのか。


頂点バッファっつーものがある。これはVRAM上に頂点の座標その他の情報を突っ込んでおいて、GPUから高速にアクセスするためのものだ。
DrawPrimitiveはこの頂点バッファを指定して描画する。対してDrawPrimitiveUPはメインメモリに作った頂点情報のポインタを指定して、VRAMに転送、描画、という流れになる。
いずれにせよいったんVRAMに転送しないとGPUからは参照できないから、毎フレームほとんどの頂点を変更する用途なら、DrawPrimitiveUPを使うほうがよい。
具体的には2D描画。
2D描画の場合はスクリーン座標で頂点を指定するため、毎フレーム、画像1つごとに頂点バッファをロックして書き換えてアンロックするなら単純に無駄だ。


DrawPrimitiveを使う用途は、頂点が多くて書き換えの少ないパターン。つまり、膨大な頂点を持つ3Dオブジェクトを描画する場合、となる。
3Dの場合は頂点はローカル座標で持ち、ワールド変換行列で位置や姿勢を指定するから、頂点情報は変わらない。こういう場合にはDrawPrimitiveのほうがよい。
じゃあ、頂点バッファにローカル座標を入れておいて、ワールド変換行列で画面上の位置や回転を制御すれば2Dでも速くなるのか、というと、そうでもない。ワールド変換行列を変更するとビュー変換・射影変換の行列も再計算する必要が出てきて、これに相当時間がかかるから、画像1枚ごとに再計算していては大変なことになる。
2Dでは自前で最小限の座標計算式を構築して頂点を設定してDrawPrimitiveUPするのがやっぱり速い。と思う。


また、インデックスというのもある。DrawIndexedPrimitiveとかDrawIndexedPrimitiveUPとかで使う。
これは頂点情報に連番を振っておいて、どの頂点を使うかをその番号で指定する、というものだ。
どういう場合に使うかというと、1つの頂点を複数のポリゴンが共有する場合、まあ、普通の3Dオブジェクトならよくあると思うが、そういうのが多い場合に頂点情報そのものを削る効果がある。
頂点情報が減ると座標変換処理も減って、効率が上がる。2Dでも三角形2つで四角を表現するから6頂点となっていて、2点は共有されているからインデックスを使うことで座標情報は4頂点に減る。逆にインデックスによる参照処理が増えるから、2D描画程度では効果があるかどうか微妙だ。実際どうなのかはまだ試してないから、一度試してみる価値はあるかもしれない。


ちなみにDXRubyでは2D画像は自前で座標を計算してDrawPrimitiveUP、3Dのメッシュ描画はID3DXMeshを使っていて、これは内部で頂点バッファとインデックスバッファを持ち、最適化して頂点数を減らしている。
素人なりに一応描画速度のことは気にしているつもりだ。


マップ描画の話を書こうと思ってタイトルに入れといて、書いてみたけど書いていてダメなことがわかったので消した。