ShaderGraphで遊んでみた 〜キャラクターの設定に説得力を与える方法〜

## はじめに
こんにちは:relaxed:
[CYBIRD Advent Calendar 2023](https://qiita.com/advent-calendar/2023/cybird) 24日目担当の@shiso_cです。
23日目は@cy_ryosuke_zushiさんの「[Unity(URP)：いい感じのポストエフェクト紹介](https://qiita.com/cy_ryosuke_zushi/items/0356bf621f4cf5215f21)」でした。
手軽にエフェクトをかけられて良いですね！
ポストエフェクトの自作には、これから紹介するShaderGraphを使う方法もあるので、ぜひ合わせてご覧ください。


## 概要
[去年の記事](https://qiita.com/shiso_c/items/26f88483e0907e0660a4)をご覧になった方はご存知かもしれませんが…
私は[Unity1週間ゲームジャム(通称：Unity1Week、以下u1w)](https://unityroom.com/unity1weeks)に頻繁に参加しておりまして、2023年も引き続き連続参加記録更新中です！

私は毎度のようにオリジナルのキャラクターを生み出すのですが、その設定を伝えるのがなかなかに難しい:disappointed_relieved:

u1wでは特に、一度の開催で数百のゲームが投稿されるので、ひとつのゲームを遊ぶ時間ってとても短いんです……
つまり**短時間**で**わかりやすく**設定を伝える必要があります。

この記事は、そんな悩みを**ShaderGraph**を使って解決してみたお話です。

タイトルの通り **『遊んでみた』** レベルの話なので、ごちゃごちゃとこねくり回した結果こうなったよ〜程度に見ていただけると幸いです！

題材のゲームはこちら🐶

https://unityroom.com/games/amagumo_wanko

:::note info
ちなみに現在Unity1Week開催中です！
本日20時から評価期間ですが、遅刻投稿OK、遊ぶだけの参加もOKなので、興味を持った方はぜひ参加してみてはいかがでしょうか？
:::

## ShaderGraphとは？
簡単に言うと、ShaderGraphは**プログラミング無しでシェーダーを作成できるUnity公式のツール**です。

公式マニュアル↓
https://docs.unity3d.com/ja/Packages/com.unity.shadergraph@10.0/manual/First-Shader-Graph.html

ノードベースで線を繋ぐだけでシェーダーを作ることができるので、エンジニアに限らず、デザイナーやプランナーの方でも編集できます。

また、主観ですが、途中経過を目で見ながら作成できるので、遊び感覚で何となくいじってみると結構楽しいです:laughing:

シェーダーの学び始めの取っ掛かりとしても良いと思います！
（コードベースの方の知識もあるに越したことはないですが……）

※ShaderGraphの導入方法については、検索するとたくさん出てくると思うので、この記事では割愛します。

## あまぐもわんこ
ここからが本題です。

今回登場するのが**あまぐもわんこ**というキャラクター:cloud_rain:
絵本に登場する架空の生き物的な存在です。
![furu_book.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2294759/d4a98cce-b903-894d-5561-80d0204a6260.png)
この子の最大の特徴は**水を吸い込んで雨を降らせることができる**ということ。

言葉で言われても **何じゃそら？** となる設定ですね

では、実際にシェーダーを適用するとどうなるのか……
こうなります！
![mizu.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2294759/70fb3a2c-6c6b-a2da-d548-ac3b8b6df1fc.gif)
この画像なら、わんちゃんが水を吸い込んでいる様子が一目で分かりますね:eyes:

この含水量の部分の表現をShaderGraphで作っています。
全体像はこんな感じ↓
![スクリーンショット 2023-07-04 18.24.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2294759/13d887a7-8ff2-97c5-f1c0-7bbf7808040c.png)

### 作成手順
では実際に作ってみましょう！

このシェーダーは大まかに分けて3つの要素で構成しています。
![スクリーンショット 2023-07-04 18.24.13_123.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2294759/4af09352-6856-d081-2acb-b2c084b11b27.png)

#### ①水の描画範囲を決める部分
**UVからGだけ出力する**と**Y軸方向のグラデーション**ができるので、それを**Stepで二値**にして出力します。
このStepに渡す閾値(wetty)をプロパティとして外に出しておくと、スクリプトから値を代入できるので、ゲーム中に値を変化させて見た目を変えるという使い方ができます。

今回は大元のテクスチャ(MainTex)が均等に画像を並べたものなので、Moduloを使って、画像の高さ毎の繰り返しになるように調整しています。
![スクリーンショット 2023-07-04 18.17.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2294759/2df0921c-1303-e839-7198-8c3484b0adcf.png)


#### ②水の表現
以下のサイトを参考にして水面の動きを作りました。
https://zenn.dev/kidsstar/articles/eb7e2769038639

水面は**Voronoi**を使うと簡単に作ることができます。
![スクリーンショット 2023-12-14 18.47.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2294759/373733dc-dd80-d60c-4dbe-d12b7577630b.png)
Timeでスクロールの方向と揺らぎを与えると、グッと本物っぽくなりますよ:ocean:


個人的なこだわりポイントは、最後に色を合成する部分を**Add**にしてみたところです。
水の透明感が出せていたらいいなと思います。

元画像にどんな画像を用意するかで合成方法の適性は変わると思うので、お好みで色々と試してみると面白いです。
（ちなみに犬の元画像が白いので、元画像に直接Addすると白飛びする…）

#### ③元画像との合成
**Lerp**を使って、①の出力に合わせて、元画像そのままのものと、元画像と②の出力を乗算したものを出し分けています。

以下のサイトによると、StepとLerpを組み合わせること2色の塗り分けが可能になるとのことでした。

https://nn-hokuson.hatenablog.com/entry/2018/05/24/195206
> lerpはlerp(a,b,v)という形で使用します。vは0.0〜1.0で指定して、その割合によってaとbがブレンドされます。

今回はvにStepの出力を繋いでいるので0か1の入力になりパキッと塗り分けていますが、使い方によってはグラデーションとかできそうですね。

一番最後の出力は**FragmentのAlpha**に**MainTextureのA**を入れてあげると、元画像の形にクリッピングされます:scissors:


![mizu.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2294759/edd8ca2b-0faf-dcf4-e610-c48e63e0f0fa.gif)
"水を吸い込んで雨を降らせる犬"**あまぐもわんこ**の完成です！

## おまけ🎄ツリーがないなら作ればいいじゃない！
突然ですが今日は何の日でしょうか？

そうです！**クリスマスイブ**です🎄

せっかくなので（？）もう少しだけShaderGraphで遊んでみましょう！
今度はわんちゃんを**クリスマスツリー**にしたいと思います！

緑色の塊に光の粒がピカピカしていたらそれっぽくなるはず…！
ということでシェーダーの全体像はこちら！
![スクリーンショット 2023-12-18 18.09.29のコピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2294759/00001f8e-0899-458a-49cc-2991fe0c055f.png)

せっかくなので、あまぐもわんこ用シェーダーでも使用した
- Voronoi
- Time

をここでも使ってみました！

### 作成手順
#### ①光の粒
そもそもVoronoiは**複数の母点が任意に置かれる**ので、ランダムに点を置きたいときにちょうど良いです。
※ちなみにAngleOffsetに0を入れると母点が均等に並ぶので、綺麗なドット模様もできます。

> ボロノイ図（ボロノイず、英: Voronoi diagram）は、ある距離空間上の任意の位置に配置された複数個の母点（英: site、サイト）に対して、同一距離空間上の他の点がどの母点に近いかによって領域分けされた図のことである。
ー引用ー
「[ボロノイ図](https://ja.wikipedia.org/wiki/%E3%83%9C%E3%83%AD%E3%83%8E%E3%82%A4%E5%9B%B3)」『フリー百科事典　ウィキペディア日本語版』より。
最終更新 2023年7月10日 (月) 12:00　UTC

今回は母点の部分だけ取り出したいので、**Subtractで出力の調整をしたUV**をもとにTextureを貼り付けます。
~~画像用意するのも面倒くさかったので、~~ 今回は**Particle用のデフォルト画像**を使いました。
![スクリーンショット 2023-12-19 14.37.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2294759/f49c539f-2594-67de-83c9-9e1ff561236d.png)

このままだと母点同士が離れている部分にも色が出てしまうので、**Step関数を使って作ったマスク**で調整しています。

#### ②光の点滅
Timeを使って**点滅**と**色の変更**をしています。
直接SineTimeを使ってもいいですが、速度の変更ができるようにMultiplyを挟んでからSineに変換しています。

最後に、わんこの体を緑色にして、①②で作ったイルミネーションを重ねます。
（単純な合成はMultiplyかAddしておけば何とかなる:thumbsup:）

![kira2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2294759/ca3ac2d8-dc69-c2cf-7ee0-1807b474743d.gif)

クリスマスツリーならぬ、**光振り撒くトピアリーわんこ**の完成です✨

　/／
🐶　**Merry Christmas！！**
　\＼

## おわりに
ShaderGraphで遊んでみた、いかがでしたでしょうか？

元画像が同じでも、あまぐもわんこは**雲**、トピアリーわんこは**木**に見えますよね？？
見えていて欲しい……見えていてくれ……

シェーダーをうまく使うことで、表現の幅が広がるんじゃないかなーと思います。
ShaderGraphを使うと感覚的にシェーダーを作成できるので、ぜひ色々と試して遊んでみてください！

明日の[CYBIRD Advent Calendar 2023](https://qiita.com/advent-calendar/2023/cybird) 最終日は、@ma_da_iさんの「[5chのトレンドを可視化する](https://qiita.com/ma_da_i/items/4a837f85ffde04384705)」です！

いよいよ最終日ですね！最後までお楽しみに👋