Grain Gradient

Soft tri-color noise gradient with film grain rendered via a SwiftUI Metal stitchable shader — two slowly drifting low-frequency value-noise samples blend three colors, and a per-frame high-frequency hash adds film grain

Free
Free with a ShipSwift account.

Copies a short instruction with your private download link. Paste it into your agent: it downloads the whole skill (the source code, the setup steps and the mistakes we already made for you) and builds the screen.

Works with

+70

What it does

Full-screen soft gradient with film grain, rendered through SwiftUI's colorEffect Metal pipeline — the poster-style hero background that reads as designed rather than flat. Two low-frequency value-noise samples, offset and scaled differently so they drift independently, drive the two blend weights between three user colors; a contrast exponent shapes those weights from a smooth pastel field to sharper color zones. A high-frequency hash on the raw pixel position, shifted every frame, adds grain that shimmers like real film and stays the same size at any noise scale.

Requires iOS 18+ / macOS 15+.

What you get

  • ✓305 lines of source code, ready to paste
  • ✓File Layout
  • ✓Source Code
  • ✓Usage
  • ✓Parameters
  • ✓Integration Checklist
  • ✓Notes / Gotchas
animationmetalshadergradientgrainbackgroundSwiftUI

Usage

// Default — warm peach / lilac / rose gradient, full-screen
ZStack {
    SWGrainGradient()
        .ignoresSafeArea()
    // Your content here
}

// Recolor — cool mint
SWGrainGradient(
    color1: .teal,
    color2: .green,
    color3: .mint
)

// As a hero background
heroContent
    .background { SWGrainGradient() }

// Clean gradient (no grain), sharper color zones
SWGrainGradient(grain: 0, contrast: 2.0)

// Demo / debug — gear button opens a live-tuning sheet.
// Requires an enclosing NavigationStack.
NavigationStack {
    SWGrainGradient(showsControls: true)
}

Parameters

ParameterTypeDefaultRangeNotes
color1Color#FFB380 (warm peach)—Base color, dominant where both noise weights are low
color2Color#B399FF (soft lilac)—Mixed in by the first noise sample
color3Color#FF8099 (rose)—Mixed in by the second noise sample
speedFloat1.00…3Multiplier on the drift time (internally slowed by 0.15)
scaleFloat1.20.2…5Spatial scale of the noise field — higher = smaller, more numerous color cells
grainFloat0.060…0.3Film-grain amplitude — 0 = clean gradient, 0.1 ≈ noticeable, 0.2 = chunky photo grain
contrastFloat1.00.1…4Exponent on the blend weights — higher = sharper color transitions, lower = smoother pastel field
showsControlsBoolfalse—Demo-only gear ToolbarItem; requires an enclosing NavigationStack

Integration Checklist

  1. Copy SWGrainGradient.swift and SWGrainGradient.metal into your Xcode target; the .metal file is compiled into the default ShaderLibrary automatically.
  2. Confirm the deployment target is iOS 18+ / macOS 15+.
  3. Use it as a ZStack background with .ignoresSafeArea() for full-bleed, or inside .background { } behind a hero section.
  4. Pick three colors close in lightness for the soft poster look; widely different colors read as blotches, so lower contrast if that happens.
  5. Keep text legible on top: the field drifts, so test your foreground against every region of the gradient (or add a scrim).

Notes / Gotchas

  • Grain is in pixel space. The grain hash uses the raw pixel position, not the scaled noise coordinates, so the grain stays film-sized at any scale and on any screen size.
  • The per-frame grain shift is wrapped. The hash input adds fmod(time * 60.0, 256.0). An unbounded time * 60 grows past float precision inside the hash within minutes and the grain collapses into flat or banded patterns; keep the wrap if you edit the shader.
  • Square cells on any aspect ratio. Positions are normalized by the shorter side of the bounding rect, so color cells don't stretch on wide or tall views.
  • The output is opaque. The shader returns alpha 1, and the base layer is color1, so the first frame already matches the gradient tone — no black flash before the shader runs.
  • Cheap per pixel. Two value-noise samples plus one hash per pixel — far lighter than the FBM-based backgrounds — so a full-screen instance is fine.
  • The argument order in the .colorEffect call must match the Metal swGrainGradient signature exactly: boundingRect, time, speed, scale, grain, contrast, color1, color2, color3.
  • When showsControls is true, the gear button is a native ToolbarItem — the call site must be inside a NavigationStack.

More in Effects and animation

Metal shaders: fields of dots that roll like waves and flow into living patterns, all drawn on the GPU.
Metal dot fields
Free
Metal shaders: fields of dots that roll like waves and flow into living patterns, all drawn on the GPU.
A deep-space starfield in Metal: glowing nebulae drift past twinkling stars.
Deep-space starfield
Free
A deep-space starfield in Metal: glowing nebulae drift past twinkling stars.
Neon outlines that bloom from the center with prism-colored edges, rendered live in Metal.
Neon outlines
Free
Neon outlines that bloom from the center with prism-colored edges, rendered live in Metal.
Colored blobs that drift, melt into one another like liquid, and blend their colors as they merge.
Liquid metaballs
Free
Colored blobs that drift, melt into one another like liquid, and blend their colors as they merge.
A 3D network graph you can spin. Tap any node and its links light up, with the details below.
3D network graph
Free
A 3D network graph you can spin. Tap any node and its links light up, with the details below.
Items orbit into a dotted ring, and payment cards fan out of a wallet as the balance rolls in.
Orbit ring and wallet
Free
Items orbit into a dotted ring, and payment cards fan out of a wallet as the balance rolls in.
A field of bright colored dots that float and shimmer across the whole screen.
Floating color dots
Free
A field of bright colored dots that float and shimmer across the whole screen.
Stacked glass panels in mirrored layers, with neon gradients flowing through them.
Glass color panels
Free
Stacked glass panels in mirrored layers, with neon gradients flowing through them.
Drag the slider and scattered points of light pull together into a perfect 3D sphere.
Dot sphere
Free
Drag the slider and scattered points of light pull together into a perfect 3D sphere.
Living patterns: a mosaic of cells that keeps reshaping, then a hypnotic color swirl.
Cells and swirl
Free
Living patterns: a mosaic of cells that keeps reshaping, then a hypnotic color swirl.
Organic noise shaders: glowing veins that pulse through the dark, then bold color blobs in constant flow.
Noise veins and blobs
Free
Organic noise shaders: glowing veins that pulse through the dark, then bold color blobs in constant flow.