こんにちは。タノシムスタジオ@東京オフィスでクライアントエンジニアをやっている飛田です。タノシムスタジオでは、クライアントサイドにUnityを採用して、ゲーム開発をしています。
前回は、Universal Render Pipeline(URP)の基本的な使い方について説明しました。今回はpart2ということで、URPを使用しているプロジェクトで利用可能なShader Graphについて解説します
本記事で示す内容は、以下のような環境で検証をしました。
- UnityHub 2.3.2 + Unity 2019.3.5f1
- UniversalRP 7.2.1
- Build Settings
- Platform: PC, Mac & Linux Standalone => Target Platform: Mac OS X
Shader Graphとは
Shader Graph(シェーダーグラフ)は、Universal Render PipelineやHD Render Pipelineを使用しているプロジェクトで利用できる、GUIで視覚的に操作してシェーダーを作成できる機能です。名前にGraphとついている通り、データやデータの操作をノードで表現し、それらを接続することで、シェーダーを組み上げていくことができます。
これにより、従来は、HLSLなどのシェーダープログラミング言語を使って書かなければならなかったシェーダーを、非プログラマーでも作成することができるようになりました。もちろん、実現したい表現によっては、ある程度の数学的素養が求められますが、プログラミング言語の仕様を把握しなくても、シェーダーを作成できるので、プログラマにとっても、手軽にシェーダーを実装できる、非常に強力なツールとなっています。
ShaderGraphを使ってみよう
シェーダーとマテリアルの準備
まず、前回と同様にUnityHubからURPプロジェクトを作成します。それから、新しいシーンを作成して、以下の手順で、ShaderGraphを利用するマテリアルを作成し、シーン上のオブジェクトにアタッチします。
-
ShaderGraphを作成する
- Projectウィンドウ内で右クリックし、コンテキストメニューからCreate > Shader > PBR Graphを選択する
- 作成したShader GraphをFirstShaderGraphという名前にする
-
マテリアルを作成する
- Projectウインドウ内で右クリックし、コンテキストメニューからCreate > Materialを選択する
- 作成したマテリアルをShaderGraphMatという名前にする
-
ShaderGraphMatに適用するシェーダーを変更する
- ProjectウインドウでShaderGraphMatを選択する
- Inspectorビューで、Shaderの項目を"Shader Graphs" > "FirstShaderGraph"と選択し、適用するシェーダーを変更する
-
シーン上にSphereオブジェクトを作成する
- Hierarchyビューで右クリックし、Create > 3D Object > Sphereを選択する
-
Sphereオブジェクトのマテリアルを変更する
- HierarychyビューでSphereを選択する
- InspectorビューのMesh RendererコンポーネントのMaterialsのElement 0に、ShaderGraphMatをドラッグ&ドロップし、マテリアルを変更する
単純なShader Graphの作成
ここでは、非常に単純な、静的に設定したテクスチャを貼り付けるだけのシェーダーを作成します。
Projectウインドウ内で、FirstShaderGraphをダブルリック、または、選択した状態でInspectorビューの「Open Shader Graph」ボタンをクリックしてください。
すると、Shader Graph Editorウインドウが開きます。
左から、以下のようなものが表示されています。
- A. FirstShaderGraphと書かれたウインドウ: Blackboardと呼ばれるもので、後で詳しく説明- します。
- B. Main Previewと書かれたウインドウ: 最終的な見た目のプレビューです。
- C. PBR Masterと書かれたノード: 最終的なアウトプットを表すMasterノードノードです。
初期状態では、ノードは、Masterというノードだけが存在します。ここから、以下の手順で、ノードを追加し、ノード同士を接続していきます。
- Sample Texture 2Dを作成する
- 右クリックして、Create Nodeをクリックする
- Input > Texture > Sample Texture 2Dを選択する
これで以下のようにノードが追加された状態になります。
Masterノード以外のノードは、上半分が左右に別れており、左がそのノードに対する入力、右がそのノードの出力を表しています。また、下半分はそのノードのプレビューです。いまはTextureがなにもセットされていないので真っ白です。
- Sample Texture 2DノードとPBR Masterノードを接続する
- Sample Texture 2Dノードの右半分に表示されているRGBA(4)の右の丸を、PBR MasterノードのAlbedo(3)の左の丸までドラッグ&ドロップする
これでノード同士が接続され、Sample Texture 2Dノードの出力が、Masterノードに入力されました。
なお、RGBAが4つの値を持つのに対して、Albedoが3つの値しか持たないので、4つ目の値であるアルファは捨てられることになります。
-
テクスチャを設定する
- Sample Texture 2Dノードの左半分のTexture(T2)につながっているテクスチャのインプット欄の丸をクリックする
- 適当なテクスチャ、例えば、OBS_Albedoを選択する
-
Shader Graphを保存する
- ウインドウ左上の「Save Asset」ボタンをクリックする
これで、指定したテクスチャを貼り付けるだけのShaderが完成しました。Unity Editorに戻ってみましょう。
SceneビューやGameビューで表示されているSphereが、Shader Graph Editorのプレビューと同様の見た目になっています。
ShaderGraphとスクリプトを連携させてみよう
Blackboardの利用
Unityのシェーダーには、InspectorやC#スクリプトから値を操作することを可能にする、プロパティというものがあります。Shader Graphで作成したシェーダーで、プロパティをInspectorなどに公開したい場合、Blackboardという機能を利用します。
ここでは、前項で作成したシェーダーを修正して、Inspectorでテクスチャを設定できるようにします。以下の手順で、FirstShaderGraphをさらに編集しましょう。
-
Blackboardビューを表示する
- もしBlackboardが表示されていなければ、Shader Graph Editorウインドウの右上にある、Blackboardボタンを押す
-
BlackboardにTexture 2Dプロパティを追加する
- Blackboardビューの+ボタンを押す
- Texture 2Dを選択する
-
Texture 2Dプロパティを公開する
- 追加したプロパティのExposedにチェックを入れる
- 追加したプロパティのExposedにチェックを入れる
-
プロパティに対応するノードを作成する
- 作成したプロパティをBlackboardビューの外までドラッグ&ドロップする
-
Texture 2DノードとSample Texture 2Dノードを接続する
- 作成したTexture 2Dノードの丸ボタンを、Sample Texture 2Dのインプット側にあるTexture(T2)の丸までドラッグ&ドロップする
- 作成したTexture 2Dノードの丸ボタンを、Sample Texture 2Dのインプット側にあるTexture(T2)の丸までドラッグ&ドロップする
-
Shader Graphを保存する
- 「Save Asset」ボタンを押す。
これでInspectorでテクスチャの設定ができるようになりました。Projectウインドウで、ShaderGraphMatを選択すると、InspectorビューでTexture 2Dというプロパティが表示されます。Texture 2Dの右側の四角をクリックし、適当なテクスチャを選択してみましょう。
C#スクリプトからプロパティを操作する
ここでは、前項で作成したシェーダーに、Saturation(彩度)ノードを追加し、C#スクリプトから彩度を操作する例を示します。
FirstShaderGraphをShader Graph Editorで更に編集しましょう。
-
Saturationノードを追加する
- 右クリックして、コンテクストメニューから"Create Node"を選択する
- 検索欄で"Saturation"を検索し、選択する
-
ノードを接続する
- Sample Texture 2DノードのRGBAをSaturationノードのInに接続する
- SaturationノードのOutをMasterノードのAlbedoに接続する
-
Vecto1型のプロパティを追加する
- Blackboardウインドウの"+"ボタンをクリックする
- "Vector1"を選択する
-
追加したVector1プロパティの設定を変更する
- 名前を"Saturation"に変更する
- Exposedにチェックを入れる
- Referenceを"_Saturation"に変更する
-
プロパティをノード化・接続する
- Saturationプロパティをドラッグ&ドロップして、ノード化する
- Saturtionノードの"Saturation"に接続する
-
Shader Graphを保存する
- "Save Asset"ボタンを押す
Unity Editorに戻り、ShaderGraphMatを選択すると、Inspectorビューで以下のようになります。
Saturationがデフォルトでは0なので、プレビューでは完全にグレースケールです
InspectorからSaturationプロパティの値を変更できるようになりましたが、さらに、C#スクリプトでゲーム実行時に値を動的に変更してみましょう。
- SaturationControlスクリプトを作成する
- 新規C#スクリプトを作成し、SaturationControlという名前にする
- SaturationControlを編集し、以下のようにする
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(MeshRenderer))]
public class SaturationControl : MonoBehaviour
{
[SerializeField] Material material = null;
MeshRenderer meshRenderer;
void Awake()
{
meshRenderer = GetComponent<MeshRenderer>();
meshRenderer.material = new Material(material);
}
void Update()
{
var saturation = (Mathf.Sin(Time.time) + 1f) / 2f;
meshRenderer.material.SetFloat("_Saturation", saturation);
}
}
- Sphereオブジェクトの設定を行う
- シーン上のSphereオブジェクトに、SaturationControlをAdd Componentする
- MaterialフィールドにShaderGraphMatをアタッチする
これで、ゲームを再生すると、Sphereの彩度が周期的に変化するようになります。
C#スクリプトからプロパティの値を操作する場合は、Materialクラスのプロパティのデータ型に応じたメソッド(SetFloat(), SetColor(), SetTexture()など)を呼ぶ必要があります。
今回、操作したいプロパティはVector1型なのでSetFloat()メソッドを使用します。メソッドの第一引数には、プロパティ名を渡す必要がありますが、Shader Graphで作成したシェーダーの場合、指定すべき名前は、Blackboardウインドウに表示されている、Referenceという項目に表示されている文字列であることに注意してください。
おわりに
今回は、Shader Graphの基本的な使い方と、シェーダーとC#スクリプトの連携の簡単なサンプルを紹介しました。
今回利用したノードはSample Texture 2DとSaturationだけでしたが、Shader Graphには様々なノードが用意されています。
たとえば、数学的なものだと、単純な計算を行うAdd、Multiply、三角関数を表すSine, Cosineなどがありますし、色調を調整するようなものであれば、Saturation以外にもContrastやWhite Balanceなどがあります。
ぜひ、色々試してユニークなシェーダーを作ってみてください。
参考URL
Shader Graph: https://unity.com/ja/shader-graph
Shader Graph Manual: https://docs.unity3d.com/Packages/com.unity.shadergraph@7.2/manual/index.html