LoginSignup
5
4

More than 3 years have passed since last update.

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

Last updated at Posted at 2019-08-18

開発環境

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

今回作成するもの

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

image.png

手順

手順としては以下の通り

下準備

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


using UnityEditorShaderGraph

public class クラス名:CodeFunctionNode
{
    ・・・
}

といった感じです。

ノードの呼び出し収納先の指定

このコードの上に[Title("階層名","メニューに表示されるノード名")]を付けると
CreateNodeで行いやすくなります。
※ ShaderGraph ver 3.0.0では階層は1段しかもうけれない模様 ("OO/OO"と指定したが反映されず)

ノードのタイトル

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

image.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

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

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 = 何かしらの初期化や計算して導かれる値

5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4