jamesrochabrun/shaderkit
alt="Buy Me A Coffee" width="200">
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:
- File → Add Package Dependencies
- Enter the repository URL
- Select your version requirements
Or add to your Package.swift:
dependencies: [
.package(url: "https://github.com/jamesrochabrun/ShaderKit.git", from: "1.0.0")
]Available Shaders
ShaderKit provides 37 composable shader effects across 9 categories.
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 |
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()
}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
)Requirements
- iOS 17.0+ / macOS 14.0+
- Swift 5.9+
- Xcode 15+
License
MIT License
Package Metadata
Repository: jamesrochabrun/shaderkit
Default branch: main
README: README.md