ShaderGraphで自作のNodeを作る際に手順　＋　つまったところ



# 開発環境
Unity2018.2.3
ShaderGraph3.0　preview

# ShaderGraphの自作ノード（カスタムノード）の作成の仕方

必要な要素としては以下の通り
1. ノードの呼び出し収納先の指定
2. ノードのタイトル
3. ノードの入力と出力の設定
4. 実際のシェーダーコードの記述

参考にしたURL
http://r-ngtm.hatenablog.com/entry/2019/01/19/190218
https://blogs.unity3d.com/jp/2018/03/27/shader-graph-custom-node-api-using-the-code-function-node/
参考にしたソースコード
https://gist.github.com/rngtm/d8b4bcd8785f24193bbadcf25325cdb4

#今回作成するもの


入力される４つの値をまとめたものを出力するためのものです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101366/7eea7d87-a32b-5f47-57ea-a65c3eb07374.png)



# 手順
手順としては以下の通り
## 下準備

C#のソースコードの作成、継承としてCodeFunctionを使用する

```

using UnityEditorShaderGraph

public class クラス名：CodeFunctionNode
{
    ・・・
}
```
といった感じです。
## ノードの呼び出し収納先の指定
このコードの上に[Title("階層名","メニューに表示されるノード名")]を付けると
CreateNodeで行いやすくなります。
※　ShaderGraph　ver 3.0.0では階層は1段しかもうけれない模様　（"OO/OO"と指定したが反映されず）

## ノードのタイトル

ノードのタイトルは、実際のShaderGraphに使用した際に、Nodeのタイトルに当たるものです。
以下の図でなら、「MyIntergrateNode」がそれにあたります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101366/af39beac-ce9e-74f9-8269-027431be814b.png)



```

クラス名（）
｛
    name = "ノードでのタイトル名"
}

```


## ノードの入力と出力の設定



```
                  [Slot(0, Binding.None)] Vector1 r,
                  [Slot(1, Binding.None)] Vector1 g,
                  [Slot(2, Binding.None)] Vector1 b,
                  [Slot(3, Binding.None)] Vector1 a,
                  [Slot(11,Binding.None)] out Vector4 ret

```
ノードの入力と出力には、Slot[]を使用します。
Slotの第一引数は、SlotIdなので、重複がしなければ問題ありません。
出力には、変数の前に　out　を使用する事で、出力の扱いになります。




## 実際のシェーダーコードの記述（今回つくったもの）

```

using UnityEngine;
using UnityEditor.ShaderGraph;
using System.Reflection;


[Title("Custom","Integration")]
public class IntegrateShaderNode : CodeFunctionNode
{
    public IntegrateShaderNode()
    {
        name = "MyIntegrateNode";
    }

    protected override MethodInfo GetFunctionToConvert()
    {
        return GetType().GetMethod("ShaderFunction",
            BindingFlags.Static | BindingFlags.NonPublic);
    }

    private static string ShaderFunction
        (
       
                  [Slot(0, Binding.None)] Vector1 r,
                  [Slot(1, Binding.None)] Vector1 g,
                  [Slot(2, Binding.None)] Vector1 b,
                  [Slot(3, Binding.None)] Vector1 a,
                  [Slot(11,Binding.None)] out Vector4 ret
              )
              {
                  ret = Vector4.zero;
                  return @"
                  {
                      ret =  float4(r,g,b,a);
                  }"
                  ;
    }
}

```

## エラーが出た場合の解決方法　（体験したやつ）

カスタムノードで、ノード自体は問題ないが、中のShaderコードでエラーが出た場合以下のような感じの見た目になります

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101366/05e63b2b-6cd4-9d7d-346a-662d44145a5b.png)


こうなると正しく動かないので、修正の必要があるのですが、慣れてないと意外とひっかかったりします。
この章では、引っかかった例を記述します。

### Vectorの形に引っ張られて、Shaderの書き方から逸脱した

今回のOutがVector4型で記述しているので、それにつられるパターンです

```
//間違った例
ret = Vector4(1,1,1,1);
//正しい例
ret = float4(1,1,1,1);

```


### out出力が初期化かかっていると思い込んでしまった。


呼び出された関数内で、初期化を行っているので、そのまま使用できると思い込んでしまったものです。
処理自体はあるから、意外と引っかかった人はおおいのではないでしょうか？そうでもない？

```
//間違った例
ret = ret + float4(1,1,1,1);

//正しい例
ret = 何かしらの初期化や計算して導かれる値

```