mcpField
T
texture-packing-variant-stripping

texture-packing-variant-stripping

github.com/adevra開発1644 回インストール31 週間前に更新
リポジトリ

texture-packing-variant-stripping について

モバイルや Web ビルドのテクスチャとシェーダーバリアントを管理する Unity 開発者向けの最適化リファレンスです。チャンネルパッキングと、キーワードやバリアントを削減する方法を解説します。

主な機能

  1. 01RGBA テクスチャのチャンネルパッキング
  2. 02URP マスクマップの規約
  3. 03shader_feature と multi_compile の指針
  4. 04URP 機能とキーワードの削減
  5. 05モバイルと Web 向けテクスチャ圧縮

活用シーン

  1. 01グレースケールマップをまとめてテクスチャサンプルを削減
  2. 02シェーダーバリアントとビルド容量の削減
  3. 03モバイル向けパック済みテクスチャの圧縮形式選び

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/adevra/unity-shader-agent-skills --skill texture-packing-variant-stripping

インストール後、Claude Code で/texture-packing-variant-strippingを入力して読み込まれたか確認します。

詳細

Unity モバイル向けのテクスチャパッキングとシェーダーバリアントのストリッピング

トリガー

Unity でテクスチャの最適化、チャンネルパッキング、シェーダーバリアントの肥大化、ビルドサイズ、シェーダーのコンパイル時間、シェーダーキーワードの管理を行う場合に、このスキルを使用してください。トリガーとなる語句には、「チャンネルパッキング」、「テクスチャパッキング」、「マスクマップ」、「MODS マップ」、「RMA」、「シェーダーバリアント」、「バリアントのストリッピング」、「multi_compile」、「shader_feature」、「ビルドサイズ」、「シェーダーキーワード」、「Always Included Shaders」、「IPreprocessShaders」、またはシェーダーのコンパイルが遅い、ビルドサイズが大きいという問題の報告などがあります。


テクスチャチャンネルのパッキング

チャンネルパッキングでは、複数のグレースケールマップを単一の RGBA テクスチャに格納します。これにより、モバイルにおける主なボトルネックであるテクスチャサンプル数とメモリ帯域幅の両方を削減できます。

標準的な URP パッキング規約
Mask Map (single RGBA texture):
  R = Metallic
  G = Occlusion (AO)
  B = Detail mask (or custom)
  A = Smoothness
ベストプラクティス
  1. 視覚的に最も重要なマスクを Green チャンネルに配置します。 人間の視覚は緑に最も敏感であり、ほとんどのテクスチャ圧縮形式(ETC2、ASTC、DXT)では、Green により多くのビットが割り当てられます。

  2. 関連するデータを一緒にパッキングします。 Metallic と Smoothness を常に一緒にサンプリングする場合は、同じテクスチャに配置します。

  3. パッキングしたマスクテクスチャには、リニア色空間(sRGB ではない)を使用します。 Unity では、色以外のデータ(roughness、AO、metallic、height)のテクスチャインポート設定で「sRGB」のチェックを外します。

  4. 1 回のテクスチャサンプルで 4 回分を置き換えられます。 次のようにする代わりに:

    // BAD — 4 texture samples
    half metallic = SAMPLE_TEXTURE2D(_MetallicMap, sampler_MetallicMap, uv).r;
    half ao = SAMPLE_TEXTURE2D(_AOMap, sampler_AOMap, uv).r;
    half detail = SAMPLE_TEXTURE2D(_DetailMask, sampler_DetailMask, uv).r;
    half smooth = SAMPLE_TEXTURE2D(_SmoothnessMap, sampler_SmoothnessMap, uv).r;
    

    次のようにします:

    // GOOD — 1 texture sample
    half4 masks = SAMPLE_TEXTURE2D(_MaskMap, sampler_MaskMap, uv);
    half metallic = masks.r;
    half ao = masks.g;
    half detail = masks.b;
    half smooth = masks.a;
    
応用:テレインのパッキング

Unity の Shader Graph 17.4 のテレインサンプルでは、4 レイヤーのテレインに対して、テクスチャサンプル数を12 回から 5 回に削減する高度なパッキングが紹介されています。

  • CNS パッキング:Color(RGB)+ Normal(RG → B を再構築)+ Smoothness を 1 セットに格納
  • CHNOSArray:Color、Height、Normal、Occlusion、Smoothness をパッキングしたテクスチャ配列
HLSL チャンネルパッキングヘルパー
// Pack 4 grayscale values into RGBA
half4 PackChannels(half metallic, half ao, half detail, half smoothness)
{
    return half4(metallic, ao, detail, smoothness);
}

// Reconstruct normal Z from XY (for normal map packing)
half3 UnpackNormalRG(half2 normalRG)
{
    half3 n;
    n.xy = normalRG * 2.0h - 1.0h;
    n.z = sqrt(1.0h - saturate(dot(n.xy, n.xy)));
    return n;
}

シェーダーバリアントの管理

バリアント爆発の問題

各 multi_compile キーワードによって、バリアント数は乗算的に2 倍になります。

#pragma multi_compile _ _A        → 2 variants
#pragma multi_compile _ _A _B     → 3 variants
#pragma multi_compile _ _A
#pragma multi_compile _ _B        → 2 × 2 = 4 variants
#pragma multi_compile _ _A
#pragma multi_compile _ _B
#pragma multi_compile _ _C        → 2 × 2 × 2 = 8 variants

URP に組み込まれているキーワード(影、フォグ、追加ライトなど)を含めると、単一のシェーダーで数千ものバリアントが生成されることがあります。

影響
  • ビルド時間:複雑なシェーダーでは 20 分以上
  • ビルドサイズ:シェーダーデータが 100MB 以上(WebGL では深刻な問題)
  • ランタイムメモリ:バリアント切り替えによってドローコールが 20~40% 増加
  • WebGL:シェーダーのコンパイルがメインスレッドをブロックするため、バリアントが多いほどフリーズ時間が長くなります
shader_feature と multi_compile の比較
shader_featuremulti_compile
コンパイル対象ビルド内のマテリアルで使用されるバリアントのみすべての組み合わせ
用途マテリアル固有の切り替えグローバル状態(フォグ、シャドウ)
未使用のバリアント自動的にストリッピングされます使用されていなくても含まれます
ローカル版shader_feature_local(最大 64)multi_compile_local(最大 64)
グローバル版shader_feature(最大 256)multi_compile(最大 256)

ルール:制御可能なもの(マテリアルの切り替え、機能フラグ)にはすべて shader_feature を使用します。multi_compile は、Unity がグローバルに制御するもの(フォグ、ライトマップ、インスタンシング)にのみ使用してください。

推奨される URP キーワードのストリッピング

機能を使用していない場合は、次のキーワードをストリッピングしてください。

// In an IPreprocessShaders implementation:
static readonly ShaderKeyword[] STRIP_KEYWORDS = new[]
{
    new ShaderKeyword("_ADDITIONAL_LIGHTS"),          // If using main light only
    new ShaderKeyword("_ADDITIONAL_LIGHT_SHADOWS"),   // If no additional light shadows
    new ShaderKeyword("_SHADOWS_SOFT"),               // If using hard shadows only
    new ShaderKeyword("_MIXED_LIGHTING_SUBTRACTIVE"), // If not using mixed lighting
    new ShaderKeyword("_SCREEN_SPACE_OCCLUSION"),     // If not using SSAO
    new ShaderKeyword("LIGHTMAP_SHADOW_MIXING"),      // If not mixing lightmaps + realtime
    new ShaderKeyword("_LIGHT_LAYERS"),               // If not using light layers
    new ShaderKeyword("_REFLECTION_PROBE_BLENDING"),  // If not blending reflection probes
    new ShaderKeyword("_REFLECTION_PROBE_BOX_PROJECTION"), // If not using box projection
};
URP アセットの機能のストリッピング

URP アセットの設定で未使用の機能を無効にし、それらのバリアントがコンパイルされないようにします。

  • Additional Lights → オフ(ディレクショナルライトのみを使用する場合)
  • Shadows → カスケード数を減らし、ソフトシャドウを無効にする
  • Post-Processing → 使用しない場合は無効にする
  • HDR → 必要ない場合は無効にする
  • Environment Reflections → ベイク済みの反射を使用する場合は無効にする
プラットフォーム条件付きコンパイル
// Include features only on platforms that can handle them
#if defined(SHADER_API_MOBILE) || defined(SHADER_API_GLES) || defined(SHADER_API_GLES3)
    // Mobile/WebGL: simplified path
    #define MOBILE_SHADER 1
#else
    // Desktop: full features
    #define MOBILE_SHADER 0
#endif

half4 frag(Varyings i) : SV_Target
{
    half4 color = SampleAlbedo(i.uv);
    
    #if !MOBILE_SHADER
        // Desktop-only: normal mapping, specular, etc.
        color.rgb += SampleNormalAndLight(i);
    #endif
    
    return color;
}

モバイル/Web向けテクスチャ圧縮

形式プラットフォームビット/ピクセル品質備考
ASTC 4×4Android (ES 3.0+), iOS8最良すべてのモバイル向けに推奨
ASTC 6×6Android (ES 3.0+), iOS3.56良好重要度の低いテクスチャに使用
ASTC 8×8Android (ES 3.0+), iOS2許容範囲背景や遠景のテクスチャ
ETC2Android (ES 3.0+), WebGL 2.04-8良好WebGL 2.0のデフォルト
ETC1Android (ES 2.0)4可アルファチャンネル非対応
PVRTCiOS (older)2-4ばらつきありレガシー形式。ASTCを推奨

チャンネルパックテクスチャの場合:リニアカラースペースでASTC 4×4またはETC2を使用してください。マスクマップにはPVRTCを使用しないでください。ブロック圧縮により、マスクの境界が鋭い部分に目立つアーティファクトが生じます。


最適化チェックリスト

  • すべてのグレースケールマップを、共有テクスチャのRGBAチャンネルにパック済み
  • パックしたテクスチャをLinear(sRGBではなく)としてインポート済み
  • 最も重要なマスクデータにGreenチャンネルを使用
  • マテリアルトグルにはmulti_compileではなくshader_featureを使用
  • 可能な場合はローカルキーワードを使用(shader_feature_local)
  • URP Assetで未使用のURP機能を無効化
  • Always Included Shadersリストを整理(Project Settings > Graphics)
  • 未使用キーワード向けのIPreprocessShadersストリッピングスクリプトを追加
  • ビルドログでバリアント数を確認(「Compiled N shader variants」を確認)
  • すべてのモバイルテクスチャにASTCまたはETC2圧縮を使用
  • Standard Shaderをプロジェクトから削除(Simple Litまたはカスタムシェーダーを使用)

参考資料

コメント