Unity Tool · 2026 · v1.0.0

MINIATURE CAMERA
— TILT SHIFT

Depth-of-field post-processing effect for Unity 6 URP, built entirely on the Render Graph API.
Two visual modes (depth-based 3D DoF and screen-space linear gradient), three blur engines, auto-focus raycast, physical camera simulation, and integrated time control for miniature / stop-motion looks. Everything configurable from the inspector, the Scene View overlay, or at runtime through the scripting API.
Unity Tool C# HLSL URP Render Graph
EngineUnity 6.3+ (6000.3.x)
PipelineUniversal RP 17.x
APIRender Graph
PlatformsAll URP targets
Version1.0.0
What's inside

FEATURE OVERVIEW

Reference

DOCUMENTATION

Full API and technical reference. Use the search on the right to jump directly to a feature, method, enum, or setting. Same content as the in-package DOCUMENTATION.md, kept in sync with every release.

Overview

Miniature Camera is a depth-of-field post-processing effect for Unity 6 URP, built entirely on the Render Graph API. It supports two visual modes (depth-based 3D DoF and screen-space linear gradient), three blur algorithms, auto-focus via screen-center raycast, game speed control, and frame-rate simulation for miniature / stop-motion looks.

Everything is configurable from the inspector, the Scene View overlay, or at runtime through a clean scripting API.

Features

FeatureDetails
Blur ModesDepth-Based (3D DoF), Linear Gradient (photo tilt-shift)
Blur EnginesGaussian, Kawase, Dual Kawase
Blur QualityLow, Medium, High, Ultra
Bokeh ShapesDisabled, Circle (8-dir), Hexagonal (6-dir)
Depth CalculationAbsolute, Relative, Camera Relative, Auto (raycast)
Transition CurvesLinear, Smooth, Quadratic, Cubic
Physical CameraCircle of Confusion formula (f-stop, focal length, sensor height)
Depth ProtectionBilateral rejection to prevent color bleeding at depth edges
Render ScaleFull, Half, Quarter resolution blur pass
Time ControlGame speed (Time.timeScale) + frame-rate simulation in a single feature
PresetsScriptableObject assets, saveable and loadable from inspector or code
Scripting APIFull runtime control over focus, blur, mode, quality, and physical camera
Debug ModeColor overlay that visualizes focus zones
Scene ViewOptional effect preview in the Scene View camera

Requirements

DependencyMinimum Version
Unity6.3 (6000.3.x) or higher
Universal RP17.x (bundled with Unity 6)
Render GraphEnabled (default in Unity 6 URP)
Depth TextureEnabled in URP Renderer settings
Shader ModelSM 3.5
PlatformAll platforms supported by URP

The Render Graph API (RecordRenderGraph) is required. This package does not support the legacy Execute() path or Unity 2021 / 2022 LTS. Tested on Unity 6.3, 6.4, and 6.5.

Depth Texture must be enabled on your URP Renderer asset: select the Renderer, then under Rendering, check Depth Texture. Without it, the depth buffer is unavailable and the Depth Based blur mode cannot compute focus zones.

Installation

Via Unity Package Manager

  1. Open Window > Package Manager
  2. Click + then Add package from disk...
  3. Navigate to TiltShift/package.json
  4. Click Open

Manual

Copy the Assets/TiltShift folder into your project's Assets directory.

Setup after install

  1. Select your URP Renderer asset (usually in Settings/)
  2. Under Rendering, ensure Depth Texture is enabled
  3. Click Add Renderer Feature
  4. Select Miniature Camera Render Feature
  5. Assign the M_TiltShift material from TiltShift/Runtime/Shaders/
  6. Optionally add Miniature Camera Time Control Feature below it for game speed and frame skip

Quick Start

Minimal setup

URP Renderer asset
  Renderer Features
    Miniature Camera Render Feature         <- add this
    Miniature Camera Time Control Feature   <- optional (game speed + frame skip)

Step 1 — Add the feature via the URP Renderer inspector.

Step 2 — Assign the material: Assets/TiltShift/Runtime/Shaders/M_TiltShift.mat

Step 3 — Play. Use the inspector sliders to configure the effect.

Scripting Quick Start

using TiltShift;
using UnityEngine;
using UnityEngine.Rendering.Universal;

public class DoFController : MonoBehaviour
{
    private TiltShiftRenderFeature feature;

    void Start()
    {
        feature = GetTiltShiftFeature();
    }

    void Update()
    {
        float dist = Vector3.Distance(Camera.main.transform.position, target.position);
        feature.SetFocusCenter(dist);
    }

    private TiltShiftRenderFeature GetTiltShiftFeature()
    {
        var urpAsset = UnityEngine.Rendering.GraphicsSettings.currentRenderPipeline
            as UniversalRenderPipelineAsset;

        var field = typeof(UniversalRenderPipelineAsset)
            .GetField("m_RendererDataList",
                System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);

        var list = field?.GetValue(urpAsset) as ScriptableRendererData[];

        foreach (var data in list)
            foreach (var feat in data.rendererFeatures)
                if (feat is TiltShiftRenderFeature ts) return ts;

        return null;
    }
}

Architecture

URP Renderer Asset
  Renderer Features
    TiltShiftRenderFeature       inspector + scripting API
      TiltShiftSettings          serialized parameters
      TiltShiftPass (internal)   render graph recording
    TiltShiftTimeControlFeature  game speed + frame-rate simulation

    TiltShiftPreset              ScriptableObject assets (.asset files)

Frame execution order per camera

  1. URP renders the scene normally
  2. TiltShiftPass.RecordRenderGraph() adds blur passes to the graph
  3. URP executes the graph — the blur result replaces activeColorTexture
  4. TiltShiftTimeControlFeature optionally replaces the frame with a cached one (frame skip)
  5. URP presents the final image

TiltShiftRenderFeature

Namespace: TiltShift · Inherits: ScriptableRendererFeature · File: Runtime/TiltShiftRenderFeature.cs

The main entry point. Add this to your URP Renderer asset. It owns all effect settings and exposes the scripting API.

Tilt Shift custom inspector with collapsible sections
Custom Inspector · Mode / Focus / Blur / Debug
The custom inspector exposes every setting with collapsible sections, live sliders, and automatic clamping.

Properties

PropertyTypeDescription
settingsTiltShiftSettingsAll effect parameters, serialized to the Renderer asset.

Lifecycle

MethodWhen CalledWhat it Does
Create()On asset load, domain reloadInstantiates TiltShiftPass. Skipped if no material assigned.
AddRenderPasses()Every frame, every cameraEnqueues the pass. Skips if material is null. In Auto Focus mode, also computes the center-screen raycast (game camera only, once per frame via Time.frameCount guard) and updates autoFocusCurrentDistance.
Dispose()On destroy or domain reloadNothing to release in this class.

Scripting API — Focus (Depth Mode)

MethodSignatureDescription
SetFocusCenter(float depth)Centers the focus zone at the given depth, preserving its width.
SetFocusRange(float near, float far)Sets near and far focus boundaries in world units.
SetFocusNear(float depth)Sets the near boundary only.
SetFocusFar(float depth)Sets the far boundary only.
SetFocusTransitions(float nearSmooth, float farSmooth)Sets transition zone widths in world units.

Scripting API — Focus (Linear Gradient Mode)

MethodSignatureDescription
SetGradientCenter(float normalizedY)Vertical center of the focus band (0 to 1).
SetGradientShape(float width, float softness)Band width and edge softness (0 to 1 each).
SetGradientAngle(float degrees)Band rotation (-90 to +90 degrees).

Scripting API — Blur

MethodSignatureDescription
SetBlurSize(float h, float v)Sets horizontal and vertical blur radii independently (0 to 20 px).
SetBlurSize(float size)Sets a uniform blur radius for both axes (0 to 20 px).
SetBlurAngle(float degrees)Rotates the blur kernel (-90 to +90 degrees).

Scripting API — Mode Switches

MethodSignatureDescription
SetBlurMode(BlurMode mode)Switch between DepthBased and LinearGradient.
SetBlurEngine(BlurEngine engine)Switch between Gaussian, Kawase, and DualKawase.
SetBlurQuality(BlurQuality quality)Set sample or iteration count: Low, Medium, High, Ultra.

Scripting API — Physical Camera

MethodSignatureDescription
SetPhysicalCamera(bool enabled, float fStop = 2.8f, float focalLength = 50f, float sensorHeight = 24f)Enable or disable physical lens simulation. Only active in Depth Based mode.

Scripting API — Debug

MethodSignatureDescription
SetDebugMode(bool enabled)Toggle the focus zone color overlay.

TiltShiftTimeControlFeature

Namespace: TiltShift · Inherits: ScriptableRendererFeature · File: Runtime/TiltShiftTimeControlFeature.cs

Optional companion feature that combines game speed control (Time.timeScale) with frame-rate simulation (frame skip) for an enhanced miniature / stop-motion camera look. Both sections can be used independently or together.

Add this feature after TiltShiftRenderFeature in the renderer so the blur is included in the cached frame.

Time Control inspector with Game Speed and Frame Skip sections
Time Control · Game Speed + Frame Skip
Time Control inspector: Game Speed controls Time.timeScale, Frame Skip simulates a target frame rate.
WARNING — Time.timeScale is global.
The Game Speed section modifies Time.timeScale and optionally Time.fixedDeltaTime, which affect every gameplay system that reads scaled time: Physics (Rigidbody, collisions, joints), Animator and Animation components, Particle Systems, Coroutines using WaitForSeconds (use WaitForSecondsRealtime to bypass), NavMesh agents, Audio pitch (when tied to time), any custom script reading Time.deltaTime. Values are saved on activation and restored when the feature is disabled or destroyed.

Settings — Game Speed

PropertyTypeDefaultDescription
settings.gameSpeedEnabledboolfalseEnable game speed modification.
settings.gameSpeedfloat0.5Game speed multiplier (0.01 to 10). Applied to Time.timeScale.
settings.adjustFixedDeltaTimebooltrueScale Time.fixedDeltaTime proportionally to keep physics stable.

Settings — Frame Skip

PropertyTypeDefaultDescription
settings.frameSkipEnabledboolfalseEnable frame-rate simulation.
settings.simulatedFpsint12Target simulated frame rate (4 to 30 fps).
settings.linkFpsToGameSpeedboolfalseScale simulated FPS with game speed.

When linkFpsToGameSpeed is enabled, the effective FPS is simulatedFps * gameSpeed, clamped to [4, 30]. For example, simulatedFps = 12 and gameSpeed = 0.5 produces a 6 fps look.

How Frame Skip Works

On a render frame (once every 1/effectiveFps seconds): the current rendered image is blitted into a persistent cache (RTHandle).

On a skip frame (every other frame): the cached image is blitted back over the current frame, holding it frozen.

The GPU still renders every frame. Only the final presented image is frozen. The frame skip uses Time.unscaledTime for its interval, so it is unaffected by game speed changes.

PassData

private class PassData
{
    public RenderTargetIdentifier cacheRT;     // from RTHandle.rt, safe outside SetRenderFunc
    public TextureHandle          cameraColor; // converted to RTI inside SetRenderFunc only
    public bool                   isSkipFrame;
}

TextureHandle to RenderTargetIdentifier conversion via op_Implicit requires the Render Graph Resource Registry, which is only active inside SetRenderFunc(). Converting a TextureHandle in RecordRenderGraph() throws InvalidOperationException. Store TextureHandle fields in PassData and cast inside SetRenderFunc.

TiltShiftSettings

Namespace: TiltShift · Attribute: [Serializable] · File: Runtime/TiltShiftSettings.cs

Holds all effect parameters as serializable fields. Lives as a nested field inside TiltShiftRenderFeature and is serialized to the Renderer asset.

Tilt Shift Render Feature inspector showing all settings fields
Tilt Shift Render Feature · Inspector
All Tilt Shift Settings fields exposed on the Render Feature inspector. Depth Based mode ramps blur through depthMinSmooth, stays sharp in the focus zone, then ramps back up through depthMaxSmooth.

Mode

FieldTypeDefaultDescription
materialMaterialnullMaterial using the TiltShift/S_TiltShift shader. Required.
renderPassEventRenderPassEventBeforeRenderingPostProcessingURP injection point.
activePresetTiltShiftPresetnullCurrently assigned preset (inspector drag-and-drop).
blurModeBlurModeDepthBasedFocus zone calculation method.
blurEngineBlurEngineGaussianBlur algorithm.
blurQualityBlurQualityHighSample or iteration count.
bokehShapeBokehShapeDisabledLens bokeh shape (Gaussian only).

Focus Zone — Depth Mode

FieldTypeDefaultDescription
depthCalculationModeDepthCalculationModeRelativeHow depth boundaries are computed.
depthMinfloat5Absolute mode: near boundary in meters.
depthMinSmoothfloat5Absolute mode: near transition width in meters.
depthMaxfloat15Absolute mode: far boundary in meters.
depthMaxSmoothfloat10Absolute mode: far transition width in meters.
focusDistancefloat10Relative mode: focus center in meters.
focusNearPercentfloat-20Relative mode: near boundary as a percentage of focus distance.
focusFarPercentfloat20Relative mode: far boundary as a percentage of focus distance.
transitionPercentfloat15Relative mode: transition width as a percentage of focus distance.
focusPositionNormalizedfloat0.3Camera Relative mode: normalized focus position (0 = near, 1 = far).
focusWidthNormalizedfloat0.2Camera Relative mode: normalized focus zone width.
transitionNormalizedfloat0.1Camera Relative mode: normalized transition width.
autoFocusLayerMaskLayerMaskEverythingAuto mode: physics layers for the center-screen raycast.
autoFocusMaxDistancefloat500Auto mode: maximum raycast distance and fallback.
autoFocusSmoothingfloat2Auto mode: smoothing speed (0 = instant, 20 = very fast).
autoFocusDebugboolfalseAuto mode: draw center raycast in Scene View (green = hit, yellow = miss, red cross = hit point).
transitionCurveTransitionCurveSmoothShape of the blur gradient.
transitionSoftnessfloat1.0Softness multiplier (0.1 to 3).

Auto mode reuses the Relative mode zone parameters (focusNearPercent, focusFarPercent, transitionPercent) to define the shape of the focus zone around the dynamically computed focus distance.

Focus Zone — Linear Gradient Mode

FieldTypeDefaultDescription
gradientCenterfloat0.5Vertical band center (0 = bottom, 1 = top).
gradientWidthfloat0.2Band width in normalized screen space.
gradientSoftnessfloat0.3Edge softness.
gradientAnglefloat0Band rotation in degrees (-90 to +90).

Physical Camera

FieldTypeDefaultDescription
usePhysicalCameraboolfalseUse Circle of Confusion instead of manual blur size. Depth Based only.
fStopfloat2.8Aperture f-number (1 to 32). Lower value = stronger blur.
focalLengthfloat50Focal length in millimeters (10 to 300).
sensorHeightfloat24Sensor height in millimeters (10 to 50). 24mm = full-frame.

Blur

FieldTypeDefaultDescription
blurSizeHfloat3Horizontal blur radius in pixels (0 to 20).
blurSizeVfloat3Vertical blur radius in pixels (0 to 20).
linkBlurSizebooltrueLock H and V together in the inspector.
blurAnglefloat0Kernel rotation in degrees (-90 to +90).
blurIterationsint2Gaussian H+V pass pairs per frame (1 to 4).

Depth Protection

FieldTypeDefaultDescription
depthThresholdfloat0.5Depth discontinuity threshold (0 to 5). Gaussian + Depth Based only.
depthFallofffloat2.0Rejection sharpness (0.1 to 10).

Performance

FieldTypeDefaultDescription
renderScaleRenderScaleFullBlur pass resolution divisor.

Debug

FieldTypeDefaultDescription
debugModeboolfalseColor overlay: Green = in focus, Red = near blur, Blue = far blur.
applyToSceneViewboolfalseApply the effect in the Scene View camera.

Computed Properties

// Sample count for the current BlurQuality
// Low=3, Medium=5, High=9, Ultra=13
int GaussianSampleCount { get; }

// Iteration count for the current BlurQuality
// Low=2, Medium=3, High=4, Ultra=6
int KawaseIterations { get; }

// Circle of Confusion formula returning blur radius in pixels.
// CoC = (f * f) / (N * (d - f)) / sensorHeight * screenHeight * 0.5
float ComputePhysicalBlurSize(float focusDistanceMeters, float screenHeightPixels);

TiltShiftPreset

Namespace: TiltShift · Inherits: ScriptableObject · File: Runtime/TiltShiftPreset.cs · Create Menu: Right-click > Create > Miniature Camera > Preset

A serialized snapshot of TiltShiftSettings stored as a .asset file.

Preset dropdown with built-in presets: Default, Portrait, Landscape, Miniature, Cinematic
Preset dropdown · 5 built-in presets
Drag any .asset preset into the Preset field and it applies instantly.

Properties

PropertyTypeDescription
presetNamestringDisplay name shown in the inspector.
descriptionstringShort description (TextArea).
(all settings fields)Hidden in the inspector. Access via CaptureFrom and ApplyTo.

Methods

// Copies all values from the given settings into this preset.
void CaptureFrom(TiltShiftSettings settings);

// Applies all stored values to the given settings.
void ApplyTo(TiltShiftSettings settings);

Usage

// Save current state
var preset = ScriptableObject.CreateInstance<TiltShiftPreset>();
preset.presetName = "My Cinematic";
preset.CaptureFrom(feature.settings);
AssetDatabase.CreateAsset(preset, "Assets/MyPreset.asset");

// Apply at runtime
myPreset.ApplyTo(feature.settings);

Built-in Presets

Generate via Tools > Miniature Camera > Create Default Presets.

PresetEngineModeUse Case
DefaultGaussianDepth, RelativeBaseline starting point
PortraitGaussianDepth, RelativeCharacters, NPCs
LandscapeGaussianDepth, RelativeEnvironments, open worlds
MiniatureGaussianLinear GradientAerial views, top-down cameras
CinematicGaussianDepth, RelativeCutscenes, hero shots

TiltShiftPass (internal)

Namespace: TiltShift · Visibility: internal · Inherits: ScriptableRenderPass · File: Runtime/TiltShiftPass.cs

Handles the render graph integration. Not meant for direct use — controlled through TiltShiftRenderFeature.

Shader Property IDs

All Shader.PropertyToID() calls are cached as static readonly int fields to avoid per-frame string hashing.

ID FieldShader UniformDescription
ID_DepthMin_DepthMinNear focus boundary
ID_DepthMax_DepthMaxFar focus boundary
ID_DepthMinSmooth_DepthMinSmoothNear transition width
ID_DepthMaxSmooth_DepthMaxSmoothFar transition width
ID_BlurSizeH_BlurSizeHHorizontal blur radius
ID_BlurSizeV_BlurSizeVVertical blur radius
ID_BlurAngle_BlurAngleKernel rotation
ID_DepthThreshold_DepthThresholdDepth protection threshold
ID_DepthFalloff_DepthFalloffDepth protection falloff
ID_GradientCenter_GradientCenterLinear band center
ID_GradientWidth_GradientWidthLinear band width
ID_GradientSoftness_GradientSoftnessLinear band softness
ID_GradientAngle_GradientAngleLinear band angle
ID_KawaseOffset_KawaseOffsetKawase iteration offset
ID_TransitionSoft_TransitionSoftnessTransition softness multiplier

Shader Keywords

KeywordWhen Active
TILTSHIFT_DEBUGdebugMode == true
TILTSHIFT_LINEAR_GRADIENTblurMode == LinearGradient
TILTSHIFT_QUALITY_LOWblurQuality == Low
TILTSHIFT_QUALITY_MEDIUMblurQuality == Medium
(none)blurQuality == High (default variant)
TILTSHIFT_QUALITY_ULTRAblurQuality == Ultra
TILTSHIFT_BOKEH_CIRCLEbokehShape == Circle
TILTSHIFT_BOKEH_HEXbokehShape == Hexagonal
TILTSHIFT_CURVE_SMOOTHtransitionCurve == Smooth
TILTSHIFT_CURVE_QUADtransitionCurve == Quadratic
TILTSHIFT_CURVE_CUBICtransitionCurve == Cubic
(none)transitionCurve == Linear (default variant)

Render Graph Passes

Pass NameEngineDescription
TiltShift_DownsampleGaussian (scaled)Blit to half or quarter resolution
TiltShift_BlurH_{i}GaussianHorizontal blur pass i
TiltShift_BlurV_{i}GaussianVertical blur pass i
TiltShift_Bokeh_{i}Gaussian + BokehCombined bokeh pass i
TiltShift_UpsampleGaussian (scaled)Blit back to full resolution
TiltShift_CopyFinalAll enginesCopy blurred result to source
TiltShift_Kawase_{i}KawaseKawase blur iteration i (cloned material)
TiltShift_DKDownDual KawaseDownsample to half resolution (cloned material)
TiltShift_DKIter_{i}Dual KawaseKawase iteration at half resolution (cloned material)
TiltShift_DKUpDual KawaseUpsample to full resolution (cloned material)
TiltShift_DebugDebugSingle blit through the debug pass
TiltShift_CopyDebugDebugCopy debug result to source

Kawase and Dual Kawase passes use AddBlitPass with pre-cloned materials. At construction time, 6 permanent copies of the base material are created, each with a different _KawaseOffset value baked in. Each AddBlitPass call receives its own clone, so every iteration is genuinely independent. Without cloning, all passes would share a single material reference and read the last offset value written on CPU, making all iterations produce identical results.

Enumerations

BlurMode

public enum BlurMode
{
    DepthBased     = 0,  // Focus zone driven by the depth buffer
    LinearGradient = 1   // Screen-space focus band (photo tilt-shift look)
}

BlurEngine

public enum BlurEngine
{
    Gaussian   = 0,  // Separable Gaussian, highest quality, supports depth protection
    Kawase     = 1,  // Kawase, faster, good for mid-range hardware
    DualKawase = 2   // Dual Kawase, fastest, works at half resolution
}

BlurQuality

public enum BlurQuality
{
    Low    = 0,  // Gaussian: 3 samples  / Kawase: 2 iterations
    Medium = 1,  // Gaussian: 5 samples  / Kawase: 3 iterations
    High   = 2,  // Gaussian: 9 samples  / Kawase: 4 iterations (default)
    Ultra  = 3   // Gaussian: 13 samples / Kawase: 6 iterations
}

BokehShape

public enum BokehShape
{
    Disabled   = 0,  // Standard elliptical blur
    Circle     = 1,  // 8-direction radial sampling
    Hexagonal  = 2   // 6-direction sampling (vintage lens look)
}

DepthCalculationMode

public enum DepthCalculationMode
{
    Absolute       = 0,  // Direct world-unit values
    Relative       = 1,  // Percentages of focus distance (recommended)
    CameraRelative = 2,  // Normalized between near/far clip planes
    Auto           = 3   // Raycast from screen center (dynamic)
}

TransitionCurve

public enum TransitionCurve
{
    Linear    = 0,  // Uniform gradient
    Smooth    = 1,  // Smoothstep, natural look (recommended)
    Quadratic = 2,  // x squared, slow start then fast
    Cubic     = 3   // x cubed, very gradual edges
}

RenderScale

public enum RenderScale
{
    Full    = 1,  // Full resolution, best quality
    Half    = 2,  // Half resolution, balanced
    Quarter = 4   // Quarter resolution, fastest
}

Scripting API

Getting the Feature Reference

There is no static singleton. Locate the feature through reflection on the active renderer:

public static TiltShiftRenderFeature GetFeature()
{
    var urpAsset = UnityEngine.Rendering.GraphicsSettings.currentRenderPipeline
        as UniversalRenderPipelineAsset;
    if (urpAsset == null) return null;

    var list = typeof(UniversalRenderPipelineAsset)
        .GetField("m_RendererDataList",
            System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)
        ?.GetValue(urpAsset) as ScriptableRendererData[];

    if (list == null) return null;

    foreach (var data in list)
        if (data != null)
            foreach (var feat in data.rendererFeatures)
                if (feat is TiltShiftRenderFeature ts) return ts;

    return null;
}

Call this once in Start() and cache the result.

Focus Tracking

void Update()
{
    float distance = Vector3.Distance(cam.transform.position, target.position);
    feature.SetFocusCenter(distance);
}

Cinematic Focus Pull

IEnumerator FocusPull(float from, float to, float duration)
{
    float t = 0f;
    while (t < 1f)
    {
        t += Time.deltaTime / duration;
        feature.SetFocusCenter(Mathf.SmoothStep(from, to, t));
        yield return null;
    }
}

Preset Switching

[SerializeField] private TiltShiftPreset portraitPreset;
[SerializeField] private TiltShiftPreset landscapePreset;

void OnDialogueStart() => portraitPreset.ApplyTo(feature.settings);
void OnDialogueEnd()   => landscapePreset.ApplyTo(feature.settings);

Physical Camera

feature.SetPhysicalCamera(
    enabled:      true,
    fStop:        1.4f,   // wide open, very shallow DoF
    focalLength:  85f,    // portrait telephoto
    sensorHeight: 24f     // full-frame sensor
);

Preset System

Creating a Preset from the Inspector

  1. Click Save as Preset in the Miniature Camera inspector
  2. Choose a save location
  3. The preset is saved as a .asset file and auto-assigned

Creating a Preset from Code

var preset = ScriptableObject.CreateInstance<TiltShiftPreset>();
preset.presetName = "My Cinematic";
preset.description = "Hero shot";
preset.CaptureFrom(feature.settings);
AssetDatabase.CreateAsset(preset, "Assets/TiltShift/Presets/MyCinematic.asset");
AssetDatabase.SaveAssets();

Applying a Preset

From the inspector: drag a .asset file into the Preset field — it applies immediately. From code: myPreset.ApplyTo(feature.settings);

Built-in Presets

Located in Assets/TiltShift/Presets/. Generate them via Tools > Miniature Camera > Create Default Presets.

Shader Passes Reference

The S_TiltShift shader has 6 passes:

Pass IndexNameDescription
0BlurHHorizontal Gaussian blur, or Bokeh combined pass
1BlurVVertical Gaussian blur
2TiltShift_DebugSimple blit used for downsample, upsample, and debug copy
3KawaseKawase blur kernel, applied at varying offsets
4DualKawaseDownDual Kawase downsample from full to half resolution
5DualKawaseUpDual Kawase upsample from half back to full resolution

All passes read from _MainTex (the source texture provided by the blit or unsafe pass).

Performance Guide

Blur Engine Comparison

EngineGPU Cost (1080p, RTX 3070)Notes
Gaussian, High, 2 iterations~1.2msBest quality, supports depth protection and bokeh
Kawase, High~0.6msGood for mid-range hardware, no depth protection
Dual Kawase, High~0.3msFastest option, works at half resolution

Gaussian Iterations

Each additional iteration roughly doubles the effective blur radius:

IterationsEffective RadiusGPU Cost
1r0.6ms
2~1.4r1.2ms
3~1.7r1.8ms
4~2r2.4ms

Render Scale

ScalePixel CountGPU Multiplier
Full100%1.0x
Half25%~0.25x
Quarter6.25%~0.06x

Use Half at 4K to reduce the blur to 1080p workload with minimal visible quality loss.

Platform Recommendations

PlatformEngineQualityScaleIterations
PC high-endGaussianUltraFull3
PC mid-rangeGaussianHighFull2
ConsoleGaussianHighHalf2
Mobile high-endKawaseHighFull
Mobile mid/lowDual KawaseMediumHalf
VRDual KawaseLowQuarter
Unity profiler showing Miniature Camera GPU cost per pass
Unity Profiler · GPU timing
ProfilingSampler markers for each pass make it easy to measure cost in the Unity Profiler.

Troubleshooting

Effect not visible

  • Check that Depth Texture is enabled on the URP Renderer asset (under Rendering)
  • Check that the M_TiltShift material is assigned in the feature inspector
  • Confirm the feature is enabled in the URP Renderer asset
  • Verify blurSizeH and blurSizeV are greater than 0
  • In Depth Based mode, check that focusDistance and the near/far values cover objects in the scene
URP Renderer asset with Depth Texture checkbox enabled under Rendering
URP Renderer · Enable Depth Texture
Depth Texture must be ticked on the URP Renderer, otherwise the depth buffer is unavailable and Depth Based mode produces no effect.

Debug Mode — visualize focus zones

Toggle debugMode on the feature to paint the scene with focus-zone colors: green for the sharp focus band, red for the near blur, blue for the far blur. Invaluable to tune focusDistance and the transition widths.

Debug overlay showing green focus zone, red near blur, blue far blur
Debug Overlay · Green / Red / Blue zones
Debug overlay active: green = in focus, red = near blur, blue = far blur.

InvalidOperationException: Current Render Graph Resource Registry is not set

A TextureHandle was implicitly converted to RenderTargetIdentifier outside of SetRenderFunc(). Store TextureHandle fields in PassData and perform the cast (RenderTargetIdentifier)handle only inside the SetRenderFunc lambda.

ZBinningJob errors in the console

These are cascading URP internal errors triggered by a failing render pass. Fix the primary error above and they go away.

Blur bleeds over foreground objects

Enable Depth Protection and raise depthThreshold (try 1.0 to 2.0). This only works with BlurEngine.Gaussian and BlurMode.DepthBased.

Bokeh shape not visible

Bokeh requires blurEngine == Gaussian. The radius also needs to be at least 8 pixels to show the shape clearly.

Kawase Ultra looks worse than Kawase Low

This was a bug where _KawaseOffset was set during RecordRenderGraph but all passes shared the same material reference, so every pass ended up using the last offset value. The fix uses 6 pre-cloned materials, each with a different _KawaseOffset baked in at construction time. Update to the latest version to get the fix.

Frame Skip stuttering feels too regular

Add a small random variation from code:

timeControlFeature.settings.simulatedFps = Mathf.RoundToInt(12f + Random.Range(-1f, 1f));

Time Control: game feels broken after enabling Game Speed

The Game Speed section of TiltShiftTimeControlFeature modifies Time.timeScale, which is global. Every system reading Time.deltaTime will slow down: physics, animations, particles, coroutines (WaitForSeconds), NavMesh, etc. This is by design for the miniature effect, but it will break gameplay that expects normal speed. Use during non-interactive sequences or dedicated cinematic cameras only. If the value gets stuck after a crash, reset it manually: Time.timeScale = 1f; Time.fixedDeltaTime = 0.02f;.

Time Control: fixedDeltaTime not restored

If adjustFixedDeltaTime is on and the application crashes or the domain reloads unexpectedly while the feature is active, Time.fixedDeltaTime may stay at a scaled value. Add a safety reset:

[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
static void ResetTime()
{
    Time.timeScale      = 1f;
    Time.fixedDeltaTime = 0.02f;
}

Scene View shows the effect

Set settings.applyToSceneView = false. This is the default. The feature checks cameraData.isSceneViewCamera and skips if the setting is off.

Changelog

v1.0.0

  • Gaussian, Kawase, Dual Kawase blur engines
  • Depth Based and Linear Gradient blur modes
  • Absolute, Relative, Camera Relative, and Auto depth calculation modes
  • Auto FocusDepthCalculationMode.Auto raycasts from screen center to dynamically focus on whatever the camera is looking at. Works with perspective, orthographic, zoom, and camera movement. Configurable layer mask, max distance, and smoothing.
  • Physical camera simulation using the Circle of Confusion formula
  • Depth protection with bilateral sample rejection
  • Bokeh shapes: Circle and Hexagonal
  • Transition curves: Linear, Smooth, Quadratic, Cubic
  • Render Scale at Full, Half, and Quarter resolution
  • Time Control — unified Renderer Feature combining game speed (Time.timeScale, 0.01x–10x) and frame-rate simulation in a single inspector, with fixedDeltaTime scaling and global-state warnings
  • Link to Game Speed option that automatically scales simulated FPS with game speed
  • Time Control section in the Scene View overlay with game speed and frame skip controls
  • Preset system with ScriptableObject assets and inspector buttons (5 built-in presets)
  • Full scripting API with automatic value clamping
  • Custom inspector with collapsible sections
  • Scene View overlay for quick access to common settings
  • Debug mode with focus zone color overlay
  • Auto Focus debug raycast visualization in Scene View
  • Unity 6 URP Render Graph support via RecordRenderGraph
  • Kawase and Dual Kawase passes use pre-cloned materials with baked _KawaseOffset values