AmplifyShaderEditorで複雑なシェーダーを作る
単に使いやすいだけでなく正直わかりにくい仕様が多すぎるサーフェスシェーダーのラッパーとしても優秀で、更に裏でコードが生成されるため最悪あとでコードベースに移行すれば良いことや、標準のShaderGraphがVR対応していないこともあり、私は良く使っています。
入門記事も見つかりやすく簡単なことは習得しやすい一方で、ある程度複雑なことをやろうとするとどうやったらできるのか情報を見つけにくいことも多く、時間がかかったり、やむなくコードベースに移行することもあります。もちろん、そもそもできないこともそれなりにあるのでコードベースへの移行が避けられないこともあります。
VRC演出ワールド制作においてはディゾルブ機能等の演出向け機能を追加した汎用シェーダーを自作する機会も多いため、ASEの早く作れるという利点は非常に大きいです。
また、VRCLVのサンプルシェーダーもASEで提供されているため、その仕組みの理解にも役立ちます。
もちろんコードで書ける人が無理に学習する必要はないのですが、どこからシェーダーに入門するか迷っている人や、コードでやってみて肌に合わなかった人には特にオススメできます。また自身がコードで書ける場合も、ASEなら書けるという人と制作物そのものを挟んでコミュニケーションができるメリットがあり、チーム制作においては有効な場面があります。
有料ですがよくセールで半額になっているので、高いと思う方はAsset Storeの大規模セールの際に見てみるとよいと思います。
少なくとも毎年12月はセールしてる気がします。
思い出すたびに追記していきます。
何かTipsをお持ちの方はご連絡頂けると非常に助かります。
公式のwiki
まずはここの情報を確認するのが良いです。
ノードのワンクリック作成
割り当てられたショートカットキー+左クリックでノードを作成できます。
検索する手間が省けるので良く使うキーは覚えておくといいです。無理に覚えるほどではないです。
12345は各種変数(Float, Vector2, Vector3, Vector4, Color)
ASMDは四則演算(Add、Subtract、Multiply、Divide)
TがTextureSample、UがTextureCoordinates(UV)
ZがSwizzle、VがAppend
「.」がdot(内積)
グループを分ける、変数を登録する、呼び出す
複雑なシェーダーを書くのにまず覚えておくべき機能です。
https://scrapbox.io/files/695875a6e9aee9fdbeec9be9.png
Cキーでコメント付きの枠を追加でき、その内側に配置したノードは枠の移動に追従するようになります。
計算ごとにひとまとめにし、最後にRegister Local Varに繋ぐようにすると見やすくなります。 VRC LightVolumeのサンプルとかも綺麗なので整理の仕方の参考になります(分岐は複雑ですが…)
Register Local Var、Get Local Varで変数の登録と呼び出しができます。
それぞれR+左クリック、G+左クリックで作成できます。
CullMode(裏面、両面描画)を変更できるようにする
https://scrapbox.io/files/6958686603dd6200c8203a23.png https://scrapbox.io/files/69586a67c85fc3cd8c8ad96e.png https://scrapbox.io/files/695868de57e5bc9484983de2.png
Floatを追加
Type=PropertyにしてAutoRegistorをオン
ノードを接続しなくてもマテリアルプロパティに出るようになります。
AttributesからEnumをオン
UseEngineEnumClass
UnityEngine.Rendering.CullMode
Unityで定義済みのEnumからCullModeを呼び出せるようになります。
OutputNodeのCullModeの右端の丸をクリックしてーに変更
これがわかりにくい
Floatを参照できるようになるので、定義したFloatを選択して保存するとマテリアルプロパティに表示されるようになります。
vert-fragシェーダーを作成する
SurfaceShaderしか作れないのかな?と誤解されがちですが、普通にvertex-fragmentのシェーダーも作れます。
全部Emissionに繋いでいる、みたいな状態であれば、描画負荷・コンパイル速度ともこちらの方が良いです。
OutputNodeの入力をはじめ、諸々の余計な設定も表示されなくなるので迷わなくなります。
使ったことはないですがImageEffectやCRT用シェーダーなど、その他のタイプも用意されています。
やり方は2通りあります。
ShaderTypeからBuilt-In>Unlitを選ぶ
https://scrapbox.io/files/69586dbf9baf63e54538630e.png
シェーダーの新規作成時にBuilt-In>Unlitを選ぶ
https://scrapbox.io/files/69586ebbb9f196edfc131df7.png
CustomExpressionでcgincを読む
CustomExpressionは部分的にコードで記述したい場合に便利で、特にAddやMultiply、Dotをたくさん繋がなければならないようなライティング関連の複雑な計算はコードベースでひとまとめにしたほうが色々と好都合な場面が多いです。
もちろんASEのほうがわかりやすい人はFunctionノードを作成しても良いと思います。
Mode:Createだとコードの記述欄が狭く、見にくいです。Mode:Fileにするとcgincファイルを参照でき、その方が書きやすいと思います。
https://scrapbox.io/files/695884af346a4cd4061b9e30.png
Mode:Fileにし、Sourceに参照するcgincをD&Dします。
Nameを使いたい関数と一致させます。
Input、Outputをその関数と一致するよう設定します。
アウトラインを追加する
OutlineというSurfaceShaderでのみ使えるノードがあり、VertexOffsetまたはVertexPositionに繋ぐとアウトライン用のパスが追加されるという不思議な挙動をします。 コードを見るとSurfaceShaderに元々ある機能を呼び出しているようですが、Unity公式マニュアル側に機能の説明が見当たらないのが謎です。
https://scrapbox.io/files/69586fc1c45f00b4dae85bf6.png
通常のVertexOffsetと組み合わせたい場合はなんとAddで合流させます。
アウトラインの位置の計算も必要になるので、以下のようにすることになります。
https://scrapbox.io/files/695870a5b4c00a4c4984422b.png
Input(v2f)に任意の情報を追加する
構造体に任意名のフィールドを追加できるわけではなさそうですが、一応vertからsurf(frag)に渡すフィールドを増やすことができるノードがあります。
FinalColorを変更する
SurfaceShaderにはFinalColorという機能があり、Albedo、Emissionを出力するだけでなく、ライティング等の諸々の計算が終わった最終の色をさらに補正する機能があります。
Unityのマニュアルにも記述があり、例の通りカスタムフォグ的な機能を実装するのに使うことが多いです。
水中でだけフォグがかかるとか、距離だけでなく高さによっても濃さが変化するとか
ASEでも使いたくなりますが、そのためのInputやOutputは用意されていないようです。
しかし、頑張ると使えるので説明します。
コード側のどこに対応するかは割愛しますが、コード側でどうなっているか見るとより良いと思います。
OutputノードのAdditional Surface Optionsに「finalcolor:FinalColorFunc」と追記します。FinalColorFuncの部分はあとで作る関数名なので何でも良いです。
https://scrapbox.io/files/6958798374a63eab48c1d748.png
CustomExpressionノードを追加し、以下のように設定します。
先ほどの関数名をNameに設定
Set-Uniqueを外しAuto-Registerをオン
ノードをどこにも繋がなくても関数が登録されるように
OutputTypeはvoid
Inputsを画像の通りに
oのTypeは通常のStandardSurfaceであれば画像の通り、CustomLightingを使ったりしている場合は型がTypeが変わってくるのでコードを見に行ってsurfのinoutと同じ型にします。
INはvertの出力、oはsurfの出力なので、Code内でその内容を参照してFinalColorに反映することもできます。
FinalColorをそのまま加工するだけでなく、AlbedoやEmission、Normalの値に応じた変化を加えることもできるということです。
Code内でFinalColorを好きに加工します。
https://scrapbox.io/files/69587ad8c86a23ade1b1ea8f.png
実はこのFinalColorを使うとBuilt-in Fogが消えるという問題がSurfaceShader自体にあります。
FogもFinalColorに干渉する機能なので、まあ納得感はありますがBuilt-In Fogと併用できないと困ることも多いです。
という話がUnityのフォーラムでもされており、FinalColorの処理内に自分でBuilt-In Fogのマクロを追記する形で解消できる、と説明されています。
これをASE上で取り込む方法を、私は見つけられていません。
前述のInputに任意の情報を追加するノードでも、Input構造体に任意名のフィールド(ここではfogCoord)を追加する方法がなさそうです。
出来たとして、vert内でoを参照するマクロを記述する方法がなさそうです。
やむなくコードベースに切り替えて対処していますが、ASE上で対応する方法を知っていたらぜひ教えてください。
複雑なので次触ったときに追記予定
ParticleSystem周り
これに関しては基本的にコードベースで触ったほうが良いと思っています。
CustomLighting周り