前回 Shader Graph でディゾルブシェーダーを作りましたが、Shader Graph だと ComputBuffer に対応してなくて、
これだとやりたいことできへんやんということで結局コードを書くことにしました。
でせっかくなので紙が燃えるときのようなエッジのエフェクトを追加します。
シェーダーファイルの作成
プロジェクトウインドウで Create > Shader から適当にシェーダーを作ります。Unlit か Surface Shader ならいけると思います(試してない)。
自分は Universal Rendering Pipeline の Lit.hlsl をコピーして使いました。
プロパティの設定
Properties 欄にディゾルブ関係のプロパティを設定します。
Properties { .... // Dissove Properties _DissoveTexture("Dissolve Texture", 2D) = "white" {} _EdgeColor("Edge Color", Color) = (1, 1, 1, 1) _EdgeTexture("Edge Texture", 2D) = "white" {} _DissolveThreshold("Dissove Threshold", Float) = 0.0 _EdgeArea("Edge Area", Float) = 0.0 }
- _DissoveTexture
どのように溶けていくかを指定する白黒のテクスチャです。黒い部分から消えていきます - _EdgeColor
エッジ部分に合わせる色。なくてもいいです - _EdgeTexture
エッジ部分に表示するテクスチャ - _DissolveThreshold
スクリプトから設定して溶け具合を指定します
マテリアルからこの値を設定すると、0 > 1 に向かって徐々に消えていきます - _EdgeArea
端からどのくらいをエッジ部分とするかの値です
フラグメントシェーダー内でプロパティを参照できるようにする
HLSLPROGRAM の中で変数を定義します。プロパティと同名にすることで参照できるようになります。
sampler2D _DissoveTexture; half4 _EdgeColor; sampler2D _EdgeTexture; half _DissolveThreshold; half _EdgeArea;
ディゾルブ効果の関数を作成する
Dissolve.hlsl という名前でファイルを作成し、以下のコードを作成。
ピクセルごとに
- 通常の表面
- エッジ部分
- 透明部分(クリップ)
のどれを描画するかを計算しています。
half4 DissolveFragment( half4 color, half2 uv, half dissolveThreshold, sampler2D _DissoveTexture, half4 _EdgeColor, sampler2D _EdgeTexture, half _EdgeArea ) { half albedoThreshold = clamp(dissolveThreshold + _EdgeArea, 0, 1); half4 dissoveTexture = tex2D(_DissoveTexture, uv); half albedoMask = ceil(clamp(dissoveTexture - albedoThreshold, 0, 1)); half4 albedoColor = albedoMask * color; // Dissolve Edge half edgeThreshold = clamp(dissolveThreshold, 0, 1); half edgemask = ceil(clamp(dissoveTexture - edgeThreshold, 0, 1)); half4 edgeColor = edgemask * abs(ceil(albedoMask) - 1) * tex2D(_EdgeTexture, uv) * _EdgeColor; color = albedoColor + edgeColor; clip(color.a - 0.001); return color; }
clip 関数実行時に 0.001 を引いているのは、0だとクリップしてくれないのでゲタをはかせているかんじです。
フラグメントシェーダー内で関数を呼ぶ
// 関数を使えるように include #include "Dissolve.hlsl" ... // フラグメントシェーダーの最後あたり color.rgb = MixFog(color.rgb, inputData.fogCoord); color.a = OutputAlpha(color.a); // ディゾルブ実行 color = DissolveFragment( color, input.uv, _DissolveThreshold, _DissoveTexture, _EdgeColor, _EdgeTexture, _EdgeArea ); return color; }
マテリアルの設定
マテリアルは以下のようなかんじ
冒頭の動画で、出現させるときに球の表面に一部エッジが残っている部分がありますが、ディゾルブのテクスチャに漆黒(RGBが全部0)があるところが残っているのかなあと思うのでこれはテクスチャのほうでゲタはかせるのが一番簡単かも。
次はEmit効果を追加しようかな。