Tessellationを用いたなんちゃってスカルプト
はじめに
何かが衝突した影響でモノが変形したり…といった表現は結構巷にあふれていて、その手法も様々です。 一番シンプルに思いつく実装方法といえば、衝突の際に実際にジオメトリを変形させることでしょうか?
今回は実際の頂点データを弄らず、GPUで頂点を変形してレンダリングさせています。なので、ランタイムでの利用を想定しています。
用途としては…アルミ缶とかに何かをぶつけて適当に凹ませたり…?
あんまり用途は思いつかなかったです。
壁みたいな、実際に頂点の密度が細かくないようなモデルでもいい感じに変形出来るのが良いところでしょうか?
実装
実装といっても、特殊なことは何もありません。ただのDisplacementMappingです。 基本的にはInkPainterの、TessellateHeightTransformサンプルを改造していく感じで作りました。
InkPainter/Assets/InkPainter/Sample/SampleScene at master · EsProgram/InkPainter · GitHub
なので処理的には
- DisplaementMapに対して、凹凸情報を好きなように書き込む
- この凹凸情報を参照して変形するShaderを書いてモデルの描画に使うようにする
という感じです。
書き込みはInkPainterの機能を使い回しました。
変形処理ですが、引き伸ばされた辺をいい感じに分割してほしかったので頂点シェーダーで変形後の頂点の辺の長さを考慮してTessellationを行っています。
動画を見ると結構目立つのですが、ポリゴンがポリポリしています(シェーディングの関係でポリゴンが目立つ、陰でポリゴンが際立つ感じ…)。 少々コストはかかりますが、DisplacementMapから動的にNormalMapを生成してやって、それを使ってShadingを行うと良くなりそうに思います。
最後に
コード等公開しようと思いましたが、これ以上更新しようと思うほど楽しくなかったので今回はここまででお蔵入りします。
シンプルなメッシュに対して、ざっくりとした変形は実際に頂点を変形させ、ディティールな変形には今回のような手法を用いるような、ハイブリッドな実装ができれば結構面白そうかなと思いました。