雨の日のカメラを作る
はじめに
カメラのレンズに雨が付着した感を出してみました。
ささっと作ったのですが、ちょっといい感じになったので自分で驚いてます。 雨粒が付着した部分は背景の映り込みが歪むようになっています。
Unity Standerd Assetに含まれるガラスシェーダーを使いまわしたので、10分くらいで実装することが出来ました。
実装方法
UnityTexturePaintを使います。
まずは以下の画像のように Assets -> Import Package -> Effectsを選択して、Glass Refractionをインポートします。 Glass Refractionでは、GrabPassで取得したテクスチャと法線マップを使い、写り込んだ背景を歪ませる処理が行われています。 このシェーダーをそのまま利用し、透明な状態で法線情報だけを更新していき、水滴が付着したように見せるという寸法です。
次に、カメラ正面にQuadを置き、Quadのマテリアルを先程インポートしたGlassRefractiveに変更し、テクスチャを真っ白なものに差し替えます。QuadのコンポーネントにDynamicCanvasとHeightFluidをアタッチしたら準備は完了です。
あとはTexturePaintを使って、Quadの適用な位置にHeight(液体の付着量)情報をペイントしてやります。
具体的には
using System.Collections; using System.Collections.Generic; using UnityEngine; using Es.TexturePaint; public class RainPainter : MonoBehaviour { [SerializeField] private DynamicCanvas canvas; [SerializeField] private PaintBrush brush; [SerializeField] private float minSize; [SerializeField] private float maxSize; [SerializeField, Range(0, 100)] private float aboutCallPercentOnFrame = 10; private void OnWillRenderObject() { if(Random.Range(0f, 100f) > aboutCallPercentOnFrame) return; for(int i=Random.Range(1, 10);i>0;--i){ brush.Scale = Random.Range(minSize, maxSize); canvas.PaintUVDirect(brush, new Vector2(Random.Range(0f, 1f), Random.Range(0f, 1f))); } } }
こんなスクリプトを書いてQuadに取り付けて、BrushTextureとBrushHeightTextureにこんな感じの画像を与えてやります(透過済みの画像です)。
サンプルの動画では設定はこんな感じに。
あとは実行すれば、適当な位置に水滴がついたような効果が断続的に出現します。
最後に
1粒1粒の水滴がつくたびに描画命令を発行するため、今回のままではパフォーマンス的によろしくありません。 改善する方法としては、水滴がたくさん付いているようなテクスチャを入力として、1回で複数の雨粒を書き込んでやる、などが挙げられます。