shading blood

SPH (流体シム) を deferred shading でレンダリングしているゲームというのは商用ゲームを見渡してもまだほとんど例がないため、独自性を出す余地がありそうです。なので、描画周りも色々模索中。ただしモデルは全部立方体の集合という縛りで。
面白そうなテーマだったので、血っぽい液体を再現してみました。その経過の記録。 ちなみに deferred shading については、西川善司氏の Killzone2 記事に詳しいです。


まず法線を強引に球面化 ( normalize(ピクセル位置 - インスタンス位置) ) します。
atomic_20120102


SPH で濃度というパラメータが求まり、これが文字通り密度の高い領域ほど高い数値になっているため、位置データと一緒に CUDA 側から OpenGL 側に転送。高濃度の領域は暗い赤に、低濃度の領域は鮮やかな赤になるように調整 (wikipedia:血液に丁度いい例があったのでそれと睨めっこしつつ)。ハイライトはごく普通に Phong shading。 これだけで割とそれっぽい見た目になってくれました。


ここまで来ると当然剛体が血に濡れて赤く染まるのも再現してみたくなります。
deferred shading のポイントライトは、位置や法線などの GBuffer を参照しつつ影響範囲内のピクセルを参照してライティングしていくわけですが、同じ考え方で、流体が当たった位置に球のモデルを置いて、影響範囲内のカラーバッファを赤で上書きすればそれっぽい効果が出せそうです。
やってみた図。
atomic_20120108
(カラーバッファの a 要素は shininess にしていて、これも上書きしているので、濡れた箇所のハイライトが鋭くなっています)



当たった箇所全部に球を置いたら重くて死ぬので、実際は適当に間引いています。(上の動画だと 128 衝突に 1 個置くという処理)
球置きっぱなしにしていても重くて死ぬので、時間経過で球を縮小させて消すようにしています。


アップで見ると球置いてるのがバレバレで美しくないですが、初見の人に「おっ」と思わせられる効果は得られるんじゃないかと思います。
本格的にやる場合、剛体毎に血痕用テクスチャを用意して、血痕の球はそちらに描画、とかになりそうですが、めんどくさそうなので今回はここまで。



*追記 2012/01/10
最初の法線を強引に球面化するところで、位置バッファの z も書き換えて、length(pos.xy)>radius な領域を discard することで完璧な球に見せかけることができるのに気づきました。
atomic_20120110
demoscene でよく使われる技法の応用。