【ShaderGraph】積雪表現をShaderGraphで作ってみる


本記事は、サムザップ Advent Calendar 2021 の12/22の記事です。
昨日の記事は @Buna_unity_game さんの「【ScriptableObject】シングルトンを使わずにマルチシーンのイベント管理してみる 」でした。

目次

はじめに
今回作ったもの
関連Tips
解説
最後に

はじめに

去年のアドベントカレンダーで使っていたバージョンから結構アップデートされていて、UniversalRenderPipeline(以下、Universal RP)とShaderGraphが変わっていそうなので、最新のShaderGraphを使用してみようかなと思います。
ちなみに、去年のアドベントカレンダーでの記事はこちら。

【ShaderGraph】Quadで擬似的な3D空間を表現したサンプルを紹介
平面の中に擬似的な3D空間をShaderGraph使って実現してみた...
【ShaderGraph】トゥーンっぽい炎の演出をShaderGraphで作ってみる
トゥーンっぽい炎の演出をShaderGraph使って表現してみよう...

使用環境

今回使用する環境はこんな感じです。

バージョン
Unity 2021.2.4f1
Universal RP 12.1.1
ShaderGraph 12.1.1

前回使用していたバージョンが7.3.1だったので結構変わっただろうな…と思いつつ、やっていきます。
Universal RP,ShaderGraphの設定周りの準備に関する内容は、本記事では省略します。

今回作ったもの

今の季節が冬って事もあり、ShaderGraph使って積雪表現を作ってみました。

関連Tips

ノードの説明とかは公式ドキュメント参照って事で、便利だなって思ったTipをメモ的な感じで書いておきます。

よく使ったショートカット

前回使ってたのにショートカットを忘れたので、作る前にメモ〆

ショートカットキー 内容 補足
A 全てのノードが表示されるようにズームイン/ズームアウトする Preview window、Blackboard、Internal Inspectorに被ってしまうのが使いづらいから、どうにか改善されて欲しいなーと思ったり。
F 選択中のノードが全て表示されるようにズームイン/ズームアウトする Aと同じく、使いづらい部分は多少ある。
Spacebar ノード作成 「Vertex」や「Fragment」などを選択中にSpacebar押下で、中にノード追加出来る。

※基本的なコピー&ペーストなどは長くなるので省略します。

Category / Group

グループ化したいノードを選択してGroup Selectionする事で、ノードをグループ化してまとめることが出来ます。
複雑なグラフになるほど、ノード一つ一つのプレビューをオンにしていると全体が見えなくて邪魔になります。
その為、基本的にノードのプレビューは閉じて作業しているので、このGroupを設定しておくと、何をしている処理なのかがひと目で分かります。
ただ、確認のために他グループと混線するノードはプレビューを閉じないようにしておくのが良さそうです。

Categoryを使用することで、Blackboardにも同じような事が出来ました。
(今回の分け方・使い方で良いのかは分からないですが…)

解説

全体像

積雪表現に直接関係するところ以外の説明は簡略化します。

Blackboard

まず、Blackboardから解説していきます。
Category分けをしていてBaseは基本的な構造です。

パラメーター 説明
SnowDirection 雪がレンダリングされる場所の指定
SnowColor 雪の色調整
SnowAmount 積雪量の調整
SnowBlendDistance ベーステクスチャと雪レイヤーのブレンド領域制御
SnowColorNoiseSize 積雪具合の調整
SnowColorNoiseStrength 積雪の厚み調整
BuildupNoiseSize 雪の塊具合の調整

Normal Texture

積雪表現に関わるノードと混線している訳でもないので、NormalTextureは特筆して説明する要素はなく、ただFragmentのNormalへ値を渡しているだけになります。

Dot Product Calculation

指定されたSnowDirectionとメッシュの法線ベクトルとの内積計算をします。
NormalizeでSnowDirectionを単位ベクトルにして内積計算をし、Saturateで0-1間にバインドして出力を飽和させます。

Snow Buildup(Noise Calculation)

雪の塊具合をSampleNoiseを使用して計算し、先ほど計算したDot Product Calculationの結果を乗算することで、積雪表現に必要なMap作成をします。
この時、先ほどと同じようにSaturateで0-1間にバインドして出力を飽和させておきます。

Snow Color

薄汚れた雪も表現できるようにColor調整出来るものだけでも良かったのですが、現実世界で真っ平に積雪する事は無いわけで…。
Snow ColorでもSampleNoiseを利用して、積雪の厚みを調整出来るようにしてみました。

積雪の厚みが伝わりづらいと思ったので、別画像用意しました。
SnowColorNoiseStrengthが右と左で変わっていて、これで凹凸感も表現出来るようにしています。

Sample Texture + Base (Albedo) Color

ベーステクスチャと雪レイヤーのブレンドをSnow Buildup(Noise Calculation)の結果の値を利用して線形補間した後、FragmentのBase Colorへ結果を渡しています。

Smoothness Map

Smoothnessも同様に、Snow Buildup(Noise Calculation)の結果の値を利用して線形補間した後、FragmentのSmoothnessへ結果を渡しています。

最後に

途中からTiling And OffsetとSampleTexture2Dの組み合わせが複数あったので、サブグラフ化も検討しましたが断念しました。。


branchかなんかで、TypeのDefaultとNormalの切り替えを同一のSubGraphで実現できると綺麗なのですが…。
良い方法知っている方いれば、是非教えて欲しいです!!

よく使うノードセット的なものは、SubGraphで使い回しが出来るような形でリソースを溜めておきたいなと思いました。

明日は @chrno001 さんです。