概要
今回はUnityのShader Graph内にあるCustom Functionノードで自作のhlslファイルを使う方法についてです。
環境
今回はUnity6を使用していますが、Unity2021や2022でも動作するかと思います。
- Unity 6000.3.7f1
- URP 17.3.0
- Shader Graph 17.3.0
出来上がるもの
左のカラーの画像を右のようにグレースケールにするCustom Functionを作ります。
わざわざCustom FunctionにしなくてもShader Graphのノードで作れるのですが、練習がてらやってみました。

作り方
0.準備
Unity6のURPでプロジェクトを作成するとShader Graphのパッケージがインストールされている状態で作られます。もし無い場合やインストールされているかを確認したい場合は、Package Managerを参照してください。
Shader GraphとCustom Function
Shader GraphはUnityが提供しているShaderを視覚的に構築できるツールのことです。
これを使用することで難しいShaderのプログラムを記述しなくても、Shaderを作ることが出来ます。
公式ドキュメント
Custom FunctionはShader Graphのノードの1種で、独自のHLSLコードを挿入することが出来るノードです。
このノードには「File」と「String」という2つの方法でコードを挿入することができ、今回はFileを使った方法のやり方です。
公式ドキュメント
1.hlslファイルの作成
調べた限りだとUnity内からhlslファイルを作成する方法は無さそうでした。
ですので、Assetsフォルダの階下をファイルエクスプローラーで開き、テキストドキュメントを作成します。
そして作成したファイルの拡張子を〇〇.hlslに変更します。
hlslファイルについてや画像付きの手順は、下記のサイトで詳しく説明されているのでそちらを参照してください。
2.グレースケールシェーダーの作成
先ほど作成したhlslファイルを開きます。この時使用するIDEはご自分の使いやすいエディターで大丈夫です。
テキストファイルとして作成したので、最初は何も無い状態のファイルだと思います。
そこに下記のプログラムを記述して保存してください。
float4 ConvertGreyScale(UnityTexture2D inputTex,float2 uv){
float4 texColor = SAMPLE_TEXTURE2D(inputTex.tex,inputTex.samplerstate, uv);
//グレースケールにするための係数
float3 GreyCoef = float3(0.299f, 0.587f, 0.114f);
float grey = dot(texColor.rgb, GreyCoef);
return float4(grey.xxx, texColor.a);
}
void GreyScale_float(UnityTexture2D tex, float2 uv, out float4 color)
{
color = ConvertGreyScale(tex, uv);
}
3.Shader Graphの作成
3-1.アセットの作成
Unityエディターに戻って、Assetsフォルダの下にShader Graphのアセットを作成します。
右クリックをすると出てくるメニューからLit Shader Graphを今回は選択します。

3-2.hlslファイルを適用する
そしてそのShader Graphをダブルクリックして開くと編集画面になります。
編集画面でスペースキーを押すとノードを選べるウィンドウが出るので、そこから Custom Function を選ぶと画像のように出てきます。

Custom FunctionのGraph Inspectorにて設定を行います。
- Inputs、Outputsの文字のあたりをクリックすると変数名が変えられます。hlslの引数名と違っても動きますが、分かりにくくなるため同じ変数名にした方が良さそうです
- TypeにはFileを選択し、Sourceの欄に作成したhlslファイルを設定します。
- Nameの欄にはエントリーポイントになる関数名を入れます。
- この関数名にはGreyScale_floatではなく、 GreyScale と入れてください。
3-3.ノードをつなぐ
Custom Functionの設定が終わったら、ノードを繋いでいきます。
- Texture2Dを変数として出しておき、それをCustom Functionのtexにつなぎます。
- UVノードを作成し、それをCustom Functionのuvにつなぎます。
- アウトプットのColorはそのままFragmentのBase Colorにつなぎます。
- 画像では途中結果を見るためにPreviewノードにつないでいます。
完成
Assetsフォルダでマテリアルを作成し、そのマテリアルに作成したShader Graphを適用します。
Scene上に適当なオブジェクト (今回はPlane) を配置し、そのオブジェクトに作成したマテリアルを付けると完成です。

解説
コード解説
コードはエントリーポイントの部分とグレースケールに加工している部分に分けられます。
まず下記がエントリーポイントになります。
void GreyScale_float(UnityTexture2D tex, float2 uv, out float4 color)
{
color = ConvertGreyScale(tex, uv);
}
このGreyScaleの部分が関数名で、後ろに精度を表す _float という接尾辞が必要です。リソースを節約する必要がある場合は、 **_harf ** を使うこともできます。
引数においてoutが付いているものはノードから出力される変数、ついていないものはノードからインプットされる変数になります。
インプットのうち、UnityTexture2Dという型がShader Graph内で使われるTexture2Dを受け取るための型になります。
Texture2D型も存在しているのですが、Textureの色を取る際にSampler Stateも別で必要になるみたいです。UnityTexture2D型ですとSampler Stateを内部で持っているみたいなので、今回はこちらを使用しています。
この内容は調べてもあんまりヒットせず、フォーラムで言及されているのを見つけました。
次にグレースケールに加工している関数部分です。
float4 ConvertGreyScale(UnityTexture2D inputTex,float2 uv){
float4 texColor = SAMPLE_TEXTURE2D(inputTex.tex,inputTex.samplerstate, uv);
//グレースケールにするための係数
float3 GreyCoef = float3(0.299f, 0.587f, 0.114f);
float grey = dot(texColor.rgb, GreyCoef);
return float4(grey.xxx, texColor.a);
}
SAMPLE_TEXTURE2D関数はUnityで用意されている関数で、これを使うことで色を取得しています。
引数にUnityTexture2D型にあるtextureとSampler State、外部から受け取ったuvを入れることでカラーを取得することが出来ます。
取得したカラーに対してグレースケールにするための係数を掛けてあげてるとグレースケールになった数値が出てきます。
この数値の詳細に関しては、こちらの記事が詳しく説明してくださっています。
トラブルシューティング
なんか出ないというときはエラーが出ています。
シェーダーが何か破損していたり、初期化が出来ていなかったりするとエラーが出ます。
シェーダーのエラー解消は大変ですが、エラー文から探ったりAIに聞いたりして頑張ってください。

最後に
今回、Shader Graphで自作のhlslをCustom Functionで使うということにチャレンジしてみました。
Unityでシェーダーを全部プログラムで書こうとするとなかなか大変なので、Shader Graphを使いつつ部分的にhlslで補うという方法が使えるのはとても便利だと思います。
加えてhlslはプログラムなのでAIのサポートを受けやすいという利点もあるため、今後の使われる機会が増えるのではないかと思います。
拙い記事だったかもしれませんが最後までお読みいただきありがとうございました。
参考資料


