mobile-post-processing について
モバイルおよび WebGL 向け Unity URP のポストプロセスを追加・最適化するスキルです。画面空間エフェクトの負荷比較とシングルパス実装の指針を提供します。
主な機能
- 01エフェクトを統合して全画面 Blit を削減
- 02シングルパスのポストプロセス例を提示
- 03一般的なエフェクトのモバイル負荷を比較
- 04URP Renderer Features の利用を推奨
活用シーン
- 01モバイルゲームのポストプロセス負荷を削減
- 02URP にカスタムパスを追加
- 03制約のあるハードウェア向けの画面エフェクト選定
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ adevra/ unity-shader-agent-skills --skill mobile-post-processingインストール後、Claude Code で/mobile-post-processingを入力して読み込まれたか確認します。
詳細
Unity URP 向けモバイル後処理
トリガー
ユーザーがモバイルまたは WebGL 向けに Unity の後処理エフェクトを追加、作成、最適化したい場合に、このスキルを使用します。トリガーには、「post-processing」、「bloom」、「vignette」、「color grading」、「blur」、「outline」、「edge detection」、「chromatic aberration」、「Renderer Feature」、「Full Screen Pass」、「Blit」、「post-process mobile」、または制約のあるハードウェアでのスクリーンスペースエフェクトに関する言及が含まれます。また、ユーザーがモバイルで後処理によるフレーム落ちを報告した場合もトリガーします。
基本ルール
-
後処理の各パスでは、フルスクリーンの Blit が発生します — フレームバッファー全体をメインメモリから読み込み、書き戻します。タイルベースのモバイル GPU では、タイルメモリがフラッシュされます。ミドルレンジのモバイル端末では、パスごとに 0.5~2ms を見込んでください。
-
可能な限り、すべてのエフェクトを単一のパスにまとめてください。 Unity のデフォルトの後処理スタックでは、各エフェクトが個別のパスとして実行されます。モバイルでは、これだけで 6ms 以上かかることがあります(実測値:端末によってはビネットだけで 6ms)。代わりに、シングルパス方式を使用してください。
-
Bloom が特に必要な場合を除き、HDR を無効にしてください。 HDR はフレームバッファーの帯域幅を 2 倍にします(チャンネルあたり 16 ビット浮動小数点から 8 ビットへ)。カラーグレーディングだけが必要な場合は、LDR で適用してください。
-
Bloom は、モバイルで使用するデフォルトエフェクトの中で最もコストが高いものです。 ダウンサンプリング、ぼかし、アップサンプリングが必要になるため、複数のパスが発生します。必要な場合は、反復回数を減らし(最大 2~3 回)、半解像度のぼかしを使用し、高品質のプリフィルターを省略してください。
-
モバイルでは、モーションブラーや被写界深度を使用しないでください。 複数のパスにわたって、フラグメントごとに複数のテクスチャサンプルが必要になります。
-
URP でカスタムエフェクトを使用する場合は、Volume ベースの後処理よりも Renderer Feature を優先してください。 Renderer Feature なら、Blit を実行するタイミングと方法を直接制御できます。
シングルパス後処理のテンプレート
この方法では、ビネット、カラーグレーディング、シンプルな Bloom を 1 つのパスにまとめます。
Shader "Mobile/PostProcess_SinglePass"
{
Properties
{
_MainTex ("Source", 2D) = "white" {}
_VignetteIntensity ("Vignette Intensity", Range(0, 1)) = 0.3
_VignetteRadius ("Vignette Radius", Range(0, 1)) = 0.7
_Contrast ("Contrast", Range(0.5, 1.5)) = 1.1
_Saturation ("Saturation", Range(0, 2)) = 1.1
_Brightness ("Brightness", Range(0.5, 1.5)) = 1.0
}
SubShader
{
Tags { "RenderPipeline" = "UniversalPipeline" }
Pass
{
ZTest Always ZWrite Off Cull Off
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
CBUFFER_START(UnityPerMaterial)
half _VignetteIntensity;
half _VignetteRadius;
half _Contrast;
half _Saturation;
half _Brightness;
CBUFFER_END
TEXTURE2D(_MainTex); SAMPLER(sampler_MainTex);
struct Attributes { float4 positionOS : POSITION; float2 uv : TEXCOORD0; };
struct Varyings { float4 positionCS : SV_POSITION; float2 uv : TEXCOORD0; };
Varyings vert(Attributes v)
{
Varyings o;
o.positionCS = TransformObjectToHClip(v.positionOS.xyz);
o.uv = v.uv;
return o;
}
half4 frag(Varyings i) : SV_Target
{
half4 color = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv);
// --- Vignette (no extra texture sample) ---
half2 uvCentered = i.uv - 0.5h;
half vignette = 1.0h - saturate(
length(uvCentered) / _VignetteRadius
);
vignette = smoothstep(0.0h, 1.0h, vignette);
color.rgb *= lerp(1.0h, vignette, _VignetteIntensity);
// --- Brightness / Contrast ---
color.rgb *= _Brightness;
color.rgb = (color.rgb - 0.5h) * _Contrast + 0.5h;
// --- Saturation ---
half luminance = dot(color.rgb, half3(0.2126h, 0.7152h, 0.0722h));
color.rgb = lerp(luminance.xxx, color.rgb, _Saturation);
return saturate(color);
}
ENDHLSL
}
}
}
URP Renderer Feature(C# の設定)
後処理パスを URP に挿入するには:
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
public class MobilePostProcessFeature : ScriptableRendererFeature
{
[System.Serializable]
public class Settings
{
public Material material;
public RenderPassEvent renderPassEvent = RenderPassEvent.AfterRenderingPostProcessing;
}
public Settings settings = new Settings();
MobilePostProcessPass pass;
public override void Create()
{
pass = new MobilePostProcessPass(settings);
}
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
{
if (settings.material == null) return;
renderer.EnqueuePass(pass);
}
class MobilePostProcessPass : ScriptableRenderPass
{
Settings settings;
RTHandle tempRT;
public MobilePostProcessPass(Settings settings)
{
this.settings = settings;
this.renderPassEvent = settings.renderPassEvent;
}
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{
var cmd = CommandBufferPool.Get("MobilePostProcess");
var source = renderingData.cameraData.renderer.cameraColorTargetHandle;
// Single blit with our combined shader
Blitter.BlitCameraTexture(cmd, source, source, settings.material, 0);
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
}
}
}
モバイル向け安全なエフェクト(コスト順)
| エフェクト | コスト | モバイルでの評価 | 備考 |
|---|---|---|---|
| カラーグレーディング(LDR) | 約 0.1ms | 安全 | 純粋な演算で、追加のサンプルなし |
| ビネット | 約 0.1ms | 安全 | UV 距離の計算のみ |
| フィルムグレイン | 約 0.2ms | 安全 | UV 計算によるノイズで、テクスチャ不要 |
| シンプルなアウトライン(深度) | 約 0.5ms | 注意 | 深度テクスチャと近傍 4 点のサンプルが必要 |
| Bloom(2 回反復) | 約 1~2ms | 注意 | 半解像度を使用し、反復は最大 2 回 |
| 色収差 | 約 0.3ms | 注意 | テクスチャサンプルが 1 回ではなく 3 回 |
| ぼかし(シングルパスのボックス) | 約 0.5ms | 注意 | 4 タップのボックスブラーを使用し、ガウシアンは使用しない |
| モーションブラー | 約 3~5ms | 回避 | 速度に沿った複数のサンプルが必要 |
| 被写界深度 | 約 3~5ms | 回避 | CoC の計算と可変ブラーが必要 |
| スクリーンスペース反射 | 約 4~8ms | 回避 | スクリーンスペースでのレイマーチングが必要 |
| アンビエントオクルージョン(SSAO) | 約 2~4ms | 回避 | フラグメントごとに複数の深度サンプルが必要 |
参考リポジトリ
| リポジトリ | 目的 | 重要な理由 |
|---|---|---|
| demonixis/FastPostProcessing | シングルパスのモバイル向けポストエフェクト | モバイル向けの第一候補です。 すべてが 1 つのパスにまとまっています。 |
| TPiotr/SimpleMobilePostProcessing-Unity | ぼかしとビネット | Unity のビネットだけで 6ms かかったことをきっかけに作成されました |
| yahiaetman/URPCustomPostProcessingStack | URP Volume 対応のカスタムポストエフェクト | URP に適切に統合された 8 つのエフェクト例 |
| QianMo/X-PostProcessing-Library | 多数のエフェクト(MIT) | デスクトップ品質の参考資料です。モバイル向けに調整してください |
| GarrettGunnell/Post-Processing | モジュール式の Bloom、カラーグレーディング、エッジ | シングルパスへの集約に関する解説 |
参考資料
- Febucci:URP でのカスタムポストプロセス — https://blog.febucci.com/2022/05/custom-post-processing-in-urp/
- ARM Community:モバイルでのポストプロセス — https://community.arm.com/arm-community-blogs/b/graphics-gaming-and-vr-blog/posts/post-processing-effects-on-mobile-optimization-and-alternatives
- Unity Forum:Unity 6 のモバイル向けヒント(Bloom/HDR のベンチマーク) — https://discussions.unity.com/t/unity-6-mobile-graphics-optimization-tips-and-tricks/1593293
- Android Developer:URP アセット設定 — https://developer.android.com/develop/xr/unity/performance/urp-asset-settings
- UWA Blog:Bloom の最適化 — https://blog.en.uwa4d.com/2022/12/28/unity-mobile-game-performance-optimization-the-balance-between-graphics-performance-and-gpu-pressure/