はかせのラボ

私の頭の中を書いていく雑記ブログです

プログラミング 平行投影と透視投影の話

あいさつ

どうも、はかせです。
今回は描画の話です。

なぜ描画?

まずはこの画像を見てください。
f:id:hakase0274:20190708232208p:plain

敵の弾に自分のレーザーが被ってしまっている・・・!
これでは非常にやりづらいですね。
この問題解決のために色々やろうとした話が今回の話になります。

原因は?

原因はわかってます。
各オブジェクト毎に描画をキックしていた時は
生成順=描画順になっており、
描画順に生成すれば意図したとおりの描画が可能でした。

ただインスタンシングを導入したことで
その描画順が狂ってしまったことが原因です。

解決策は?

とりあえず、ぱっと思いつくものだと
描画の優先度を設定するですね。

それぞれの描画データに優先度を設定して
優先度が高いものから描画していくってやり方です。

ただ問題はそれをどう実装するかです。
今はテクスチャ毎に一括でドローコールしています。
つまりテクスチャの種類単位ならばなにも考えず実装していいんですが、
実際はそんなことないですよね。

つまり愚直に優先度を設定してやると、
テクスチャの種類数×優先度の数だけドローコール
しなければならなくなります。
せっかく削ったドローコールを
描画順なんぞのためにまた増やすのは気持ち悪いです。
(Map/Unmapの数が増えるのも気持ち悪い)

なので優先度付けしつつも、
なんとかドローコールを増やさないでできないかを考えます。

描画の話

さて、ここら辺から表題の回収が始まります。
DirectXに限らず、画面描画の際に行うオブジェクトの投影方法には
平行投影透視投影という二種類があります。

透視投影というのは今まで私がやってきた
3Dオブジェクトの投影方法です。
近いものほど大きく遠いものほど小さく描画します。

平行投影というのは2Dの描画に使いやすい投影方法で
カメラとオブジェクトの距離に関わらず
常に一定のサイズで描画します。

今まではDirectXのサイトなどでよく使われていた
透視投影という方法を取っていました。
ただ今私が開発している弾幕シューティングは2D、
奥行きの概念は必要ありません。

つまり透視投影より平行投影の方が向いているということになります。

そして平行投影はZ値に関わらず常に一定のサイズで描画します。
ですが、DirectXのZバッファは依然存在しており、
Z値による描画順の調整は生きています。

つまり、
平行投影で描画し、Z値を優先度とすれば、
優先度ごとにドローコールを増やすことなく
描画順を制御できるのではないか?

というのが今の私の頭の中にある描画処理の全貌です。

あとがき

今回は描画順と投影方法の話でした。
正直ただ優先度付ければいいだろって思って
その辺りを放置してたいままでの自分に
タイキックでも喰らわしてやりたい気分ですw
(実際に喰らいたくはないです)

とりあえず描画順調整のロジックは浮かんだので
その実装ですね。
まぁある程度頭にできてますが、
実際できるかはわかりませんw
(だからやってみるんですけどね)

それでは今回はこの辺でノシ