【ゲーム制作】No.16 PN-AEN テッセレーション(Direct3D11)

今回は テッセレーションの分割の種類のひとつであるPN-AEN(Crack-Free Point-Normal Triangles using Adjacent Edge Normals)の実装になります。


前回行ったPN Triangles テッセレーションでは、一部のポリゴンの継ぎ目で穴があく「クラック」という現象が起こる欠点がありました。


PN-AENではPN Trianglesを改良し、「クラック」の発生を極力防いだものになります。(完全に防ぐ訳ではないみたいです)

 

PN-AENを実装するにあたり使用した資料は以下です。
PN-AEN-Triangles-Whitepaper.pdf

John_McDonald.pdf

 

PN-AENはPNの改良版であり、コードはPNで利用したものが殆ど使用出来ます。
違う点は以下の2点になります。
①IndexBufferの内容変更
②Hull Shader(Control Point) コントロールポイント3から12(9)への拡張

 ※PN-AEN版としては9への拡張なのですが、①IndexBufferの内容変更が

 12への拡張なので12としています。違いは殆どありません。


①IndexBufferの内容変更

PNでのIndexBufferは通常描画と同じで「(インデックス x 3) x 面数」でしたが、
PN-AENでは「(インデックス x 3 + 拡張コントロールポイント x 6) x 面数」に拡張されます。


これによってIndexBufferは元のサイズの3倍になります。

 

手順としてはまず通常の形でIndexBufferを構築し、
何らかの方法でサイズ3倍のIndexBufferに拡張させます。
方法を調査したところ、meshoptimizerというライブラリに
PN-AEN用に拡張してくれるmeshopt_generateTessellationIndexBuffer()関数が
用意されていた為、今回はこれを使用することにしました。

 

関数の簡単な手順は以下の通りとなります。
1、管理者権限でコマンドプロンプトを実行する。
2、vcpkgのソースコードをダウンロードする。「git clone https://github.com/microsoft/vcpkg.git」を実行
3、vcpkgをインストールする。「bootstrap-vcpkg.bat」を実行
4、vcpkgアプリを立ち上げる。「vcpkg.exe」を実行
5、Visual Studioから利用出来るようにする。「vcpkg integrate install」を実行

6、vcpkgにmeshoptimizerライブラリをインストール「vcpkg install meshoptimizer」を実行
7、ここまでやると後は、普通にVisual Stadioで使用出来ます。
 C++ファイルの先頭に「#include "meshoptimizer.h"」と記述し、
 「meshopt_generate_tessellation_index_buffer(p_index_buffer_dst, NULL, p_index_buffer_src, 6, vb, 6, 12);」と書けばビルド出来ちゃいます。ちょっと凄い!


 「略・・\vcpkg\vcpkg\buildtrees\meshoptimizer\src\v0.18-13698cd784.clean\demo\tests.cpp」の
 tessellation()に使用方法があるので参考にしてください。


 いくらかテストで動かしましたが問題無く動いています。(エラーが出る場合、十中八九引数の誤りだと思います)


 またvcpkgはこのサイトが参考になります。

 

 注意点としてmeshopt_generateTessellationIndexBuffer()で出力されるIndexBufferは
 「(インデックス x 3 + 拡張コントロールポイント x 6) x 面数」では無く
 「(インデックス x 3 + 拡張コントロールポイント x 6 + 拡張コントロールポイント x 3) x 面数」となります。
 そしてIndexBufferは元のサイズの4倍になります。
 ただし対するコードの変更は数字の変更のみで殆ど必要ありません。

 

②Hull Shader(Control Point) コントロールポイント3から12(9)への拡張

 

Hull Shader(Control Point)のコードをPNからPN-AEN用に切り替えます。
PN用ではコントロールポイントは3つでしたが、PN-AEN用はコントロールポイントは12になります。


これは「PN-AEN-Triangles-Whitepaper.pdf」のサンプルコードそのままで問題ありませんでした。
PN用はHS_PNTriangles()、PN-AEN用はHS_PNAENTriangles()です。

 

この様にコンパイルで使い分けします。
HullShader        g_pmx_object__tessellation__HS_main_PNTriangles    = CompileShader(hs_5_0, pmx_object__tessellation__HS_main_PNTriangles());
HullShader        g_pmx_object__tessellation__HS_main_PNAENTriangles    = CompileShader(hs_5_0, pmx_object__tessellation__HS_main_PNAENTriangles());

 

PN-AEN用のHS_PNAENTriangles()では引数「InputPatch<HS_RenderSceneInput, 9> I,」
数字をその時の値に書き換えましょう。( 3 or 9 or 12)

 

CPU側では「D3D_PRIMITIVE_TOPOLOGY_12_CONTROL_POINT_PATCHLIST」
こちらの数字も同じように書き換えます。( 3 or 9 or 12)

これでうまくいきました。

 

PN用の画像では右目の上辺りにクラックが発生していますが、

 

PN-AEN用では発生していないのがわかります。