はじめに
今回はShaderGraph
のCustomFunctionNode
を使ってみようという記事になります。
CustomFunctionNode
は一言で言えば、自分で動作を記述することができるノードということでしょうか。
細かい説明はそれぞれの箇所でしますが、今回目的となるガウシアンフィルタを適用したみた画像は以下になります。
画像の引用 : https://github.com/yoyoyo-yo/Gasyori100knock
そもそもガウシアンフィルタってなんやねんみたいになる方もいるかもしれませんが、以前Compute Shader
を使ってガウシアンフィルタを実装する記事を書いた際に詳しく書いたので、そちらを参照してみてください。
www.hanachiru-blog.com
CustomFunctionNode
Custom Function Node
とは名前の通り、ノードの挙動をHLSL
という言語を用いて記述することができるノードです。
docs.unity3d.com
Custom Function Node
へのコードの書き込み方としては、string
モードを使用して小さな関数を直接グラフ内に記述する方法と、外部のHLSLのインクルードファイルを参照する方法の2つがあります。
前者はお手軽にShaderGraph内にコードを書くのに対して、後者はShaderGraph外にあるファイルを読み込んできます。
stringモード
まずはstring
モードで作ってみましょう。
string
モードでもfile
モードでも明示的に入出力の変数を定義しておかなければなりません。
種類 | 変数名 | 型 |
---|---|---|
tex | 入力 | Texture2D |
uv | 入力 | Vector2 |
sam | 入力 | Sampler State |
color | 出力 | Vector4 |
今回は以上のものを定義してみました。Sampler State
は見慣れないかもしれませんが,テクスチャの細かい仕様(フィルタリングモードとラップモードの設定)を決めるもので、テクスチャの特定のピクセルの色を取ってくるときなんかに必要になるので入力に入れておきます。
Sampler State ノード | Shader Graph | 10.0.0-preview.27
入出力・関数名を記入したらコードを書いていきます。
color = float4(0, 0, 0, 1); color += (1.0 / 16.0) * SAMPLE_TEXTURE2D(tex, sam, uv + int2(-1, -1)); color += (2.0 / 16.0) * SAMPLE_TEXTURE2D(tex, sam, uv + int2(-1, 0)); color += (1.0 / 16.0) * SAMPLE_TEXTURE2D(tex, sam, uv + int2(-1, 1)); color += (2.0 / 16.0) * SAMPLE_TEXTURE2D(tex, sam, uv + int2(0, -1)); color += (4.0 / 16.0) * SAMPLE_TEXTURE2D(tex, sam, uv + int2(0, 0)); color += (2.0 / 16.0) * SAMPLE_TEXTURE2D(tex, sam, uv + int2(0, 1)); color += (1.0 / 16.0) * SAMPLE_TEXTURE2D(tex, sam, uv + int2(1, -1)); color += (2.0 / 16.0) * SAMPLE_TEXTURE2D(tex, sam, uv + int2(1, 0)); color += (1.0 / 16.0) * SAMPLE_TEXTURE2D(tex, sam, uv + int2(1, 1));
SAMPLE_TEXTURE2D
はUnity側であらかじめ定義されている関数で,Texture
の特定の位置にあるピクセルの色を取得できます。
#define SAMPLE_TEXTURE2D(textureName, samplerName, coord2)
HLSLに慣れている方はtex2D()
を使いたくなりますが、どうやらエラーが出てしまうようなので注意してください。
あとfloat4
であったりint2
とかになっているのを初めて見るかたは驚くかもしれませんが、HLSL
はC#
とは型の書き方が違うからですね。
fileモード
fileモード
の場合は拡張子が.hlsl
となるおようにファイルを作成(.cginc
でもいけるっぽい?)して、参照します。
#ifndef SAMPLE_OUTLINE_INCLUDED #define SAMPLE_OUTLINE_INCLUDED void GaussianFilter_float(Texture2D tex, float2 uv, SamplerState sam, out float4 color) { color = float4(0, 0, 0, 1); color += (1.0 / 16.0) * SAMPLE_TEXTURE2D(tex, sam, uv + int2(-1, -1)); color += (2.0 / 16.0) * SAMPLE_TEXTURE2D(tex, sam, uv + int2(-1, 0)); color += (1.0 / 16.0) * SAMPLE_TEXTURE2D(tex, sam, uv + int2(-1, 1)); color += (2.0 / 16.0) * SAMPLE_TEXTURE2D(tex, sam, uv + int2(0, -1)); color += (4.0 / 16.0) * SAMPLE_TEXTURE2D(tex, sam, uv + int2(0, 0)); color += (2.0 / 16.0) * SAMPLE_TEXTURE2D(tex, sam, uv + int2(0, 1)); color += (1.0 / 16.0) * SAMPLE_TEXTURE2D(tex, sam, uv + int2(1, -1)); color += (2.0 / 16.0) * SAMPLE_TEXTURE2D(tex, sam, uv + int2(1, 0)); color += (1.0 / 16.0) * SAMPLE_TEXTURE2D(tex, sam, uv + int2(1, 1)); } #endif
結構御作法が厳しくやりずらいところもありますが、uniform変数
を定義できたりとメリットもあるようです。
Custom Function ノード | Shader Graph | 10.0.0-preview.27
細かい箇所は公式ドキュメントをご覧ください。
最終形
作成したCustom Function Node
を活用して冒頭の貼ったような描画を行えるようにノードを組み合わせます。
さいごに
どんな組み込み関数が定義されているとか、Unity側でどんな関数が定義されているとかがわかりやすくまとまった記事がなかなかないようで大変でした。
マイクロソフトのHLSLのドキュメントは非常に読みづらいし、CustomFunctionNodeでは動作しないような関数等(例えばtex2D
とか)も含まれていてうーんといった感じです。
組み込み関数 - Win32 apps | Microsoft Docs
もっと色々な情報が出回ればShaderGraph界隈も盛り上がるような気もしますが、参入の敷居がやや高めで手が出しづらいような気がします。
天上人の方がお慈悲でわかりやすい記事を書いてくださることを祈ってます。
ではまた。