Skip to main content

Shader Graph

プロジェクト設定

ShaderLabの自由度が高く、とてもパワフルなシェーダの作り方であるが、やや難しいところもある。複雑で高速なシェーダが必要なら、ShaderLabの方が良いと思われるが、単純なシェーダなら、Shader Graphの方が楽で、作るのも速くなる。

 Shader Graphは言語ではなく、「ノード」というブロックを紐でつなげることにより、視覚的にシェーダを作成ができる。

 まず、Shader Graphをインストールしましょう。Unityの Package Manger から Shader Graph をインストールしてください。

image.png

初めてのシェーダーグラフ

まず、空のシェーダを作成しましょう。「Project」の中に、専用の「Shader」フォルダーを作成し、その中に「Lit Shader Graph」を作成してください。このシェーダーは後ほど使うので名前を「Chessboard」にしてください。

image.png

新しく作ったシェーダーグラフをダブルクリックすると、シェーダーエディタが開く:

image.png

各部品を理解しましょう:

頂点シェーダー(Vertex)

頂点シェーダーは、メッシュの各頂点の位置、または法線ベクトルを変えることができるシェーダーである。マテリアルを設定するだけで、3Dモデルの変形ができるシェーダー:

image.png

フラグメントシェーダー(Fragment)

フラグメントシェーダーは、メッシュの各ピクセルの色、法線ベクトル、金属性などを変えることができるシェーダーである。マテリアルを設定するだけで、3Dモデルの見え方を変えれるシェーダー:

image.png

ブラックボード(Blackboard)

パラメータを作成ができるところ。Unityのインスペクターで変えることができる数値をここに追加する。

image.png

グラフ・インスペクター(Graph Inspector)

普通のインスペクターと同様に、現在選択されているものに関する情報や数値を確認し、変えることができるパネル:

ノード設定(ノードによって変わる) グラフ設定(全般設定)

image.png

image.png

プレビュー(Main Preview)

シェーダの結果のプレビュー

image.png

様々なシェーダを作ろう!

Shader Graph で使える「ノード」を紹介しながら、いろんな効果を再現し、3Dモデルの見せ方を変えてみましょう。

無限チェスボード

image.png

考え方:「XZ平面の位置により、白いコマ、または黒いコマを表示したい」

ならば、3D平面の各ピクセルは3D空間の中にどこにあるのかを求める必要がある。その場合は、以下のノードを使える:

Positionノード

image.png

Positionノード

  • Vertexと繋ぐと:各頂点の位置
  • Fragmentと繋ぐと:各ピクセルの位置

入力

  • なし

設定

  • Space:どの位置を使う?
    • World:3Dシーンの絶対位置
    • Object:GameObject内の相対位置
    • View:カメラから見た位置

出力

  • Out(3):XYZの位置

Positionノードを Base Color(Fragment)と繋ぐと:

image.png

image.png

ってどういうこと?実は、「位置」を「色」に書き換えた。元々の位置はXYZとして表現していたものを、そのままRGBに書き換えて、表示しているだけ。つまり:

  • X=R→X軸の位置が大きくなると、色が赤くなる
  • Y=G→Y軸の位置が大きくなると、色が緑になる
  • Z=B→Z軸の位置が大きくなると、色が青くなる

確認:平面の位置を変えて、色がどう変わるのか、確認してみてください。
※ポイント:色はいつも0~1の間で表現するので、位置は「1」を超えると最大値になり、それ以上色が変わらない

 Positionノードで位置を取れることが分かったが、なかなかチェスボードにならない。問題を分けて、少しずつ解決してみましょう。まず、X軸だけで白黒の「しましま」のパターンを作成しましょう。YとZは要らないので、新しいノードが必要:

Split ノード

image.png

Splitノード

  • ベクトルを成分に分割する

入力

  • In(1):2D, 3Dまたは4Dのベクトル

設定

  • なし

出力

  • R(1):赤色、またはX軸
  • G(1):緑色、またはY軸
  • B(1):青色、またはZ軸
  • A(1):アルファ値、または4Dの4つ目の成分(W)

グラフを直して、Position→Split(R)→Base Colorをつなげてみましょう:

image.png

image.png

X軸の数値だけしか残らないので、Xの位置が大きいほど、白くなる!(RGBはすべてXの数値になる)。ちょっと近づいた気がしますが、しましまのパターンになっていない。何か周期的に繰り返すものがないか?

image.png

この図は「sin(θ)」のグラフであり、2πごとになみのように繰り返す関数である!x軸はどれだけ大きくなっても、出力は必ず-1~1の間になるので、次のノードを追加しましょう:

Sine ノード

image.png

Sineノード

  • ベクトルを成分に分割する

入力

  • In(1):角度(ラジアン)

設定

  • なし

出力

  • Out(1):サイン関数の結果

Position→Split(R)→Sine→Base Colorにすると:

image.png

image.png

しましまのパターンが現れた!…が、色がなめらかに変わる。確かに、Sinのグラフを見ると、-1〜1の間にゆっくり変わる。「白→黒→白→黒」の2色だけがほしい、以下のように:

image.png

つまり、「sin」が「0以上」だったら、「1」にし、「0未満」の場合は、「0」とする(青い線)。これは、「Step」ノードで実現できる!

Step ノード

image.png

Stepノード

  • 入力した値を「しきい値」以上だと「1」を返す、以下だと「0」を返す

入力

  • Edge(1):しきい値
  • In(1):入力値

設定

  • なし

出力

  • Out(1):「0」か「1」

Sineの後にStepノードを挟んで、確認しましょう。Edge は「0」にしてください。

image.png

image.png

かなりよくなった!ただし、1つの「ストライプ」はUnityのグリッドと比べると、サイズが合わない。なぜなら、Unityのグリッドの間隔は「1単位」なのだが、sin の周期は π(約3.1416)である。これは簡単に解決できる。sin の周期は Unity の1単位にすれば良いでしょう。つまり、1つの単位をπ倍数にすれば良いということです。掛け算のノードは:

Multiply ノード

image.png

Multiplyノード

  • 2つの数値の掛け算を返す

入力

  • A(1):1つ目の数値、またはベクトル
  • B(1):2つ目の数値、またはベクトル

設定

  • なし

出力

  • Out(1)
    • 数値と数値:A × B 
      • 10 x 4 = 40
    • 数値とベクトル:数値と各成分でできる新しいベクトル
      • 3 x [1, 2, 3] = [3, 6, 9]
    • ベクトルの場合は、各成分の掛け算を返す
      • 例:[1, 2, 3] × [4, 5, 6] = [4, 10, 18]

Split → Multiply → Sine を繋ぎ、「B」は「3.1416」にしておいてください:

image.png

image.png

Sineの周期をUnityの単位に合わせたので、1つのストライプはグリッドにぴったり!

これで、チェスボードの半分ができた!Z方向の処理は同じになるので、ノードを重複してもOK!(Splitノードの(R)の代わりに(B)を使ってください)

image.png

では、ZとXどう合成すれば良いでしょう?Zは「黒」の場合は、Xのストライプはそのままにして、Zは「白」になったら、Xの色を反転してほしい(白↔黒)

image.png

色は「白:1」「黒:0」というのを分かっているので、XとZの差分(X-Z)を計算してみましょう:

X方向の値(色) Z方向の値(色) X-Z 期待
1(白) 0(黒) 1(白) 1:✓
0(黒) 0(黒) 0(黒) 0:✓
1(白) 1(白) 0(黒) 0:✓
0(黒) 1(白) -1(?) 1:×

最後だけは「1」ではなく、「-1」になってしまうので、絶対値を取れば直せる。以下の2つのノードで「X」と「Z」を合成しましょう: 

Subtract ノード

image.png

Subtract ノード

  • 2つの数値の引き算を返す

入力

  • A(1):1つ目の数値、またはベクトル
  • B(1):2つ目の数値、またはベクトル

設定

  • なし

出力

  • Out(1)
    • 数値と数値:A - B 
      • 10 - 4 = 6
    • 数値とベクトル:数値と各成分でできる新しいベクトル
      • 3 - [1, 2, 3] = [2, 1, 0]
    • ベクトルの場合は、各成分の引き算を返す
      • 例:[1, 2, 3] - [4, 5, 6] = [-3, -3, -3]
Absolute ノード

image.png

Absolute ノード

  • 絶対値を返す

入力

  • In(1):数値、またはベクトル

設定

  • なし

出力

  • Out(1):数値、また各成分の絶対値

X方向とZ方向の差分+絶対値を計算し、Base Colorと繋ぐと:

image.png

image.png

レインボーキューブ

image143.gif

このシェーダは、オブジェクトのUVを変えて、テクスチャをアニメーションするシェーダである。まず、「rainbow」のテクスチャをドラッグドロップでシェーダに追加する。自動的に、Sample Texture 2Dのノードを作成される: