跳到正文

krispuckett

SwiftUIShaders

41 hand-curated drop-in SwiftUI Metal shader effects — holographic foil, kaleidoscope, magnetic fields, glitch, neon edges and more. Typed View modifiers, agent-friendly docs.

README 已保存到本站,可直接阅读

Documentation snapshot

README 快照

这篇是英文原文

下面正文是项目自己的英文 README。想读全文就用浏览器自带的整页翻译: Chrome / Edge 点地址栏右侧的翻译图标,或用右键菜单里的「翻译成中文」; 手机浏览器一般在菜单里。

本页保存的是公开项目资料快照,阅读过程不需要连接 GitHub。

SwiftUIShaders

41 SwiftUI Metal shaders. Holographic foil, kaleidoscope mandalas, magnetic fields, glitch, neon edges, and a pile more. Each one is a [[ stitchable ]] Metal function with a typed SwiftUI View modifier wrapped around it, so dropping one onto a view is a single line.

These started as a hidden shader lab inside Epilogue, my reading app. I built way more than I ever shipped, so I pulled the good ones out to share. Every shader here got rendered on a real book cover and kept only if it actually looked good. The duds, the washed-out ones, and the ones that only work on a blank gradient got cut. What’s left is the set I’d reach for myself.

Drop them into your own project and mess around. They’re also built to hand straight to a coding agent like Claude Code or Codex. If one sparks an idea, point your agent at AGENTS.md and let it riff.

Want to dial them in by eye? Hand the repo to your agent and ask it to build a slider-based tuning tool. Everything it needs is in Docs/parameters.json, and the recipe is in AGENTS.md. Tune against your own content, copy the line it spits out, paste it into your code.

The bcs_ prefix is just the shader namespace. Nothing here is wired to Epilogue’s actual app code.

Requirements

  • iOS 17+ / macOS 14+ / tvOS 17+ / visionOS 1+
  • Xcode 15+ (the Metal toolchain compiles the shaders into the package’s default.metallib)

One gotcha: build with Xcode or xcodebuild, not bare swift build. SwiftPM’s command-line driver on macOS doesn’t run the Metal toolchain, so Bundle.module and default.metallib never get produced. In Xcode it just works.

Install

Swift Package Manager. In Xcode, go to File ▸ Add Package Dependencies and point it at this repo’s URL. Or add it in Package.swift:

.package(url: "https://github.com/krispuckett/SwiftUIShaders.git", from: "1.0.0")

Then add SwiftUIShaders to your target’s dependencies.

Quick start

import SwiftUI
import SwiftUIShaders

struct ContentView: View {
    var body: some View {
        Image("book-cover")
            .resizable()
            .scaledToFit()
            .bcsHolographic(intensity: 0.6, scale: 12, speed: 1.2)  // animated, self-driving
    }
}

Every shader is a View modifier. The animated ones run themselves with TimelineView(.animation), so there’s no timer for you to babysit. Every parameter has a sensible default, so .bcsKaleidoscope() works on its own.

Text("Chapter One")
    .font(.largeTitle)
    .bcsChromaticSplit(spread: 8, angle: .pi / 4)

bookCover
    .bcsAurora()             // ambient animated glow

myView
    .bcsEmboss(strength: 3)  // static relief

One heads up: these want real content. Photos, book covers, illustrations, text. Drop one on a flat single-color fill and the displacement and edge effects have nothing to grab onto.

How it works (conventions)

Each wrapper applies one Metal layerEffect. The mapping is uniform:

Shader argumentSupplied by the wrapper
position, layerSwiftUI (automatic)
sizeThe view’s pixel size, from GeometryProxy
timeElapsed seconds, from TimelineView(.animation) (animated shaders only)
interaction point (e.g. touchPos)A UnitPoint (0…1) you pass, converted to pixels
everything elseTyped Float parameters with defaults

Every method also takes maxSampleOffset: (default 64×64). Raise it if a heavy displacement effect looks clipped at the edges. Lower it for a small perf win on cheap effects.

The shaders

37 animate. 4 are static (bcsEmboss, bcsFrosted, and the two interaction-driven ripples). Ranges in parentheses are the sweet spots. The defaults are tuned values that look good out of the box, so you can call any of these with no arguments and get something real.

ShaderTypeParameters
.bcsAurora: Auroraanimatedintensity (0–1), bands (1–8), speed (0.3–3), colorShift (0–1)
.bcsBlackHole: Black Holeanimatedmass (0.05–0.5), spin (0–5), distortion (10–200), ringBrightness (0–2)
.bcsChromaticSplit: Chromatic Splitanimatedspread (0–30), angle (0–6.28), edgeOnly (0–1), animate (0–1)
.bcsDatamosh: DatamoshanimatedblockCorruption (0–1), smearAmount (0–60), colorBleed (0–1), glitchRate (0.5–5)
.bcsDisintegrate: Disintegrateanimatedthreshold (0–1), edgeWidth (0.05–0.3), driftAmount (0–50), direction (0–6.28)
.bcsDuochrome: Duochromeanimatedintensity (0–1), hue1 (0–1), hue2 (0–1), contrast (0.5–2)
.bcsEcho: Echo / GhostanimatedechoCount (2–8), spread (5–50), direction (0–6.28), fade (0.3–0.9)
.bcsEmboss: Emboss / Reliefstaticstrength (0–5), angle (0–6.28), mixAmount (0–1)
.bcsEtherealAura: Ethereal Aura (v2)animatedauraWidth, auraIntensity, pulseSpeed, distortion, hueShift
.bcsFrosted: Frosted GlassstaticfrostAmount (0–1), grainSize (1–20), clearRadius (0–1), clearSoftness (0–1)
.bcsGeometricWarp: Geometric WarpanimatedspiralTight (1–8), zoomRepeat (0.3–2), rotation (0–6.28), blend (0–1)
.bcsGlitch: Glitchanimatedintensity (0–1), blockSize (2–50), scanLines (0–1), colorShift (0–20)
.bcsGravityWells: Gravity WellsanimatedwellStrength (10–200), wellCount (1–5), orbitSpeed (0.1–3), warpFalloff (0.5–5)
.bcsHeatShimmer: Heat Shimmeranimatedamplitude (0–20), frequency (1–30), speed (0.5–5), verticalBias (0–1)
.bcsHolographic: Holographic / Prismaticanimatedintensity (0–1), scale (1–20), speed (0.1–3), angleOffset (0–6.28)
.bcsInkBleed: Ink Bleed / Domain WarpanimatedwarpStrength (0–50), scale (1–10), speed (0.1–2), detail (2–8)
.bcsKaleidoscope: Kaleidoscopeanimatedsegments (2–16), rotation (0–6.28), zoom (0.5–3), animateSpeed (0–2)
.bcsLiquidChrome: Liquid Chromeanimateddistortion (0–30), chromeIntensity (0–1), flowSpeed (0.1–3), reflectionScale (1–10)
.bcsLiquidMirror: Liquid MirroranimatedmirrorAxis (0.3–0.7), ripple (2–30), speed (0.5–3), depth (0–1)
.bcsLiveRipple: Live Rippleanimatedamplitude (0–30), frequency (5–60), speed (1–10), damping (0.5–5), ringCount (1–5)
.bcsMagneticField: Magnetic FieldanimatedfieldStrength (5–80), lineCount (3–20), fieldTurbulence (0–1), polarity (0–1)
.bcsMelt: MeltanimatedmeltAmount (0–100), dripScale (1–15), speed (0.1–3), heat (0–1)
.bcsMorphBreathe: Morph BreatheanimatedbreatheDepth (5–50), breatheRate (0.3–3), warpComplexity (1–8), organic (0–1)
.bcsNeonEdge: Neon EdgeanimatededgeStrength (1–10), glowAmount (0–2), colorCycle (0–3), mixOriginal (0–1)
.bcsPixelateMosaic: Pixelate MosaicanimatedpixelSize (4–60), bevel (0–1), animateAssemble (0–1), gap (0–0.3)
.bcsPixelateStorm: Pixelate StormanimatedpixelSize (2–40), stormAmount (0–1), swirl (0–3), pulse (0–3)
.bcsPlasma: Plasmaanimatedintensity (0–1), scale (1–10), speed (0.5–5), colorMode (0–1)
.bcsPulse: Pulse / Heartbeatanimatedamplitude (0–30), bpm (30–180), sharpness (1–10), glowIntensity (0–1)
.bcsRefractLens: Refract Lens (Interactive)statictouchPos (UnitPoint), lensRadius (0.1–0.5), refraction (1–3), aberration (0–15), wobble (0–1)
.bcsShatter: ShatteranimatedshardCount (3–30), explode (0–1), rotationAmt (0–3), edgeGlow (0–2)
.bcsShatterGlass: Shatter GlassanimatedcrackDensity (3–15), glassRefraction (0–20), prismStrength (0–1), shatterSpread (0–1)
.bcsShockwave: ShockwaveanimatedwaveSpeed (50–500), ringWidth (5–60), strength (5–80), repeatRate (0.5–5)
.bcsSmokeReveal: Smoke RevealanimatedsmokeAmount (0–1), smokeScale (2–10), windSpeed (0.5–3), smokeTurb (0.5–3)
.bcsSolarize: Solarizeanimatedthreshold (0.2–0.8), curveIntensity (0–3), colorSeparation (0–1), animate (0–1)
.bcsThermal: Thermalanimatedintensity (0–1), shimmer (0–15), noiseSpeed (0.5–3), paletteShift (0–1)
.bcsTopographic: TopographicanimatedlineCount (5–40), lineWidth (0.01–0.15), colorize (0–1), animate (0–1)
.bcsTouchRipple: Touch RipplestatictouchPos (UnitPoint), touchAge, amplitude (0–30), frequency (5–40), speed (50–500), decay (0.5–4)
.bcsUnderwaterCaustics: Underwater CausticsanimatedcausticScale (2–15), causticIntensity (0–2), waterDistortion (0–30), waterDepth (0–1)
.bcsVortex: Vortex SpiralanimatedtwistAmount (0–10), radius (0.1–1), speed (0.1–3), falloff (0.5–5)
.bcsWavePool: Wave Poolanimatedamplitude (0–25), wavelength (5–40), speed (0.5–5), complexity (1–6)
.bcsWormhole: Wormholeanimateddepth (1–8), speed (0.3–3), twist (0–5), radius (0.1–0.5)

Interaction-driven shaders

bcsTouchRipple and bcsRefractLens take a touchPos: UnitPoint. Feed them a drag location for a touch-reactive effect, and use a GeometryReader to normalize the point:

@State private var touch: UnitPoint = .center

GeometryReader { geo in
    myView
        .bcsRefractLens(touchPos: touch, lensRadius: 0.3)
        .gesture(DragGesture(minimumDistance: 0).onChanged { v in
            touch = UnitPoint(x: v.location.x / geo.size.width,
                              y: v.location.y / geo.size.height)
        })
}

Performance notes

  • These are GPU fragment effects. Most are cheap, but the blur and displacement-heavy ones (bcsFrosted, bcsShatterGlass, bcsMagneticField) sample a lot of neighbors, so profile before you stack them on big, fast-scrolling views.
  • Animated shaders re-render every frame while they’re on screen. Don’t leave dozens running off-screen.
  • half-precision is used throughout for speed. Expect a little banding at extreme parameter values.

License

MIT. See LICENSE. Use them, ship them, remix them. Attribution’s appreciated, never required.

Official distribution

获取与安装

暂未发现可确认的官方软件包地址

当前 README 快照没有出现 npm、PyPI、Crates.io、pub.dev 等官方包页链接。本站不会根据仓库名称猜测下载地址。

本站不托管项目文件;需要安装时,请以项目维护者发布的官方文档为准。

使用前核验

本站保存公开资料用于阅读,不代表安全审计或功能背书。安装前请核对许可证、依赖来源和发布签名,不要直接运行来源不明的二进制文件或高权限脚本。