DirectXの話 第131回
PN Triangles
今回は前回に引き続きテッセレータの話で、PN Trianglesをやってみました。
正直な話、効果が薄くて公開しようか迷ったのですが、テッセレータの重要な使い方の1つを提示できる、という理由から公開することにしました。
この元の論文はこちらの"Curved PN Triangles"です。
今回のサンプルはこの論文中の計算式をそのまま実装しただけの単純な物で、工夫も何もないので解説は行いません。
とりあえずコードを読めば何をやっているのかわかるでしょう。
PN Trianglesは頂点の座標と法線から曲面を求める手法です。
名前の通り、三角形に対して使用されますが、Quadに対しても使用は可能です。
Quadでも使用する場合はPN Patchという呼び方もされますが、基本は三角形に対して行います。
論文でも三角形に対する計算式しか載っていません。
座標と法線は普通のポリゴンモデルを生成すればほぼ間違いなく提供される情報です(法線は絶対とは言えませんが)。
そのため、普通の三角形分割されたポリゴンモデルをそのまま曲面にすることが出来るという利点があります。
欠点としては、法線に連続性がないとクラッキングが発生してしまう点です。
クラッキングとは裂け目のことです。つまり、ポリゴンのエッジ部分に裂け目が発生してしまうわけです。
例えば以下の図をご覧ください。
左がテッセレートなし、右がPN Trianglesによるテッセレートありです。
左はホイール部分にクラックはありませんが、右はホイール円筒の側面と底面の境界にクラックが発生しています。
これは法線が側面と底面で連続していないために発生しています。
このような問題に対処するには角を丸めるようなポリゴンを追加するのが一般的です。
当然、そのためにはデザイナさんに追加してもらうことになるので、それなりに手間が発生してしまいます。
また、全体的に膨らむという問題もあります。
ある程度の滑らかさを持っているオブジェクトの場合、膨らむことによって正常な形状にならない場合があります。
最初の画像のロボットの腕部分は比較しなくてもわかるくらいに膨らんでいますね。
サンプルでTess Factorを1.0にすると元の太さを見ることが出来ますが、それを見ればかなり膨らんでいることがわかるでしょう。
PN Trianglesを使用するのであれば、この膨らむ分も考慮してデータを作成しなければならないでしょう。
クラックが発生する、膨らみすぎるといった理由からテッセレートをしたくない部分も存在するでしょう。
このような場所のみテッセレートしないような設定も可能ですが、そのためにはデザイナさんにそれ用のデータを追加してもらう必要があります。
テッセレータを使用しない三角形ポリゴンモデルとデータをほぼ同一で扱うことが出来ると言っても、このような追加データはどうしても必要になってしまいます。
とまあ、このようにPN Trianglesは割と微妙な技術なんじゃないかと思ったりするわけで。
特に問題なのは重いという点でしょう。
サンプルで使用しているロボットモデルが結構ポリゴン数が多いとはいえ、やはりテッセレートを行うのは重いです。
それでも最初からポリゴンを割っておくよりはいいんじゃないか?と思う人もいるかもしれません。
しかし、先日のCEDECで聞いた話によると、ポリゴンを予め割っておいた方が速い場面が比較的多いという状況らしいです。
これに関してはNVIDIAの方も認めている話で、テッセレータを使ってAddaptiveにポリゴンを分割するのは常に速度を出せる手段ではないと言うことです。
もちろん、速度が出る場面もあるでしょうけど。
また、ポリゴンの分割が多くなることによってモデルの滑らかさが増すという利点についても、カプコンの方がいまいち乗り気ではなかったです。
曰く、ちょっと滑らかになった程度ではユーザに伝わらない、とのこと。
今回のサンプルはロボットと戦車という、滑らかになりにくいモデルであることは否定できません。
しかし、それを考慮しても滑らかになっているという気がしません。
場所によっては比較すれば違いがわかるのですが、逆に言うと比較しないとわからないレベルでもあります。
そのレベルでは技術がわからないユーザだけでなく、技術がわかっている人でも実装されているか否か判断できないでしょう。
Addaptiveに滑らかにする技術は現在のテッセレータの速度からするとあまり効果は高くないと言わざるを得ません。
もちろん、全てが、とは言いませんが。
では、テッセレータって価値がないの?というと、そうでもありません。
CEDECでは、ディスプレースメントマッピングでモデルが変形するような場合には有効じゃないかと言われてました。
UE3の技術デモである『サマリタン』では、人間キャラの肌がディスプレースメントで変形していくシーンがありました。
もちろん、このモデルもディスプレースメントすること前提でポリゴンを割っておくことは可能です。
しかし、通常はそれほどポリゴン数を必要とせず、変身しているわずかな時間だけディスプレースメントが必要、と言った場合にはテッセレータは有効でしょう。
もう1つの使い方としては、頂点ワーピングを用いる何らかの手法を用いる際にポリゴンが大きすぎて歪みが目立ってしまう場合が挙げられるでしょう。
前々回にやったRectilinear Texture Warped Shadow Mapなどはまさにうってつけでしょう。
下の図はテッセレーションあり、なしの場合のRTWSMの結果です。
上はテッセレーションなしですが、影が歪んでいるのがはっきりとわかります。
下はテッセレーションありで、こちらも少々歪んでいます。
しかし、この歪みはPN Trianglesによって元のモデルが歪んでしまったために発生しているだけです。
若干の歪みは発生していると思いますが、全体的に見れば十分許容範囲でしょう。
今回はPN Trianglesでモデルを描画しているため、最初のシャドウマップ、法線・深度マップ、重要度マップ、RTWSMの4つ、加えて最終描画すべてでテッセレータを用いています。
まあ、それが重い原因でもあるのですが。
もしも曲面を使用せずそのままモデルを描画するのであれば、テッセレータを用いるのはRTWSMの描画のみとなります。
例えば、頂点シェーダでワールド座標とワーピングした頂点座標を出力します。
ハルシェーダのConstant Functionでワーピング後の三角形の辺の長さから分割数を求めます。
テッセレーション完了後、ドメインシェーダでワールド座標上のポリゴンを分割、それぞれの頂点をワーピングする、という感じでAddaptiveに対応することが出来ると思います。
元からモデルが十分に細かく分割されているのであれば不要ではありますが、シャドウ用の簡易モデルを使用する場合などはこのような対処が必要になる可能性もあります。
サンプルは下記からDLしてください。
Download : Sample121.zip
今回のサンプルではAddaptive Tessellationは行っていません。
指定されたTess Factorによって一律に分割しています。
Addaptive Tessellationの方法はNVIDIA SDKのサンプルを参照してもらえるといいかと思います。
個人的に、RTWSMには期待しているので、テッセレータによって歪みを最小限に抑えられるなら割とありじゃないかとは思っています。
懸念材料としては、ジオメトリの描画回数がかなり多くなってしまうことでしょうか。
Shadow Edge Functionを使用しなければ1回分減らせるんですがね…