#はじめに
UTVirtualアドカレの21日目です。コイツいくつクソ記事投げれば気が済むんだ?と思ったそこの人間!喜べ!今回もクソ記事だぞ(n日ぶり3回目)!
早く記事を書かねぇとアドカレの空いた部分全部一人で埋めてやるからな
Virtual要素も無し!2018から追加されたノードベースシェーダーシステム、ShaderGraphの話をします!
#Shader Graph について
Unity2018から実装されたノードベースでシェーダーを書けるシステムです。2018.1から部分的に提供され始めたScriptableRenderPipeline(レンダリングの手法を変える、または複数から選択できる仕組み)の一つとして含まれるLightWeightRenderPipeline(ライトの数が制限される代わりにレンダリングの処理コストが下がる、スマートフォンとか向け)の機能の一つとして実装されました。詳しくは凹先生の記事を読みましょう
Unity 2018.1 より提供される Scriptable Render Pipeline について調べてみた
従来のレンダリングシステムからLWRPに差し替えるのは結構面倒臭いらしいのでおとなしく新しいプロジェクトでLWRPを選択して始めた方が良さそうです。
こんな感じにノードを繋いで行くことで簡単に色々なシェーダーを作ることが出来ます。 ShaderGraphの導入部分については今回は取りあつかいません。ここら辺を見ればいいと思います。 [【Unityシェーダ】Shader Graph超入門](http://nn-hokuson.hatenablog.com/entry/2018/05/08/212502) [SHADER GRAPHで波を作ろう。](https://negipoyoc.com/blog/shadergraphtest/) #今回作るもの 今回は、音ゲのBGAなんかでよく見る円弧の円周角をイージングかけて操作するグイーンってやつを作ってみようと思います。 こういうやつ。なんとテクスチャ無しで作れます。 すごい。shader graphのいいところ
— 避雷 (@lucknknock) 2018年12月23日
・見た目が楽しい pic.twitter.com/g7HF3LTfLp
今回は円の方だけ取り扱います。 白いのが角からギュイーンってやつはまた今度別の記事で。 Githubはこちら。ShaderGraph関連の成果物をブチ込んで置きます。Circleが今回の物。 https://github.com/Hirai0827/ShaderGraph #実際に作る ##全体の俯瞰 全体のノードとしてはこんな感じになっています。shader graph 完全に理解した pic.twitter.com/Bpycjfj2CW
— 避雷 (@lucknknock) 2018年12月23日
- ドーナツ型のテクスチャを出力
- 原点を中心にグルグルアニメーションするテクスチャを出力
- 上記二つをMultiplyしてマスクする
- それに色を付けて出力
ノードベースの物全般に言えますが基本的に左から右に出力が流れていきます。今回はオレンジ枠の右側にあるものが最終出力部分です。
小さくて見えないと思うので詳しいことはGitに上げたプロジェクトを見てください。
##部分ごとの解説。
###ドーナツ状の円を作る。(青色部分)
この部分で円を二つ組み合わせて中空の円を生成しています。radiusの大きい方の円はそのまま、radiusの小さい方はからの引き算を組み合わせて0と1を反転させています。 さらにそれら二つの円を乗算することによってドーナツ状の円を生成することが出来ます。 今回は外円と内円の半径をそれぞれパラメータ化することでmaterial部分から操作することが出来るようにしました。
アニメーションなどはこの部分にマスクするように作っていきます(今回はマスクを乗算で表現しています。Multiplyのどちらかでも0だったらその座標の描画はされません。)
###アニメーションの下地を作る。(緑部分)
今回は円弧の角度θが重要な役割を果たします。 なのでxy座標系から極座標系に変換した方が楽な実装が出来ます。この部分のノード群で極座標変換をするuv(Polar Coordination)を設定した上でstep関数をかけ、一定のθ未満の部分の円を描画しないようにしています。 コレで繋いだノードの数値を閾値に円を描画するかしないかの設定を行うことができます。今回極座標系の偏角部分はRGBのG成分で判定します。カラーのくせに範囲が-0.5~0.5なのに注意しましょう。カラーなのに。
###イージングを作る(緑部分)
ここでは関数を組み合わせてイージング(加速度のある動き)を実装していこうと思います。基本的にsinもmoduloも正の範囲で扱う方が使いやすいので、適応の直前までこの範囲で設計して最後の部分でremapを繋いで-0.5~0.5の範囲に修正します。Modulo(入力値を指定の数で割った余りを出力)は周期を定めるために使っています。今回は3秒で一区切りなハズ。正直この部分はお好みの数式を使ってくれという感じですが、オススメは1-(x^2n)とかシグモイドっぽい挙動あたりを探って見るとエモいイージングが見つかりそうな気がします。今回はtimeの3乗を使っています。最初は遅く、最後の方に向かって加速する感じですね。
###アニメーションに組み込む
先ほどのイージングと同じものをもう1組生成します。先ほど作ったものが円の始まりの辺、今作ったものが円の終わりの辺です。 イージング部に接続するtime由来の数値とのコネクトを一旦接続し、ディレイ分減算することで一瞬イージングの開始を一旦遅らせています。
↑ディレイを含めた時間変化する変数を作っている
↑円弧の始端と終端の共同に分けて記述している。上が始端、下が終端
###色を付ける(オレンジ部分)
Colorで指定した色をBlend(Multiply)で合成しています。
###出力結果
これらを繋ぐことで最終的に「中空の円」が「偏角がある範囲に納まる部分のみ描画」され「描画対象になる偏角の範囲がアニメーション」し「指定の色で塗り潰されて」出力されます。まぁまぁですかね、アニメーションの数式部分を弄ればもっとマシになりそう。
#使い方
GitHubに置いてあるのはシェーダーとマテリアルです。 Planeに貼り付けて各パラメータを適当に弄ってみるといいと思います。
- time_delay…始端の発生時間と終端の発生時間の差コレで表示される円弧の長さが決まる
- radius_outer…円の外側の半径
- radius_inner…円の内側の半径 radius_outerとこれでドーナツの太さが決まる
- delay_on_start…開始自体のディレイです。この時間だけ遅れて始まります。
- Color…色を指定します。この色で塗りつぶされます。
- period…周期を表します。この時間ごとに円がぐるっとなって消えるアニメーションが起こります。
これをMaterialに設定したPlaneを複数個並べると冒頭の動画見たくなります。やってみてネ。
#最後に
ShaderGraphはそのノード時点の描画結果をリアルタイムで表示してくれるのでビジュアル面を簡単にリッチにできる反面、数式部分は演算子一つごとにノードを繋がなきゃ行けないのでこの部分は直書きしたい気持ちも強い感じです。
ただ複数テクスチャを簡単に同時に使えたりアニメーションをリアルタイムで確認できるのは圧倒的につよあじです。Shader周りの民主化も着々と進んでいる気がします。民主化被害者の会が増えるのじゃ