agentsclimarketplace

Mobile post processing

Skill adevra/unity-shader-agent-skills/skills/mobile-post-processing

Curated agent skills for Unity shader development targeting mobile GPUs and WebGL browsers.

Install
npx -y skills add adevra/unity-shader-agent-skills --skill mobile-post-processing

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 8 stars8 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Single-pass post-processing, URP Renderer Features, and mobile-safe screen effects for Unity

SKILL.md

8.8 KB, as published. Nobody here has run it

Mobile Post-Processing for Unity URP

TRIGGER

Use this skill when the user wants to add, create, or optimize post-processing effects in Unity for mobile or WebGL targets. Triggers include: "post-processing", "bloom", "vignette", "color grading", "blur", "outline", "edge detection", "chromatic aberration", "Renderer Feature", "Full Screen Pass", "Blit", "post-process mobile", or any mention of screen-space effects on constrained hardware. Also trigger when the user reports post-processing is causing frame drops on mobile.


CORE RULES

  1. Every post-processing pass costs a full-screen blit — reading the entire framebuffer from main memory and writing it back. On tiled mobile GPUs, this flushes tile memory. Budget 0.5–2ms per pass on mid-range mobile.

  2. Combine all effects into a single pass whenever possible. Unity's default post-processing stack runs each effect as a separate pass. On mobile, this alone can add 6ms+ (measured: vignette alone = 6ms on some devices). Use a single-pass approach instead.

  3. Disable HDR unless you specifically need Bloom. HDR doubles framebuffer bandwidth (16-bit float vs 8-bit per channel). If you only need color grading, apply it in LDR.

  4. Bloom is the most expensive default effect on mobile. It requires downsampling, blurring, and upsampling — multiple passes. If you need it, reduce iterations (2–3 max), use a half-resolution blur, and skip the high-quality prefilter.

  5. Never use Motion Blur or Depth of Field on mobile. They require multiple texture samples per fragment across multiple passes.

  6. Prefer Renderer Features over Volume-based post-processing for custom effects in URP. Renderer Features give you direct control over when and how the blit happens.


SINGLE-PASS POST-PROCESSING TEMPLATE

This approach combines vignette + color grading + simple bloom in one pass:

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# SETUP)

To inject the post-processing pass into 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);
        }
    }
}

MOBILE-SAFE EFFECTS (COST RANKING)

EffectCostMobile VerdictNotes
Color grading (LDR)~0.1msSAFEPure math, no extra samples
Vignette~0.1msSAFEUV distance calculation only
Film grain~0.2msSAFENoise from UV math, no texture
Simple outline (depth)~0.5msCAUTIONRequires depth texture + 4 neighbor samples
Bloom (2-iteration)~1-2msCAUTIONUse half-res, 2 iterations max
Chromatic aberration~0.3msCAUTION3 texture samples instead of 1
Blur (single-pass box)~0.5msCAUTIONUse 4-tap box blur, never Gaussian
Motion blur~3-5msAVOIDMultiple samples along velocity
Depth of field~3-5msAVOIDCoC calculation + variable blur
Screen-space reflections~4-8msAVOIDRay marching in screen space
Ambient occlusion (SSAO)~2-4msAVOIDMultiple depth samples per fragment

REFERENCE REPOS

RepoPurposeWhy It Matters
demonixis/FastPostProcessingSingle-pass mobile post-FXGo-to for mobile. Everything in one pass.
TPiotr/SimpleMobilePostProcessing-UnityBlur + vignetteCreated because Unity's vignette cost 6ms alone
yahiaetman/URPCustomPostProcessingStackURP Volume-compatible custom FX8 example effects with proper URP integration
QianMo/X-PostProcessing-LibraryDozens of effects (MIT)Desktop-quality reference; adapt for mobile
GarrettGunnell/Post-ProcessingModular bloom/grade/edgeNotes on single-pass condensation

SOURCES

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.