Skip to content

jamesrochabrun/ShaderKit

Repository files navigation

ShaderKit

Buy Me A Coffee

A Swift package for composable Metal shaders and holographic UI effects in SwiftUI.

Swift 5.9+ iOS 17+ macOS 14+

Demos:

Image
butterflyShader.mov

Quick Start

Create holographic cards with composable shader effects:

import ShaderKit

HolographicCardContainer(width: 260, height: 380) {
    CardContent()
        .foil()
        .glitter()
        .lightSweep()
}

The HolographicCardContainer provides:

  • Device motion tracking via gyroscope
  • Drag gesture for manual tilt control
  • 3D rotation effects synchronized with tilt
  • Dynamic shadow based on tilt angle
  • Automatic shader context injection

Installation

Swift Package Manager

Add ShaderKit to your project via Xcode:

  1. File → Add Package Dependencies
  2. Enter the repository URL
  3. Select your version requirements

Or add to your Package.swift:

dependencies: [
    .package(url: "https://github.com/jamesrochabrun/ShaderKit.git", from: "1.0.0")
]

The package ships three library products — depend only on what you need:

  • ShaderKit — the composable Metal shader primitives and holographic containers
  • ShaderKitUI — ready-made interactive components (jelly switch, jelly button)
  • ShaderCards — Pokémon-style holographic trading cards built on ShaderKit (see ShaderCards)

⚠️ Adding this Swift Package does NOT install the trading-card skill

The library (added via SPM, above) and the agent skill are two separate things. Coding agents do not scan Swift Package checkouts for skills, so adding ShaderKit as a dependency will never install or activate the skill — there is nothing to "also install the skill" as part of adding the package.

The skill is a Claude Code plugin, installed independently of your SPM setup (once per machine):

/plugin marketplace add jamesrochabrun/ShaderKit
/plugin install shaderkit@shaderkit

Then it's available as shaderkit:trading-card. Full details in Agent skill: trading-card.

Available Shaders

ShaderKit provides 52 composable shader effects, including holographic, glass, metallic, material, seasonal, paper, and interactive 3D treatments.

Foil Effects

Effect Description Parameters
.foil() Rainbow foil overlay intensity: Double = 1.0
.invertedFoil() Inverted foil with shine intensity: Double = 0.7
.maskedFoil() Foil with masked area imageWindow: SIMD4<Float>, intensity: Double = 1.0
.foilTexture() Fine diagonal line texture imageWindow: SIMD4<Float>

Glitter & Sparkle

Effect Description Parameters
.glitter() Sparkle particle overlay density: Double = 50
.multiGlitter() Multi-scale sparkle particles density: Double = 80
.sparkles() Tilt-activated sparkle grid -
.maskedSparkle() Sparkles in masked area only imageWindow: SIMD4<Float>
.rainbowGlitter() Rainbow with luminosity blend intensity: Double = 0.7
.shimmer() Metallic shimmer effect intensity: Double = 0.7

Light Effects

Effect Description Parameters
.lightSweep() Sweeping light band -
.radialSweep() Rotating radial light sweep -
.angledSweep() Angled light sweep -
.glare() Following light hotspot intensity: Double = 1.0
.simpleGlare() Simple radial glare intensity: Double = 0.7
.edgeShine() Edge highlight effect -

Holographic Patterns

Effect Description Parameters
.diamondGrid() Diamond grid pattern intensity: Double = 1.0
.intenseBling() Maximum intensity diamond holo -
.starburst() Radial rainbow rays from center intensity: Double = 1.0
.blendedHolo() Luminance-blended rainbow intensity: Float = 0.7, saturation: Float = 0.75
.verticalBeams() Vertical rainbow beam pattern intensity: Double = 0.7
.diagonalHolo() Diagonal lines with 3D depth intensity: Double = 0.7
.crisscrossHolo() Criss-cross diamond pattern intensity: Double = 0.7
.galaxyHolo() Galaxy/cosmos with rainbow overlay intensity: Double = 0.7
.radialStar() Star pattern with radial fade intensity: Double = 0.7
.subtleGradient() Large-scale subtle gradient intensity: Double = 0.7
.metallicCrosshatch() Metallic sun-pillar with crosshatch intensity: Double = 0.7
.spiralRings() Concentric spiral rings with metallic effect intensity: Double = 0.8, ringCount: Double = 20, spiralTwist: Double = 0.5

Glass Effects

Effect Description Parameters
.glassEnclosure() Plastic/glass layer with beveled edges intensity: Double = 1.0, cornerRadius: Double = 0.05, bevelSize: Double = 0.7, glossiness: Double = 0.8
.glassSheen() Simple glass sheen overlay intensity: Double = 0.7, spread: Double = 0.5
.glassBevel() Edge bevel with visual thickness intensity: Double = 0.8, thickness: Double = 0.6
.chromaticGlass() Prismatic RGB separation at edges intensity: Double = 0.6, separation: Double = 0.4

Seasonal Effects

Effect Description Parameters
.snowfall() Falling snowflakes with twinkling stars intensity: Double = 0.8, snowDensity: Double = 0.5, starDensity: Double = 0.6, primaryColor: SIMD4<Float>, secondaryColor: SIMD4<Float>
.frozen() Icy silver shimmer with floating blue stars intensity: Double = 0.85, starDensity: Double = 0.6, shimmerIntensity: Double = 0.8, iceColor: SIMD4<Float>, starColor: SIMD4<Float>

Metallic Effects

Effect Description Parameters
.polishedAluminum() Polished aluminum with diagonal rainbow reflection intensity: Double = 0.85

Premium Material Effects

These opaque-style coatings preserve the source layer's luminance and contrast, keeping artwork and typography readable through the material.

Effect Description Parameters
.brushedTitanium() Satin titanium with directional brushing intensity: Double = 0.85
.blackChrome() Mirror-black chrome with spectral edges intensity: Double = 0.88
.roseGold() Warm brushed rose-gold plating intensity: Double = 0.82
.liquidMercury() Flowing mirror-silver folds intensity: Double = 0.84
.anodizedTitanium() Angle-reactive heat oxidation colors intensity: Double = 0.84
.damascusSteel() Wavy, layered forged-steel grain intensity: Double = 0.86
.forgedCarbon() Chopped carbon with reactive flakes intensity: Double = 0.88
.copperPatina() Copper with procedural turquoise verdigris intensity: Double = 0.82
.pearlCeramic() Opaque ceramic with pearlescent glaze intensity: Double = 0.80
.oilSlick() Dark chrome with thin-film rainbow bands intensity: Double = 0.84

Complete Trading-Card Holo Catalog

Use .tradingCardHolo(_:intensity:) with any TradingCardHoloStyle. The catalog contains 21 procedural constructions: Regular, Cosmos, Reverse, Radiant, Amazing, V, VMAX, VSTAR, Full Art, Rainbow, Rainbow Alternate, Gold Secret, Shiny, Shiny V, Shiny VMAX, five Trainer Gallery variants, and the special rainbow-secret treatment.

Each style also exposes referenceSheetName for traceable QA and migration tooling (for example, .vMax.referenceSheetName == "v-max.css").

CardContent()
    .tradingCardHolo(.vMax, intensity: 0.88)

Paper Effects

Effect Description Parameters
.water() Water caustic effect inspired by https://shaders.paper.design/water colorBack: SIMD4<Float>, colorHighlight: SIMD4<Float>, highlights: Double = 0.07, edges: Double = 0.8, waves: Double = 0.3, caustic: Double = 0.1, size: Double = 1.0, speed: Double = 1.0, scale: Double = 0.8

Experimental Effects

Effect Description Parameters
.liquidTech() Experimental liquid tech highlights intensity: Double = 0.9, speed: Double = 1.0, scale: Double = 1.0

Composing Effects

Chain multiple effects to create unique combinations:

// Holographic trading card
HolographicCardContainer(width: 260, height: 380) {
    CardContent()
        .foil()
        .glitter()
        .lightSweep()
}

// Premium gold card with starburst
HolographicCardContainer(
    width: 280,
    height: 400,
    shadowColor: .yellow,
    rotationMultiplier: 12
) {
    CardContent()
        .starburst()
        .radialSweep()
        .multiGlitter()
}

// Psychic holographic effect
HolographicCardContainer(width: 280, height: 400, shadowColor: .purple) {
    CardContent()
        .foil()
        .glitter()
        .lightSweep()
}

// Layered effect with blended holo
HolographicCardContainer(width: 260, height: 364, shadowColor: .yellow) {
    ZStack {
        BackgroundLayer()
            .blendedHolo(intensity: 0.7, saturation: 0.75)

        SparkleLayer()
            .sparkles()

        ArtworkLayer()
    }
    .angledSweep()
}

// Glass-encased collectible card
HolographicCardContainer(width: 280, height: 400, shadowColor: .white.opacity(0.3)) {
    CardContent()
        .foil()
        .glitter()
        .glassEnclosure()
}

// Winter snowfall effect
HolographicCardContainer(width: 260, height: 380, shadowColor: .cyan) {
    CardContent()
        .snowfall(
            primaryColor: SIMD4<Float>(0.3, 0.5, 0.7, 1.0),
            secondaryColor: SIMD4<Float>(0.2, 0.4, 0.6, 1.0)
        )
}

// Frozen ice magic effect
HolographicCardContainer(width: 260, height: 380, shadowColor: .cyan) {
    CardContent()
        .frozen(starDensity: 0.7, shimmerIntensity: 0.9)
}

// Polished aluminum holographic card
HolographicCardContainer(width: 260, height: 380, shadowColor: .gray) {
    CardContent()
        .polishedAluminum()
}

// Opaque premium material, optionally finished with a glass clear coat
HolographicCardContainer(width: 260, height: 380, shadowColor: .gray) {
    CardContent()
        .brushedTitanium()
        .glassSheen(intensity: 0.16, spread: 0.7)
}

// Absolute pointer tracking for physical trading-card interaction
HolographicCardContainer(
    width: 260,
    height: 380,
    rotationMultiplier: 14.3,
    interactionMode: .surfacePointer
) {
    CardContent()
        .tradingCardHolo(.vMax)
}

Custom Tilt Source

For custom tilt control without HolographicCardContainer:

CardContent()
    .shaderContext(tilt: myTiltPoint, time: elapsedTime)
    .shader(.foil(intensity: 0.8))
    .shader(.glitter(density: 75))
    .shader(.lightSweep)

Using the Builder API

Apply effects using the generic .shader() modifier:

CardContent()
    .shaderContext(tilt: tilt, time: time)
    .shader(.foil(intensity: 0.8))
    .shader(.glitter())
    .shader(.lightSweep)

Masked Effects

Apply effects only to specific areas using UV coordinates:

// Define image window bounds (UV space 0-1)
let imageWindow = SIMD4<Float>(
    0.04,   // minX
    0.11,   // minY
    0.96,   // maxX
    0.55    // maxY
)

CardContent()
    .maskedFoil(imageWindow: imageWindow)
    .maskedSparkle(imageWindow: imageWindow)
    .foilTexture(imageWindow: imageWindow)

ShaderKitUI

ShaderKitUI provides ready-to-use interactive UI components built with Metal shaders.

JellySwitch

A 3D jelly toggle switch with spring physics and sound effects. Inspired by TypeGPU's Jelly Switch.

import ShaderKitUI

struct ContentView: View {
  @State private var isOn = false

  var body: some View {
    JellySwitch(isOn: $isOn)
      .ignoresSafeArea()
  }
}

Customization options:

JellySwitch(
  isOn: $isOn,
  jellyColor: .blue,    // Custom jelly color
  darkMode: true,       // Dark ambient lighting
  soundEnabled: false   // Disable toggle sounds
)

JellyButton

A 3D jelly button with spring physics that squishes on tap and jiggles on long press.

import ShaderKitUI

struct ContentView: View {
  var body: some View {
    JellyButton {
      print("Tapped!")
    }
    .ignoresSafeArea()
  }
}

Customization options:

JellyButton(
  action: { doSomething() },
  jellyColor: .blue,    // Custom jelly color
  darkMode: true,       // Dark ambient lighting
  soundEnabled: false   // Disable press/release sounds
)

ShaderCards

A complete holographic trading-card library in the spirit of Pokémon TCG, built on ShaderKit's shaders. Every card is rendered entirely in SwiftUI — procedural artwork (paths, gradients, Canvas), real-time Metal foil, and zero image assets.

Card library gallery

  • 95-card preset library — 33 original creatures across 11 elements, trainers, energies, 22 special editions, and 21 CSS-parity holo showcases
  • 13 rarity tiers with faithful foil recipes — from matte commons to reverse holo, radiant, rainbow rare, and gold hyper rare
  • Complete modern holo catalog — all 21 active treatments from the Pokémon Cards CSS reference, plus ten premium materials (brushed titanium, black chrome, Damascus steel, oil slick…)
  • Your own images as card art — hand CardBuilder a photo and it gets the full frame, foil, and explode treatment
  • Explodable composition — every card separates into frame, artwork, chrome, and one 3D layer per shader pass
  • Card Studio — a live card builder with editable shader stacks, rarity presets, and photo import

Quick start

Add the ShaderCards product to your target, then:

import ShaderCards

// An interactive holographic card from the library — drag to tilt,
// foil and sparkles react in real time.
TradingCardView(.creature(CardLibrary.emberfox), width: 300)

// The whole library in a browsable grid.
NavigationStack { CardGalleryView() }

// A static face for lists and thumbnails (no shader passes).
CardFaceView(card: .creature(CardLibrary.tidecaller), width: 160)

Build your own card

CardBuilder is a fluent API — every stat is optional:

let card = CardBuilder(name: "Solarix", element: .fire)
  .hp(160)
  .stage(.ex)
  .rarity(.hyperRare)
  .artwork(.pyroclaw)
  .ability("Solar Core", text: "Once during your turn, heal 30 damage from this card.")
  .attack("Nova Burst", cost: [.fire, .fire], damage: "150")
  .weakness(.water)
  .flavor("Forged in the heart of a dying star.")
  .build()

TradingCardView(card)

Use any image as the artwork — it gets the full frame and foil treatment:

let photoCard = CardBuilder(name: "Photon", element: .psychic)
  .rarity(.holoRare)
  .artwork(imageData: myImageData)   // PNG / JPEG / HEIC
  .build()

Pick the face layout independently of rarity with .layout(_:):

  • .framed — classic beveled art window with the stats body
  • .fullArt — edge-to-edge artwork, stats float on scrims
  • .minimal — poster style: just the name banner, element mark, and info line
  • nil (default) — follows the rarity: ultra rare and above go full-art

Rarity → foil recipes

Rarity Treatment
Common / Uncommon Matte
Rare Subtle glass sheen
Holo Rare Vertical rainbow beams in the art window + sparkles
Reverse Holo Foil on the frame, matte art window
Double Rare (ex) Diagonal holo art + glitter
Ultra Rare (full art) Full-bleed art, etched foil + luminance-blended holo + light sweep
Illustration Rare Full-bleed art, galaxy holo + glitter
Special Illustration Rare Full-bleed art, criss-cross holo + multi-glitter
Rainbow Rare Pastel rainbow glitter over the whole card
Hyper Rare Gold-plated art, gold frame, metallic crosshatch + glitter
Radiant Criss-cross lattice in the art window
Amazing Rare Galaxy swirl + multi-glitter art window

Every recipe lives in CardFinish.finish(for:) — override any card's finish via TradingCardView(card, finish: customFinish).

The library

CardLibrary.allCards             // all 95
CardLibrary.showcase             // one spectacular card per holo treatment
CardLibrary.specialEditionCards  // 22 foil and material designs
CardLibrary.premiumMaterialCards // the 10 opaque material cards
CardLibrary.cssParityCards       // all 21 CSS-reference treatments
CardLibrary.cards(for: .fire)    // by element
CardLibrary.cards(of: .rainbowRare) // by rarity

Apply a special finish to any card:

CardBuilder(name: "Emberfox", element: .fire)
  .artwork(.emberfox)
  .finish(.goldenSweep)   // or .codex, .starburstGold, .frozenCrystal…
  .layout(.minimal)
  .build()

The ten opaque premium materials are available directly as .brushedTitanium, .blackChrome, .roseGold, .liquidMercury, .anodizedTitanium, .damascusSteel, .forgedCarbon, .copperPatina, .pearlCeramic, and .oilSlick. Complete holo constructions apply via .finish(.tradingCardHolo(.vMax)) — see the CSS parity matrix for the full reference-sheet mapping.

Explode the composition

ExplodableCardView decomposes a card into discrete layers — frame base, artwork, chrome, and one layer per shader pass — presented with ShaderKit's CardLayerExplodeContainer. Drag to orbit (angular drags rotate in Z), pinch to spread the layers, and it springs into an isometric explode on appear:

ExplodableCardView(card: .creature(CardLibrary.mindmoth), showsTransformControls: true)

Exploded layers, etched foil, and custom image art

Card Studio

An interactive builder with rarity presets, editable foil stacks for the art window and the whole card, photo import, transform controls, and a live preview that switches between the holographic card and its exploded layers:

NavigationStack { CardStudioView() }

Card Studio

Demo app

Open the package in Xcode and run the ShaderCardsDemo scheme (macOS or iOS) to browse the full library, foil showcase, special editions, the premium-material collection, and Card Studio.

Agent skill: trading-card

The repo doubles as an agent plugin bundling one skill:

  • trading-card — turn an image into a holographic Pokémon-style trading card built from ShaderKit primitives (HolographicCardContainer + a hand-tuned shader stack + glass info panels), like the cards in the demo app. Invoke /trading-card <image-path> — no interview. Needs only the ShaderKit product.

It installs through the standard plugin mechanisms — nothing writes into your project.

Claude Code:

/plugin marketplace add jamesrochabrun/ShaderKit
/plugin install shaderkit@shaderkit

Get skill updates later with /plugin marketplace update. To try the skill while working inside this repo, run claude --plugin-dir . instead.

Codex: register the marketplace with codex plugin marketplace add jamesrochabrun/ShaderKit, then install ShaderKit from the /plugins browser (or the ChatGPT desktop app's Plugins pane).

Adding the Swift package dependency alone does not activate the skill — agents don't scan package checkouts, so install the plugin once per machine.

Once installed, run /trading-card <image-path> (optionally add a short hint like "icy" or "gold legendary" to steer the look). No interview — the skill:

  1. Reads your image and invents a cool Pokémon-style creature name and stats (HP, role/title, a motto, two signature attacks with damage numbers).
  2. Randomly picks a holographic design — or maps your hint to the closest vibe (Winter Frost, Psychic Cosmic, Burst Hero, Secret Rare, …), which fixes the palette, effect stack, and glow together.
  3. Composes the card from ShaderKit primitives: your subject over a shimmering foil background with translucent "glass" info panels.
  4. Renders a single SwiftUI showcase view — tilt-interactive with live Metal effects, centered on a dark stage.
  5. Offers quick variations — reroll the design, swap the pattern effect, or tweak the stats.

Metal toolchain: ShaderKit foils are Metal shaders. On Xcode 26+ the Metal Toolchain is a separate download; if a build reports missing Metal Toolchain, run xcodebuild -downloadComponent MetalToolchain once.

Requirements

  • iOS 17.0+ / macOS 14.0+
  • Swift 5.9+
  • Xcode 15+

Note — Metal shaders in Swift packages are compiled by Xcode's build system. Build through Xcode (or xcodebuild); plain swift build produces cards without foil.

License

MIT License

About

A Swift package for composable Metal shaders and holographic UI effects in SwiftUI.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages