DirectXの話 第133回
GPUによるMarching Cubes
今回はかなり適当ではありますが、GPUを使ってMarching Cubesを描画してみました。
Marching Cubes自体はかなり昔に当サイトの前身(要はもんしょの巣穴1.0)にてやっていましたが、そちらはCPUでポリゴン生成しているものでした。
なのでリアルタイムでなんとかするにはちょっと厳しいものがありましたが、今回はリアルタイムに生成しています。
ちなみに、ソースコードの更新日時を見ると2008年でした。4年前ですね。
Marching Cubesの概要についてはここでは説明しません。
必要であれば他サイトで調べていただくか、過去記事を参照してください。
サンプルは幅64の3DテクスチャにCompute Shaderを用いて数値を入力、この3DテクスチャをGeometry Shaderで参照して描画しています。
法線方向は面法線をそのまま利用していますが、あまりよろしくはないですね。
しかし、いまいち他にいい方法が見つからなかったので、何か良い手段があったら教えてください。
工夫と言える工夫は何も行っていません。
以前のCPUによるサンプルをそのままGPUに移植しただけです。
前回のサンプルでは動かしていませんでしたが、今回は動いてます。見た目の違いはその程度ですね。
そんなわけで記事として書くことがほとんど無いというダメさ加減。困った。
まあ、実装についてはサンプルを見てください、としか言いようがないので、見てください。
では、速度面の話をしましょう。
上の画像を見ていただければわかりますが、幅64だとまだまだ粗いです。
Marching Cubesの使い道としてはパーティクルによる液体表現なんかがあります。
パーティクルベースの物理エンジンによって液体を表現する場合、その演算以外にも描画部分が問題になります。
これをMarching Cubesで表現するのは割とありではあるのですが、残念ながらこの粗さでは使用には耐えられないでしょう。
しかし、幅を大きくしてみたら死ぬほど重かったわけで。
自宅の環境では、幅64で200FPSちょっと、幅128で30FPSちょっと、幅256で5FPS弱という結果になりました。
5FPSはとてもではないですが使い物になりません。
30FPSも上図のような物を描画するだけでこの重さでは割に合いません。
なぜそんなに重いのか?
それには2つの理由があります。
1つはCompute Shaderによる3Dテクスチャの計算、もう1つはGeometry Shaderによる描画です。
前者についてはそもそも3Dテクスチャのクリアだけでも非常に重いのですから、計算して埋めていくとなるとかなり重いのは当たり前です。
256*256のテクスチャを256枚分、リアルタイムに埋めていくと考えれば重くて当たり前とわかってもらえるかと思います。
後者はMarching Cubesの各キューブの数だけ描画を行うわけで、不要な場所(ポリゴンが生成されない部分)であってもVertex Shaderは動いてしまいます。
Geometry Shaderもポリゴン生成するかどうかを求めるわけですから、ピクセル数分だけ動いてしまいます。
幅256の3Dテクスチャの場合、処理される頂点数は1677万頂点です。
重くて当たり前の数値ですよね。
どうすればいいのか?
これについてはCEDECでもSCEEの方が将来的なレンダリング手法について語っていましたが、イテレーションを利用する方法があります。
残念ながら、これによって高速化できるかは未知数です。
イテレーションの回数やシーンの複雑さなどが絡んでくるでしょうけど、とりあえずやってみないとわからないかと。
というわけで、次回はイテレーションを利用した手法を頑張ってみようと思っています。
一応、実装のアイデアはあるので。
と言うわけでサンプルはこちら
Download:Sample124.zip
あんまり綺麗サンプルではないですが、許してもらう方向で。