Unity Shader Graphでステンシル(Stencil)を使う方法|非対応の理由とURPでの実装手順
UnityのShader Graphはノードをつないでシェーダーを組めるツールですが、ステンシルバッファへの書き込み・参照を行うノードは用意されていません。そのため「shader graph stencil」で検索して手が止まる人が多く、マスク・くり抜き・ポータル・アウトラインといったステンシルを使う表現をShader Graphだけで完結できないのが実情です。この記事では、Shader Graphでステンシルが使えない理由を整理したうえで、コードを書かずに済むURPのRender Objectsによるマスク実装と、より細かく制御するShaderLabのStencilブロックの2通りの実装手順を具体的に示します。あわせてBlackboardやGraph Inspectorなど日常的に使うパネルの役割も扱います。動作確認は最新のUnity 6.5 LTS(2026年6月リリース)を基準にしています。
まとめ:Shader Graphのステンシルは「Render Objects」か「ShaderLab」で代替する
結論を先に示します。Shader Graph単体ではステンシルを扱えないため、目的に応じて次のいずれかを選びます。
- Shader GraphにStencilノードは無い。URP・HDRPのどちらでも、Master Stackにステンシルの設定項目は公開されていない。
- コードを書きたくないなら、URPのRender Objectsレンダラーフィーチャでレイヤーごとにステンシル値を書き込み/比較する。マスクやくり抜きはこの方法が標準。
- 1シェーダー内で細かく制御したいなら、ShaderLabで
Stencil { Ref … Comp … Pass … }ブロックを書く。Shader Graph生成シェーダーとは併用に注意(再生成で消える)。 - 環境はUnity 6.5 LTS基準。Built-inレンダーパイプラインはUnity 6.5で非推奨化され、Shader GraphはURP/HDRP前提になっている。
以降で、まずShader Graphの前提を押さえ、ステンシルが使えない理由と2通りの代替実装、そして主要パネルの操作を順に解説します。
Shader Graphとは:ノードでシェーダーを作る仕組みと対応パイプライン
Shader Graphは、頂点・フラグメントの処理をノードの接続で組み立て、HLSLを直接書かずにシェーダーを作れるツールです。プレビューを見ながら調整できるため、シェーダー未経験のアーティストでも色替えやテクスチャ表現に着手しやすいのが特徴です。ただし利用にはスクリプタブルレンダーパイプライン(SRP)が必須で、対応環境の前提を最初に押さえておく必要があります。
対応パイプラインと必要なUnityバージョン
Shader GraphはURP(Universal Render Pipeline)とHDRP(High Definition Render Pipeline)専用で、Built-inレンダーパイプラインでは動きません。Built-inはUnity 6.5で非推奨(deprecated)に位置づけられ、新規プロジェクトはURPが推奨されています。Unity 6.5 LTSではURPをテンプレートから選ぶとShader Graphパッケージも同時に導入されるため、通常は個別インストールは不要です。導入済みかはPackage Managerで「Shader Graph」を確認できます。最新のUnityバージョンや変更点はUnity 6.3 LTSの新機能と6.2からの主な変更点まとめやUnityの日本語化とUnity 6の新機能もあわせて確認してください。
シェーダー作成からMaterial適用までの最短手順
基本の流れは3ステップです。Projectウィンドウで右クリックしCreate > Shader Graph > URP > Lit Shader Graph(用途に応じてUnlit)を選んでグラフを作成します。次にそのグラフを右クリックしてCreate > MaterialでMaterialを生成し、最後にシーン内のオブジェクトのMesh RendererにそのMaterialをドラッグして割り当てます。グラフをダブルクリックすればShader Graphウィンドウが開き、ノードを編集するたびにMaterialへ反映されます。
Shader Graphでステンシル(Stencil)が使えない理由
「unity shader graph stencil」で検索する人の多くは、マスク処理やくり抜き表現をShader Graphで実現しようとして詰まっています。まず、ステンシルとは何か、なぜShader Graphで扱えないのかを整理します。
ステンシルバッファの役割とShader Graphでの用途
ステンシルバッファは、各ピクセルに0〜255の8bit整数を保持できる描画用のマスク領域です。あるオブジェクトの描画時にステンシル値を書き込み、別のオブジェクトの描画時にその値を比較して「一致する場所だけ描く/描かない」を制御します。これにより、壁の穴から別空間が見えるくり抜き・ポータル、特定形状の内側にだけテクスチャを出すマスク、重なり順を無視して常に手前に出すアウトラインなどが実現できます。ステンシルは色の計算ではなく「どこを描くか」を決める仕組みである点がポイントです。
Master Stackにステンシル設定が公開されていない
Shader Graphの出力はMaster Stackが担いますが、ここにはステンシルのRef値・比較関数・書き込み動作を設定する項目がありません。ステンシルはノード(値の計算)ではなくレンダーステート(描画時の状態)に属するため、ノードグラフの表現領域から外れているためです。これはURP・HDRPのどちらのターゲットでも同じで、Unity 6.5時点でもStencilノードやMaster Stackのステンシルブロックは追加されていません。したがってステンシルは、Shader Graphの外側にある2つの仕組みで補います。
URPのRender Objectsでステンシルマスクを実装する手順(コード不要)
コードを書かずにステンシルマスクを作る標準手段が、URPのRender Objectsレンダラーフィーチャです。シェーダーには手を入れず、レンダラー側でレイヤーごとにステンシルの書き込みと比較を差し込みます。ここではマスク形状の内側にだけ被マスクオブジェクトを表示する例で手順を示します。
マスク用と被マスク用のレイヤーを分けて通常描画から除外する
まず、ステンシル値を書き込む「マスク」オブジェクトと、その値の内側にだけ出したい「被マスク」オブジェクトに、それぞれ専用レイヤー(例:Mask、Masked)を割り当てます。次にプロジェクトのUniversal Renderer Data(既定ではAssets/Settings配下)を開き、Opaque Layer MaskとTransparent Layer Maskからこの2レイヤーのチェックを外します。これで通常描画からは外れ、次に追加するRender Objectsフィーチャだけがこれらを描くようになります。
Render Objectsでステンシル値を書き込む
Universal Renderer DataのAdd Renderer FeatureからRender Objectsを追加し、マスク書き込み用に次のように設定します。マスクは色を出さずステンシルだけ書き込むため、マスク側のMaterial(Shader Graphで作った無地のUnlitで可)は最終的に見えなくてよい前提です。
| 項目 | マスク書き込み用 | 被マスク表示用 |
|---|---|---|
| Event | AfterRenderingOpaques | AfterRenderingOpaques |
| Layer Mask | Mask | Masked |
| Overrides > Stencil | ON | ON |
| Value | 1 | 1 |
| Compare Function | Always | Equal |
| Pass | Replace | Keep |
マスク側はCompare Function = Always・Pass = Replaceで、マスク形状のピクセルにステンシル値1を書き込みます。マスク自体の色を消したい場合は、マスク用Materialを半透明・不透明度0にするか、専用のColorMask 0シェーダーを使います。
被マスク側をEqualで比較し表示を制御する・順序の注意点
被マスク表示用のRender ObjectsではCompare Function = Equal・Value = 1にします。これで、ステンシル値が1になっている場所(=マスク形状の内側)にだけ被マスクオブジェクトが描画され、外側では描かれません。ここで最も間違えやすいのがフィーチャの並び順です。Render Objectsはリストの上から順に実行されるため、マスク書き込み用を先(上)、被マスク表示用を後(下)に並べます。逆にすると、比較の時点でまだステンシル値が書かれておらず、何も表示されません。透明オブジェクトを扱う場合は、EventをAfterRenderingTransparentsにした別のRender Objectsを用意します。くり抜きやポータルで被マスクが奥に隠れて出ないときは、被マスク側のDepth Test(ZTest)設定が奥行きに負けている可能性があるため、あわせて見直します。
ShaderLabのStencilブロックで細かく制御する方法
Render Objectsはレイヤー単位の制御ですが、シェーダー1本の中でステンシルを完結させたい、あるいはマテリアルごとにRef値を変えたい場合は、ShaderLabでStencilブロックを書きます。こちらはコードが必要な代わりに、書き込みと比較を細かく指定できます。
StencilブロックのRef・Comp・Passの書き方
ステンシル値を書き込むマスクシェーダーは、Passの中に次のようなStencilブロックを置きます。色を出さずステンシルだけ書き込むため、ColorMask 0で色書き込みを止め、後ろのオブジェクトを隠さないようZWrite Offにします。
Shader "Custom/StencilMask"
{
SubShader
{
Tags { "RenderType" = "Opaque" "Queue" = "Geometry" }
Pass
{
ColorMask 0
ZWrite Off
Stencil
{
Ref 1
Comp Always
Pass Replace
Fail Keep
}
}
}
}
Refは書き込む参照値(0〜255)、Comp Alwaysはステンシルテストを常に通す指定、Pass Replaceはテスト通過時にRef値で上書きする指定、Fail Keepは失敗時に既存値を保つ指定です。読み取り側のシェーダーではComp Equalにして、値が一致する場所だけ描画します。
Shader Graph生成シェーダーと併用するときの注意
Shader Graphが吐き出すシェーダーコードは、グラフを編集するたびに再生成されます。生成コードを直接書き換えてStencilブロックを足しても、次の保存で上書きされて消えるため、恒久的な方法にはなりません。実務では「ステンシルの書き込み・比較はShaderLabの専用シェーダーやRender Objectsに任せ、色・テクスチャの見た目はShader Graphで作る」と役割を分けるのが安全です。Unity 6.5ではHLSLノードを直接記述できるshader function reflection APIが追加され、Custom Functionノードによる拡張の幅は広がりましたが、レンダーステートであるステンシルはノード側からは設定できない点は変わりません。ステンシルはグラフの外で制御すると割り切るのが結局は近道です。
Blackboard・Graph Inspector・Master Stack:Shader Graphの主要パネル
ステンシル以外でも、Shader Graphを使ううえで役割を混同しやすいのがBlackboard・Graph Inspector・Master Stackの3パネルです。それぞれ「公開パラメータ」「設定」「出力」を担当します。
Blackboardで公開プロパティを管理する
Blackboardは、Materialのインスペクターに露出するプロパティ(色・数値・テクスチャなど)を一覧・追加・整理するパネルです。ここで追加したプロパティをノードとしてグラフに置くと、Material側からその値を変更できるようになります。プロパティ名や型、キーワード(分岐用のスイッチ)もBlackboardで管理し、1つのシェーダーを複数のMaterialで使い回す設計の起点になります。
Graph Inspectorでノードとグラフの設定を変更する
Graph Inspectorは、選択中のノードの設定(Node Settings)と、グラフ全体の設定(Graph Settings)を切り替えて編集するパネルです。ノード側ではPrecision(後述)やチャンネル指定などを、グラフ側ではターゲットとするパイプライン(URP/HDRP)やSurface Type(Opaque/Transparent)、両面描画などを設定します。ステンシルの項目はここにも無いため、描画状態そのものはRender ObjectsやShaderLabで扱う点は共通です。
Master Stackで出力先とターゲットを決める
Master Stackは、グラフの最終出力をVertexブロックとFragmentブロックに接続する終端です。Base Color・Metallic・Smoothness・Emissionなどの出力先が並び、ここに計算結果をつなぐことで見た目が決まります。表示される出力ポートはGraph Settingsのターゲット設定に応じて変化します。
Precision ModeとColor Mode:型と可読性の設定
Shader GraphにはModeと名の付く設定が複数あり、混同されがちです。実務で効くのは計算精度を決めるPrecision Modeと、グラフの見やすさに関わるColor Modeの2つです。
Precision Mode:half・float・inheritの選び分け
Precision Modeは、ノードやグラフ全体で使う浮動小数点の精度を決めます。Single(float・32bit)は高精度で座標計算や大きな値の扱いに向き、Half(16bit)はメモリ帯域と演算コストを抑えられるためモバイルの色・UV計算で有利です。Inheritは接続元の精度を引き継ぐ設定で、既定はこれになります。精度を落としすぎると縞(バンディング)や座標のズレが出るため、色まわりはHalf、位置計算はSingleと使い分けるのが定石です。全体の既定はGraph Settings、個別ノードはNode Settingsで変更します。
Color Mode:ノードを色分けしてグラフを読みやすくする
Color Modeは描画結果ではなく、エディタ上でノードの枠をどう色分けするかを切り替える表示設定です。カテゴリ別・Precision別などで着色でき、ノード数が増えたグラフの見通しを保つのに使います。実行結果には影響しないため、チームでの可読性向上や特定ノードの追跡用と割り切って使います。
Sub Graphでシェーダー処理を再利用する
同じノードの組み合わせを複数のシェーダーで繰り返すなら、Sub Graphにまとめて再利用します。Create > Shader Graph > Sub Graphで作成し、入力(プロパティ)と出力(Output)を定義すると、通常のグラフから1つのノードとして呼び出せます。共通のノイズ生成やUV変換をSub Graph化しておくと、仕様変更時にSub Graphだけ直せば全シェーダーに反映され、修正漏れを防げます。Sub Graph内でもプレビューで結果を確認できるため、単体でのデバッグも可能です。
主要ノードとリファレンスの調べ方
Shader Graphのノードは数が多く、名前から機能を推測しづらいものもあります。よく使うノードと、公式リファレンスでの確認方法を押さえておくと調べる時間を短縮できます。
色替え・アニメーションで頻出するノード
頻出はテクスチャを読むSample Texture 2D、時間で動かすTime、線形補間のLerp、しきい値でなめらかに切り替えるSmoothstep、UVを扱うUVやTiling And Offsetなどです。たとえば「色替え」はLerpやMultiplyでBase Colorを差し替え、「アニメーション効果」はTimeをUVや値の入力につないで作ります。パーティクルのように大量のオブジェクトを動かす視覚効果はShader Graphの守備範囲外で、VFX Graphの概要とリアルタイムVFX制作への活用メリットで扱うVFX Graphが適しています。
公式ドキュメント(Node Library)で仕様を確認する
各ノードの入力・出力・型は、Unity公式マニュアルのNode Libraryが一次情報です。ノード名で検索すると、ポートの意味やデフォルト値、対応パイプラインまで確認できます。エディタ上でもノードを選んでF1相当のヘルプから該当ページへ飛べるため、「このノードのSmoothstepのEdge1・Edge2は何か」といった細部は推測せず公式で確認するのが確実です。
よくある質問
Shader Graphでステンシルは使えますか?
ノードとしては使えません。Shader GraphのMaster Stackにステンシルの設定項目が無いためです。コードを書かない場合はURPのRender Objectsレンダラーフィーチャで、書き込みたい場合はShaderLabのStencilブロックで代替します。
Shader Graphはどのレンダーパイプラインで使えますか?
URPとHDRPで使えます。Built-inレンダーパイプラインでは使えず、Built-inはUnity 6.5で非推奨化されました。新規プロジェクトはURPテンプレートで始めるとShader Graphがそのまま使えます。
Shader GraphとVFX Graphはどう違いますか?
Shader Graphは1つのマテリアルの見た目(色・質感・変形)を作るツール、VFX GraphはGPUで大量のパーティクルを制御して炎や煙などのエフェクトを作るツールです。用途が異なり、両者を組み合わせて使うこともあります。詳細はVFX Graphの概要とリアルタイムVFX制作への活用メリットを参照してください。
Shader Graphで影やカスタムライティングは作れますか?
URPのLit系ターゲットで標準的なライティングは扱えますが、独自のライティングモデルや高度な影の制御はノードだけでは難しく、Custom FunctionノードでHLSLを書くか、ShaderLabの手書きシェーダーが必要になる場面があります。
ノードでできない処理をHLSLで書けますか?
Custom Functionノードで任意のHLSLを組み込めます。Unity 6.5ではHLSLノードを直接記述できるshader function reflection APIも追加されました。ただしステンシルのようなレンダーステートはノード側から設定できないため、Render ObjectsやShaderLabで扱います。