GPU上でのVoxel構築手法(3)

先の記事を踏まえてGPUでVoxelizeを行ってみました。

実装に際しての変更点など

Conservative Rasterization
Conservative Rasterizationは、2D投影平面上で必要なオフセット量をエッジの法線に応じて計算し、それを3Dのポリゴン平面上で適用しています。こうすることで、ラスタライズされる際にポリゴン平面の位置を保存することができ、これによりpixel shaderですばやく交差する可能性のあるvoxelとのチェックを行うことができます。

voxelとポリゴン平面の交差テスト
先の記事では、最初にvoxelとポリゴン平面の交差テストを行うように記述していました。実装では、geomerty shader側でポリゴン平面のdepth gradientを計算しておくようにしました。これでpixel shader側で簡単に平面の交差テストを行うことができます。具体的には、pixel shader側に渡された、投影平面の補完された座標値のz値の整数部が交差するvoxelを表します。加えて、小数部とdepth gradientの和が1を超えれば深度方向に+側に隣接しているvoxelにも交差していることになります。さらに、小数部とdepth gradientの差が負の値ならば反対側の隣接voxelにも交差していることになります。

pixel shaderにおける分岐
geometry shader側には分岐する必要のある処理がほとんどありません。対して、pixel shader側には各テストの結果に応じて大量の分岐が生じます。
分岐の要素として最も大きいものは、深度方向のチェックで交差判定を行う事になる、最大2つの隣接voxelです。これを分岐処理で記述しても、XY平面で隣接するvoxelとの分岐の傾向に相関が少ないので、まったく意味がありません。結局、中心とあわせて3voxel分のテストの処理を行うことになります。最適化の可能性があるとすれば、depth gradientの値による分岐です。depth gradientの値が0.5より少ない場合は、深度方向で最大2つのvoxelしか交差しません。したがって、この場合は2voxel分の交差テスト処理を行えばよく、depth gradientの値はポリゴン平面内で一定なので、pixel shader内の分岐は一定となります。しかし、この実装を行ってみたところ、あまり有意な差が得られませんでした。voxelizeするモデルの形状にもよるのですが、gradientの値が0.5以下になる割合が少なすぎるとあまり意味がありません。このあたりはシェーダーの最適化を進めるときにまた考えてみたいと思います。

ポリゴンの形状による問題点
今回採用しているConservative Rasterizationの方法では、geometry shaderで頂点を増やすことなく処理を行います。そのためポリゴンの形状によっては非常に多くのvoxelと交差判定を行う必要が発生します。具体的には三角形の形状が細長い場合です。今回使用したモデルでは比較的そのような形状の三角形は少なかったのですが、それでもこの問題は発生しました。以下の画像は、該当のポリゴンから発生したラスタライゼーションの結果です。実際のアプリケーションでvoxelize処理を行う場合は、事前にモデルの三角形の形状をチェックしたほうがよいかも知れません。

処理時間

6 SeparationgVoxelizationでStanford Bunny(69451 polygons)をGTX480でvoxelizeしました。voxel解像度とvoxelizeにかかる処理時間を表にしました。(ただいま代替機で作業してます。そのうち680で調べます)

6 Separating Voxelization
voxel解像度 5123 2563 1283 643
処理時間 1.98ms 1.59ms 1.49ms 1.44ms
充填voxel数(充填率) 531356(0.39%) 121880(0.73%) 27793(1.3%) 6508(2.5%)

1283以下の解像度ではgeometry shaderがボトルネックになってしまっているようです。これ以下の解像度ではあまり処理時間が変化しません。
一方、5123の場合でも2ms以下で処理することができるようです。ちなみに、voxelのSeparatingによる交差判定を行わずに描画した場合は0.47msで描画できました。これでは描画に破綻があるので使用できませんが、おおよその差である1.5msがSeparatingの判定処理による時間とみなすことができると思います。
また、voxelの充填率は同じモデルを同じ領域でvoxelizeした場合は、voxel解像度が上がるにつれて充填率が低下していきます。つまり、だんだんと疎なvoxelizeになっていくということです。このあたりも興味深いところです。

以下の画像は一応ですが、voxelizeされたときの様子です。

643
1283
2563
5123

意外な落とし穴 – voxelのクリアにかかる時間

上記の処理時間に、voxelのクリア時間を含めた処理時間を以下に示します。

6 Separating Voxelization
voxel解像度 5123 2563 1283 643
処理時間(クリア処理を含む) 8.7ms 2.42ms 1.60ms 1.46ms

voxelのクリアにかかる時間は、GTX480でテストを行う限り、voxel解像度と共に飛躍的に増えます。5123では6ms以上にもなります。冷静に考えれば、512×512のRender Target512枚分のクリア処理を行えば、このぐらいの時間がかかるかもしれません。実際のアプリケーションでは、クリア処理が必須なので、いくらvoxelize処理を最適化しても安易なクリア処理を行えば台無しになってしまいます。できれば描画処理の直前でクリアを行うのは避けたほうがよいかも知れません。加えてこのあたりで、octree化しないvoxelの限界が見て取れるような気もします。

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中