scenario-unity-shaders について
scenario-unity-shadersは、Unity 6.3を扱うテクニカルアーティストやシェーディングエンジニア向けのスキルです。シェーダー作成と検証を支援し、対象プラットフォームでのコンパイル、レンダーパスの整合性、バリアント予算、初回実行、GPUコストの計測を重視します。
主な機能
- 01手書きURP HLSLのワークフロー
- 02テンプレートベースのShader Graph編集
- 03対象APIでのシェーダーコンパイル確認
- 04バリアントのストリッピングと予算監査
- 05PSOのウォームアップと初回実行確認
- 06GPUコストの計測
活用シーン
- 01トゥーン、水面、ディゾルブシェーダーの作成
- 02各レンダリング段階でのパス確認
- 03出荷するシェーダーバリアントの削減
- 04フルスクリーン効果のコストとウォームアップ測定
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ scenario-labs/ skills --skill scenario-unity-shadersインストール後、Claude Code で/scenario-unity-shadersを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/critique.mdexpert-notes.mdgui-paths.mdprocedures.mdsources.mdscripts/ut_shaders.pyscripts/AgentKit/Shaders/ComputeJobs.csGpuCostJobs.csPsoJobs.csRendererFeatureJobs.csShaderGraphJobs.csShaderJobs.csShaderLab.csVariantJobs.csscripts/Runtime/AgentFullscreenFeature.csAgentPsoProbe.csscripts/Shaders/AgentCompute.computeAgentCustomLighting.hlslAgentDissolve.shaderAgentEdgeOutline.shaderAgentGrayscale.shaderAgentLit.shaderAgentNoise.hlslAgentPasses.hlslAgentToon.shaderAgentWater.shader詳細
Unity シェーダー(テクニカルアーティスト、シェーディング)
Unity 6.3におけるエキスパートレベルのシェーディングとは、証明できるシェーダーのことです。対象のグラフィックス API 向けにコンパイルされ、すべてのパスで整合性が取れ、ストリッピング後のバリアント数が把握され、初回使用時にウォームアップされていることが示され、GPU ミリ秒単位でコストが測定され、数値を含むキャプチャで見た目が確認されています。マウスを使えないエージェントは、テキストを使ってこれを実現します。主な方法は手書きの URP HLSL です。Shader Graph は、公開されたプロパティで既存のグラフを駆動し、Custom Function ノードの背後にエージェントが所有する .hlsl を配置して使用します。新しいグラフの配線は GUI で行います(references/gui-paths.md)。対象環境:6000.3.21f1、URP 17.3、Shader Graph 17.3、Apple Silicon 上の Metal。このスキル内で名前が挙げられた兄弟スキルが利用可能なスキルにない場合は、ユーザーにインストールを依頼してください(npx skills add scenario-labs/skills --skill <name>)。無人で進める場合は、ツールスキーマに基づいて作業し、不足している点を明示してください。
必須の背景知識: scenario-unity-expert(チャネル、レビューループ、6.3の注意点)。そのツールキット(ut_env、ut_run、ut_review、AgentKit)はインポートして使用し、コピーしません。
ステータス(2026-09-24、ブラインド評価リファクタリング後): ここではすべての手順を Unity 6000.3.21f1 で実行しました。tests/code/unity-shaders/run_all.sh --live(開発プレイヤーの PSO 検証を含むライブチェック73件、オフラインチェック32件。すべて合格。証拠は archive/tests/unity-shaders/ にあります)。
スタンス(専門家ならではの見解)
- まずテキスト、グラフはテンプレートから。 Shader Graphにはループもライティングノードもほとんどないため、ライトとループはHLSLで扱います(Daniel Ilett、F8bAI6dIrto [00:07:13])。唯一の利点は深度パスとシャドウパスが自動生成されることですが(bH--RU6qyTw [00:38:24])、手書きシェーダーでも
AgentPasses.hlslがそれを実現します。グラフを使う場合は、1つ複製して公開参照を設定し、変化するロジックはFileモードの.hlslに記述します。Graph Settingsはすべてのパスに適用されます。Allow Material Overrideを有効にせずにAlpha Clippingを設定すると、生成された8つすべてのパスに#define _ALPHATEST_ON 1が書き込まれ、Booleanキーワードを使っても削除できません(インストール済みのUniversalTarget.csで確認)。 - すべてのパスで一貫させます。 変位と
clip()は、ShadowCaster、DepthOnly、DepthNormalsでも実行します(6.3 Manual、Ilett [00:37:52])。DepthOnlyパスがない場合、Depth Primingを使うと不透明シェーダーが見えなくなります(確認済み)。DepthNormalsはワールド法線をそのまま書き込みます。Manualのnormal * 0.5 + 0.5の例では、SSAOとアウトラインで正しく読み取れません(確認済み)。 - チュートリアルではなく、インストール済みのパイプラインを確認します。 インストール済みの
Lit.shaderからキーワードをコピーします(Ilett [00:14:51]、ut_shaders.urp_lit_keywords())。6.3には_CLUSTER_LIGHT_LOOPと4種類のソフトシャドウバリアントがあります。LIGHT_LOOP_BEGINはディレクショナルライトをスキップするため、カスタムループではForward+の下でディレクショナルライト用の事前ループが必要です。Unity独自のCustom Lightingサンプルにも、このループはありません(確認済み)。 - バリアント数はストリッピング後に数える予算です。 マテリアルの切り替えには
shader_feature、実行時のC#切り替えに限ってmulti_compileを使い、dynamic_branchは#ifではなくifでテストします(6.3 Manual)。ストリッピング前にStrict Shader Variant Matchingを使い、その後、ビルドログのファネルを確認します(Carotenuto、Unity blog 2024)。shader_feature(または_local)のバリアントは、ビルド内のマテリアルで有効になっている場合にのみ同梱されます(確認済み:0と6)。実行時のC#から切り替えてはいけません。Unity 6 Shader Build Settingsでは、コード使用数がゼロのキーワードを除外したり、型を変更したりできますが、#ifでテストされるキーワードへのdynamic_branchのオーバーライドは黙って無視されます。URPのソフトシャドウとSSAOのセットも対象です(確認済み)。 - 初回使用時にウォームアップ済みであることを実証します。 開発プレイヤーで、グラフィックスAPIとプラットフォームごとに1つの
GraphicsStateCollectionをトレースし、ロード画面の間にウォームアップします。ゲームプレイ中のフレームで、Shader.CreateGPUProgramのサンプル数がゼロ、ログに記録されたアップロード数もゼロであることを示します(6.3 Manual、Metalで14から0に減少したことを確認)。 - コストは命令数ではなくGPU時間です。 ループは最大反復回数で数え、float4はfloatのおよそ4倍のコストがかかり、超越関数は多くのサイクルを消費します(Ben Cloward、E82XxlXMJs4 [00:15:44])。ここでの測定では、float4に対する64回の
sinはfloatのおよそ3倍、積和ループの10倍以上のコストでした。halfを使うのは、デバイスプロファイラーでALU律速と確認できた場合のみです(Freya Holmér、kfM-yu0iQBk [01:20:26])。デスクトップのPlatformDefaultでは、halfはfloatとしてコンパイルされます。 - Render Graphの形。
RecordRenderGraphでは宣言のみを行い、記録はしません。新しいテクスチャに一度だけblitし、その後resourceData.cameraColor = destinationを設定します。AddRenderPassesで条件を判定し、バックバッファーは拒否します(6.3 docs、Unity dither sample、U8PygjYAF7A [00:09:06] [00:10:10])。 - 1つのスカラー場、1つのしきい値、2つの色。見た目を確認し、測定します。 トゥーン、水、ディゾルブ、アウトライン、ディザリングでは0..1の値にしきい値を適用します(visual digest)。水の深度マスクは、岸辺の法線も安定させます(gRq-IdShxpU [00:06:12])。クリップテストから放射エッジをオフセットします(Brackeys、taMp1g1pBeE [00:05:31])。中間値は色として出力し(Freya [01:57:25])、投影プローブ位置のピクセルをアサートします。
最初に確認すること
- プラットフォームとグラフィックス API:Metal、Vulkan、DX12、GLES 3.x、WebGL 2、または WebGPU。コンピュートは Metal、Vulkan、DX11/12、GLES 3.1 以降で動作します(GLES 3.1 では 4 バッファーが保証されます)。GLES 3.0 や WebGL 2 では動作しません。Web では WebGPU を通じて利用できます(6.3 では実験的機能です)。GPU Resident Drawer と STP は GLES を完全に除外します。
- レンダラーごとのレンダリングパス(Forward、Forward+、Deferred+):ライトループのコードを決定します。Shader Graph のカスタムライティングは Forward と Forward+ でのみ動作します。
- 品質レベルごとの URP アセット:Depth Texture と Opaque Texture、ソフトシャドウ、SSAO。テンプレートの
Mobile_RPAssetでは Depth Texture がオフになっています。深度フェードする水にはオンにするか、ベイク済みの海岸マスクが必要です。 - スタイルと担当者:トゥーンまたは PBR。アーティストがグラフを編集する場合(グラフは保持し、エージェントが
.hlslを担当)、またはコードのみの場合。 - オブジェクトごとの値:マテリアルインスタンス、
MeshRenderer/SkinnedMeshRenderer.SetShaderUserValue(6.3、SRP Batcher に対応)、またはMaterialPropertyBlock(SRP Batcher が無効になります)。 - 予算:エフェクトの GPU ms、シェーダーごとのバリアント数、オーバードロー、初回使用時のヒッチ。指定がない場合のデフォルト:URP 17.3 Forward+、テンプレートの PC およびモバイル向けティア、HLSL、シェーダーは
Assets/AgentShaders/以下。
ワークフロー
- インストールして棚卸しする。
ut_shaders.install(P);RendererFeatureJobs.ListFeatures(すべての品質レベル、アセット、レンダラー、フィーチャー);lint_shader_file、shadergraph_summary(ターゲット、プロパティ、Graph Settings の検出結果)、lint_project_keywords。GATE:パイプラインの事実を計画に記載し、lint エラーを列挙します。 - 作成する。
scripts/Shaders/のAgentLit、AgentToon、AgentWater、AgentDissolve、AgentEdgeOutline、AgentGrayscale、AgentCompute、共有のAgentPasses.hlsl(AGENT_CLIP/AGENT_DISPLACE)とAgentNoise.hlslから始めます。グラフを使う場合:ShaderGraphJobs.ImportPackageSample、DuplicateGraph、shadergraph_set_target_settings、GeneratedCode、AgentCustomLighting.hlsl。GATE:lint エラーがゼロであること。 - ターゲット向けにコンパイルする。
ShaderJobs.ValidateShaders(ShaderUtil.GetShaderMessagesに加え、Metal ではパスごとにCompileVariant)。GATE:エラーがゼロで、4 つの不透明パスが存在すること。 - ベンチマークして見た目を確認する。
SetupMaterials、ShaderLab.BuildScene、ShaderLab.Shots(起動ごとに多数のショットを撮影:マテリアル、レンダラー、フィーチャー、URP の変更;プローブをピクセルに投影)。GATE:ut_reviewのフラグに問題がなく、コンタクトシートが開かれ、プローブ値が確認できること(シャドウは何もない地面より暗い、1 でディゾルブの影が消える、追加ライトで照らされる側が変わる)。 - 全画面エフェクト。
AgentFullscreenFeatureを使うRendererFeatureJobs.AddFeature、またはコード不要のFullScreenPassRendererFeature。GATE:オン/オフのキャプチャに意図した差があり、バックバッファーエラーがないこと。 - バリアント。
VariantJobs.StrippingSettings(厳密な一致をオン)、出荷するマテリアル用のBuildShaderBundle、parse_variant_funnel、variant_budget_check、ストリップルールまたはKeywordOverrides(Shader Build Settings)、PostProcessingAudit(Assets/ 以下のすべての VolumeProfile でポスト処理バリアントを保持)。GATE:出荷するシェーダーごとの数が予算内であること;ロガーの合計が Unity の「After scriptable stripping」と一致すること;オーバーライドをクリアするか、意図をもってコミットすること。 - 初回使用時のカクつき。
PsoJobs.BuildPsoScene、ut_run.build(development=True)、ut_shaders.run_pso_playerのトレース、コールド、ウォーム;PsoJobs.InspectCollection;AgentPsoProbeが読み込むStreamingAssets/PSO/<platform>_<api>.graphicsstateを出荷します。GATE:pso_gateに問題がなく、コールドではアップロードが示され、ウォームではマーカーとログの両方でアップロードがないこと。 - コスト。
GpuCostJobs.MeasureFullscreenCostで A/B をインターリーブし、非同期コンパイルをオフにします(半精度テストにはprecision_model)。GATE:ノイズを超える ms の改善があること;デバイスの数値は開発用プレイヤーから取得します(scenario-unity-performance)。 - 納品する。 シェーダー、マテリアル、フィーチャーアセット、API ごとの
.graphicsstate、および証拠パケット(Handoffs)。
数値
| 値 | 対象 | 出典 |
|---|---|---|
| 7,688 全体;各ステージ 4,046;設定後 62;出荷時 13 | テンプレートの URP アセットを使用した macOS AssetBundle ビルドの AgentKit/Lit | 実測 |
| 13 から 11 | Shader Build Settings でソフトシャドウセットを除外した後の AgentLit の出荷バリアント数 | 実測 |
| 433 から 577 | 未使用の Bloom HQ + dirt プロファイルが 1 つ Assets/ 内にある場合の UberPost バリアント数 | 実測 |
| 14 から 0;1.8 から 2.4 ms | ゲームプレイ中の初回使用時の GPU プログラムアップロード数、コールド時とウォーム時;macOS プレイヤーで 1 フレーム中に 26 から 27 PSO をウォームアップ | 実測 |
| 0.007 から 0.033 / 0.29 から 0.42 / 0.89 から 1.66 ms | 1080p 全画面描画 1 回:64 回の乗算加算 / 64 回の sin / 64 回の float4 sin、M5 Max。同一実行内で比較 | 実測 |
| 0.92 から 1.00 / 0.77 から 0.89 | half4 と float4 の sin 実行時間の比、PlatformDefault / Unified 精度モデル、M5 Max(ノイズ約 10 %) | 実測 |
| 128 を超えるキーワード、4 つは予約済み | シェーダーごと:コンパイルが遅くなります | 6.3 マニュアル |
| 2000 / 2450 / 3000 | Geometry / AlphaTest / Transparent キュー | Cyanilux |
| 64x1x1、8x8x1 | コンピュートスレッドグループ;切り上げ除算したディスパッチと境界チェック | 6.3 マニュアル、[追加] |
| (1.2, 0.35, 0.03) と (4, 1.1, 0.15) | HDR のディゾルブエッジがオレンジ色を保つ場合と、Neutral トーンマッピングでクリーム色に白飛びする場合 | 実測 |
| 0.2126, 0.7152, 0.0722 | リニアカラーにおける Rec. 709 輝度 | 6.3 マニュアル |
品質ゲート
- 測定可能: lint と
lint_project_keywordsのエラーがゼロ;対象 API のValidateShadersのエラーがゼロ;SRP Batcher 互換(レンダリング後に読み取り);プローブ(影の輝度は開けた地面の 0.75 倍未満;ディゾルブの影は 1 で復元;Forward と Forward+ で追加ライトが照らされた側を変化させる;水面の法線は沖より岸辺で穏やか);機能のオン/オフによる差;出荷バリアント数が予算内で安定;不要な VolumeProfile がない;API ごとにpso_gateがクリーン;GPU ms の A/B 比較;コンピュート GPU の結果が CPU と一致(最大誤差が 1e-5 未満)。 - 視覚: コンタクトシートを開いて確認;トゥーンの階調が明瞭;水の色相変化、穏やかな岸辺、泡、動き;ディゾルブエッジが色相を保つ;アウトラインはシルエットのみ;マゼンタがない。
よくある間違い
| 間違い | 症状 | 修正 |
|---|---|---|
| DepthOnly パスがない | Depth Priming Forced でオブジェクトが消える | AgentDepthOnlyVertex/Fragment |
| フォワードパスでのみクリップしている | ディゾルブしたオブジェクトが完全な影を落とし続ける | すべてのパスで共有する AGENT_CLIP |
DepthNormals が n * 0.5 + 0.5 を返す | SSAO とアウトラインが正しく表示されない | 生の法線を返す |
指向性ライトの事前ループなしで LIGHT_LOOP_BEGIN を使用している | Forward+ で2つ目の指向性ライトが何も照らさない | 最初に URP_FP_DIRECTIONAL_LIGHTS_COUNT をループする |
_FORWARD_PLUS、SHADOWS_SCREEN、ComputeScreenPos(URP 11 で非推奨) | コンパイル警告、使用されないシャドウ分岐 | _CLUSTER_LIGHT_LOOP、GetMainLight(shadowCoord)、GetNormalizedScreenSpaceUV(positionCS) |
ランタイム C# から切り替える shader_feature_local(ディゾルブの「被弾時」など) | プレイヤーでバリアントが不足し、ピンク色になるか最も近いものになる | マテリアルを切り替えるか、multi_compile_local を使用する;lint_project_keywords |
| Shader Graph の Alpha Clipping をスキップする Boolean キーワード | すべてのパスで常にオブジェクト全体がアルファテストされる | Allow Material Override(_ALPHATEST_ON キーワード)か、2つ目の不透明マテリアルを使用する |
#if でテストされるキーワードに dynamic_branch Type Override を指定する | バリアント数が変わらない | if() でテストし、ステージ接尾辞なしで宣言する |
_fragment 接尾辞付きキーワードに if (KW) を使用する | 「既知のキーワードだが、このパスでは宣言されていない」 | すべてのステージで宣言する |
| 使われていない VolumeProfile アセット(サンプル、テスト) | シーンで使われないエフェクトのポスト処理バリアントが生成される | Assets/ の外へ移動する;PostProcessingAudit |
| すべての API に対する PSO コレクションを1つだけ用意する、または検証済みのものがない | デバイスで初回使用時にカクつく | API ごとにトレースし、コールド実行とウォーム実行を比較する |
| URP アセットで Depth Texture がオフになっている | 水がべた塗りの泡になり、SSAO が深度を要求している間は見えなくなる | 描画に使用するすべての URP アセットで有効にする;SSAO をオフにしてテストする |
| あるレンダラーでフィーチャーが欠落している | ある品質レベルで「エフェクトが何もしない」 | 品質レベル全体で ListFeatures を実行する |
| After Rendering への挿入 | 何も描画されず、バックバッファエラーが発生する | After Rendering Post Processing |
| HDR エッジカラーが4以上 | 発光エッジがクリーム色に薄れる | 1~1.5 にする。グローは Bloom で表現する |
| 命令数やデスクトップでの半分の値でコストを判断する | 「最適化済み」シェーダーが速くならない | MeasureFullscreenCost を実行する;デバイス上で半分の値にする |
UnityPerMaterial の外にプロパティがある | SRP Batcher がオフになり、値が混ざる | HLSLINCLUDE に CBUFFER を1つだけ置く |
引き継ぎ
- 受け取るもの:scenario-unity-rendering-lighting から、品質レベルごとの URP アセット、レンダリングパス、Depth/Opaque Texture、ポストプロセススタック、トーンマッピング、Default Volume Profile。scenario-unity-vfx から、パーティクルシェーダーの要件(ブレンドモード、ソフトパーティクル、フリップブック)。VFX Graph、Particle System、エフェクト予算は scenario-unity-vfx が担当します。scenario-unity-world-building から、水面と地形のサーフェス。scenario-unity-architecture から、マテリアルを操作するゲームプレイコード。
- 引き渡すもの:scenario-unity-vfx と scenario-unity-world-building に、シェーダー、参照先を記載したマテリアル、機能アセット。scenario-unity-performance に、GPU ms テーブル、バリアントの絞り込み、デバイスキャプチャの低温/高温時の証拠を含む
.graphicsstateファイル。scenario-unity-pipeline-automation に、CI 用のバリアント予算と PSO ゲート。scenario-unity-mobile と scenario-unity-web に、API の制限(GLES 3.1 では compute を使用可能、GLES 3.0 または WebGL 2 では使用不可)、デバイス上でプロファイリングする half 精度、モバイルでの Depth Texture のコスト、タイル GPU でのアルファテストのコスト。 - パケット:パス、
ValidateShadersJSON、コンタクトシート、プローブ、絞り込み結果、PSO 実行結果、コストテーブル、Verified と Assumed。
Unity 6.3 に関する注意事項
- Render Graph のみ:Compatibility Mode は削除されています(移植用の
URP_COMPATIBILITY_MODEは 6.4 で廃止)。AddBlitPassはビルダーを返します(returnBuilder: true)。After Rendering は常に最終 blit の後に実行されます(6.2 以降)。 _CLUSTER_LIGHT_LOOPは_FORWARD_PLUSに置き換えられました(6.1)。ソフトシャドウには_LOW/_MEDIUM/_HIGHのバリアントがあります。フォグは URP のFog.hlslでdynamic_branchとして宣言されています。- Shader Build Settings:
EditorGraphicsSettings.Get/SetShaderBuildSettings(アクティブな設定です。ビルドプロファイルで上書きできます)。GraphicsStateCollectionは試験的機能です。トレースには開発用プレイヤーが必要です。Metal にはCreateGraphicsGraphicsPipelineImplがありません。Log Shader Compilation にはUploaded shader variant to the GPU driver: ...と表示されます。 - URP はビルド前にすべてのオーバーライドを Default Volume Profile に再追加するため、ほとんどのポストプロセスのバリアントファミリーは常にビルドに含まれます。
SetShaderUserValue(uint)はMeshRendererとSkinnedMeshRendererに存在しますが、Rendererにはありません。シェーダーはunity_RendererUserValueを読み取ります。- Shader Graph 17.3:テンプレート、Unlit と Keep Lighting Variants を使用したカスタムライティング。リフレクション HLSL ノードには 17.5 が必要です。Preprocessor Directives は 6.6 で導入されます。WebGPU は 6.6 からサポートされます。Built-in RP は 6.5 から非推奨です。
参考資料
references/procedures.md:P1 から P19 まで。ライブテストと結果を含む、コピー可能なコード。references/expert-notes.md:専門家ごとの原則、観察された結果、意見の相違。references/critique.md:作業完了と判断する前の評価基準。references/gui-paths.md:GUI での同じ手順。references/sources.md:出典、認証情報、タイムスタンプ、改訂履歴。scripts/ut_shaders.py:インストール、リンター、バリアントと PSO のヘルパー、Shader Graph リーダーおよびエディター、ピクセルプローブ。scripts/AgentKit/Shaders/:ShaderJobs、ShaderLab、RendererFeatureJobs、VariantJobs、PsoJobs、ComputeJobs、GpuCostJobs、ShaderGraphJobs。scripts/Runtime/:AgentFullscreenFeature.cs、AgentPsoProbe.cs(ランタイムアセンブリ)、scripts/Shaders/(テンプレート)。