import { Expr, GpuFragmentParams, KitTexture } from '../contract'; import { d } from './index'; /** Tap count of the motion-blur gather (one `textureSample` each — see `blur.unrolledTapGather`). */ export declare const MOTION_BLUR_TAP_COUNT = 32; /** Normalized Gaussian tap weights, computed at JS time — no `exp()` per tap per pixel. */ export declare const MOTION_BLUR_WEIGHTS: number[]; /** * Sample coordinate for one linear-blur tap. `tapT ∈ [-0.5, 0.5]` is the centered tap position * ((i/31)-0.5). The blur vector is the (aspect-corrected) direction × intensity, normalised to the * viewport and doubled. `angleDeg` is degrees (transformAngle is identity-degrees), so * the body converts. All scalar infix (avoids vector `.div`). */ export declare const linearBlurTapCoord: import('typegpu').TgpuFn<(uv: d.Vec2f, angleDeg: d.F32, intensity: d.F32, viewport: d.Vec2f, tapT: d.F32) => d.Vec2f>; /** * Sample coordinate for one orbit-blur tap: rotate the (aspect-corrected) offset from `center` by * `(tapIndex − 15.5) × angleStep`, where `angleStep = intensity·0.005 / 31`. Centering the 32-tap * sweep on the source pixel (taps at ±0.5·step, ±1.5·step, …) keeps the blurred image aligned with * the sharp one — a one-sided sweep visibly counter-rotated content by half the blur angle * (pre-2026-08 behavior; deliberately corrected). `center` is the ALREADY-transformed * prop value (transformPosition stores `(x, 1 - y)`), so `1.0 - center.y` recovers the authored y. * * Each tap's rotation is computed DIRECTLY (`cos/sin((tapIndex − 15.5)·angleStep)`) rather than via * a stateful recurrence — no accumulated f32 drift and no loop-carried state. */ export declare const angularBlurTapCoord: import('typegpu').TgpuFn<(center: d.Vec2f, intensity: d.F32, uv: d.Vec2f, aspect: d.F32, tapIndex: d.F32) => d.Vec2f>; /** * Sample coordinate for one zoom-blur tap: scale the offset from `center` by * `scale = 1 + radius·(tapIndex/31)` (radius = intensity·0.01), pulling near-center samples out and * far samples in for the radial streak. `center` is the ALREADY-transformed prop value * (transformPosition stores `(x, 1 - y)`), so `1.0 - center.y` recovers the authored y. * * The x offset is aspect-corrected (×aspect) then un-corrected (÷aspect) at the end; the two cancel * algebraically but are kept in that exact op order so the f32 rounding matches. Pure. */ export declare const zoomBlurTapCoord: import('typegpu').TgpuFn<(center: d.Vec2f, intensity: d.F32, uv: d.Vec2f, aspect: d.F32, tapIndex: d.F32) => d.Vec2f>; /** The three tap trajectories a motion blur can follow. */ export type MotionBlurPathKind = 'linear' | 'orbit' | 'zoom'; export interface MotionBlurGatherArgs { /** The path anchor: `linear` → the angle in degrees; `orbit`/`zoom` → the transformed center. */ focus: Expr; /** Blur intensity (the shaders' 0–100 range). */ amount: Expr; uv: Expr; aspect: Expr; viewportSize: Expr; } /** * The 32-tap Gaussian motion-blur gather: `Σ sample(tapCoord(i)) · weight(i)`, left-folded in tap * order (float addition is not associative — the fold order is part of the result). One * `texture.sample()` per tap with no control flow, the only legal shape for textureSample in a * fragment; the linearClamp sampler clamps out-of-range taps. */ export declare function motionBlurGather(kind: MotionBlurPathKind, args: MotionBlurGatherArgs, sample: (coord: Expr) => Expr): Expr; /** * One decorrelated hash per pixel → a random offset in the [-1,1]² unit square, scaled to pixels by * `intensity` and normalised by the viewport (so the grain size is DPR-stable). Returns the * displaced sample coordinate. `viewport` is `_sys.viewportSize` (device pixels). The seed is * ~thousands, where the old sin-fract hash streaks on iOS Metal (low-precision large-argument sin) * — hence the integer bitcast hash. Vector ops fluent, scalar infix. */ export declare const diffuseBlurUV: import('typegpu').TgpuFn<(uv: d.Vec2f, intensity: d.F32, viewport: d.Vec2f) => d.Vec2f>; export interface ScatterGatherArgs { uv: Expr; /** Displacement radius in pixels. */ amount: Expr; viewportSize: Expr; /** Compile-time edge mode (transformEdges value); `stretch` relies on the clamping sampler. */ edgeMode: number; sample: (coord: Expr) => Expr; } /** The scatter gather: sample the child once at the hash-displaced coordinate, with edge handling. */ export declare function scatterGather(args: ScatterGatherArgs): Expr; export declare const DROP_SHADOW_TAP_WEIGHTS: number[]; /** The shadow's screen UV: offset the sample by the compass-angle direction × distance (X divided by * aspect so the offset covers equal pixel distance in both axes). Pure. */ export declare const dropShadowUV: import('typegpu').TgpuFn<(uv: d.Vec2f, viewport: d.Vec2f, angle: d.F32, distance: d.F32) => d.Vec2f>; /** `uv + (ox, oy) · blurRadius / viewport` — one separable-blur tap offset in UV space. Pure. */ export declare const dropShadowTapUV: import('typegpu').TgpuFn<(uv: d.Vec2f, viewport: d.Vec2f, blurRadius: d.F32, ox: d.F32, oy: d.F32) => d.Vec2f>; /** * The final drop-shadow composite in PREMULTIPLIED space (the child RTT is premultiplied) — the * gather's caller unpremultiplies the return. `cutout` is a runtime 0/1 flag selected via * `std.select`. Normal: original content OVER the shadow. Cutout: shadow only, with the original * silhouette punched out. `shadowColor` is the vec4 rgba tint. Pure. */ export declare const dropShadowComposite: import('typegpu').TgpuFn<(originalColor: d.Vec4f, shadowColor: d.Vec4f, shadowAlpha: d.F32, cutout: d.F32) => d.Vec4f>; export interface SilhouetteBlurArgs { /** Where the silhouette is read from (e.g. the shadow-offset UV). */ at: Expr; /** The screen UV the vertical pass reads back at. */ uv: Expr; viewportSize: Expr; /** Blur radius in pixels. */ blurRadius: Expr; /** Sample the child RTT (premultiplied). */ sample: (coord: Expr) => Expr; convertToTexture: GpuFragmentParams['convertToTexture']; } /** * Two-pass separable Gaussian blur of the child's ALPHA silhouette (the frozen 13-tap table), * running INLINE in the fragment: horizontal pass at `at` → an intermediate RTT * (`convertToTexture` of the pass's Expr) → vertical pass at `uv`. Returns the blurred coverage * scalar. */ export declare function silhouetteBlur(args: SilhouetteBlurArgs): Expr; /** One neighbour sample UV: uv + (dirX, dirY) × one device pixel (pixelSize = 1 / viewportSize). * Pure. */ export declare const sharpnessTapUV: import('typegpu').TgpuFn<(uv: d.Vec2f, viewport: d.Vec2f, dirX: d.F32, dirY: d.F32) => d.Vec2f>; /** Sharpening kernel: center × (1 + 4·amount) − neighbours × amount, clamped to [0,1]. Operates on * the premultiplied samples; alpha is taken from the centre tap (neighbour alpha is unused — RGB * only). The caller unpremultiplies the result. */ export declare const sharpnessCompose: import('typegpu').TgpuFn<(center: d.Vec4f, top: d.Vec4f, bottom: d.Vec4f, left: d.Vec4f, right: d.Vec4f, amount: d.F32) => d.Vec4f>; export interface SharpenGatherArgs { uv: Expr; viewportSize: Expr; /** Kernel strength; 0 collapses to identity (centerWeight 1, neighbourWeight 0). */ amount: Expr; /** Sample the child RTT (premultiplied). */ sample: (coord: Expr) => Expr; } /** The sharpen gather: sample the centre + 4 orthogonal one-pixel neighbours and run the * unsharp-mask kernel over them, in premultiplied space. */ export declare function sharpenGather(args: SharpenGatherArgs): Expr; /** * Quantise the UV to a pixel grid + build the gap/roundness cell mask. * * Returns vec3(sampleUV.x, sampleUV.y, mask): the cell-center-ish sample coordinate (this samples * the floored cell origin, not the center) packed with the rounded-rect cell coverage mask. * `scale` counts pixels along the LONGEST side; the shorter side scales by aspect (clamped ≥ 1). * Floor-quantise for the sample UV, fract-local coords for the SDF. Pure. */ export declare const pixelateSample: import('typegpu').TgpuFn<(uv: d.Vec2f, aspect: d.F32, scale: d.F32, gap: d.F32, roundness: d.F32) => d.Vec3f>; export interface PixelateGatherArgs { uv: Expr; aspect: Expr; /** Pixel count along the longest edge (higher = smaller pixels). */ scale: Expr; /** Space between cells as a fraction of cell size. */ gap: Expr; /** Corner roundness of each cell (0 = square, 1 = circle). */ roundness: Expr; /** Sample the child RTT and unpremultiply — the scaffold's straight-alpha sampler. */ sampleStraight: (coord: Expr) => Expr; } /** The pixelate gather: one straight-alpha sample at the quantised cell coordinate, with the * rounded-rect cell mask applied to the alpha. Returns STRAIGHT alpha. */ export declare function pixelateGather(args: PixelateGatherArgs): Expr; /** * The distorted sample coordinate for a screen UV. `tileCount` applies to the LONGEST side; the * shorter side scales by aspect. The grid is rotated in aspect-corrected square space; the * refraction offset pushes each fragment away from its tile centre (roundness fades that off * radially). Vector ops fluent, scalar ops infix. Pure. */ export declare const glassTilesUV: import('typegpu').TgpuFn<(uv: d.Vec2f, aspect: d.F32, intensity: d.F32, baseTileCount: d.F32, rotationDegrees: d.F32, roundnessAmount: d.F32) => d.Vec2f>; export interface GlassTilesUVArgs { uv: Expr; aspect: Expr; intensity: Expr; tileCount: Expr; rotation: Expr; roundness: Expr; } /** The tile-distorted sample coordinate (shared by the fragment and the analytic remap). */ export declare function glassTilesDistortUV(args: GlassTilesUVArgs): Expr; /** * The glass-tiles fragment: sample the child RTT at the tile-distorted coordinate with the default * clamp-to-edge sampler (no edge modes), then unpremultiply. Catmull-Rom reconstruction: each tile * magnifies its slice of the content, so a single bilinear tap would facet any hard edge underneath. * Returns STRAIGHT alpha. */ export declare function glassTilesFragment(args: GlassTilesUVArgs & { texture: KitTexture; }): Expr; /** The analytic remap coordinate: the same tiled-refraction bend, clamped to [0,1] to match the * fragment path's clamp sampler (edgeClampUV clamps to `vec2(0)`..`vec2(1)`). */ export declare function glassTilesRemapUV(args: GlassTilesUVArgs): Expr; /** One chromatic-aberration sample UV: shift X by ±(colorShift·0.002). `dir` is +1 (red) / -1 * (blue); green samples the un-shifted uv directly. */ export declare const crtSampleUV: import('typegpu').TgpuFn<(uv: d.Vec2f, colorShift: d.F32, dir: d.F32) => d.Vec2f>; /** Combine the three split-tap samples into one RGB: red from the +tap, green from the centre, * blue from the −tap. */ export declare const rgbSplitCombine: import('typegpu').TgpuFn<(redSample: d.Vec4f, greenSample: d.Vec4f, blueSample: d.Vec4f) => d.Vec3f>; /** Brightness + contrast around 0.5. */ export declare const adjustShade: import('typegpu').TgpuFn<(color: d.Vec3f, contrast: d.F32, brightness: d.F32) => d.Vec3f>; /** Sinusoidal scanlines: darken by a sin wave over `uvY × frequency` (period constant 3.14159·2). */ export declare const scanlineShade: import('typegpu').TgpuFn<(color: d.Vec3f, uvY: d.F32, scanlineFrequency: d.F32, scanlineIntensity: d.F32) => d.Vec3f>; /** Subtle RGB phosphor pattern (per-channel sin masks with phase offsets 2.09/4.18). */ export declare const phosphorShade: import('typegpu').TgpuFn<(color: d.Vec3f, uv: d.Vec2f, pixelSize: d.F32) => d.Vec3f>; /** Aspect-corrected circular vignette (X in height-units). */ export declare const vignetteShade: import('typegpu').TgpuFn<(color: d.Vec3f, uv: d.Vec2f, aspect: d.F32, vignetteRadius: d.F32, vignetteIntensity: d.F32) => d.Vec3f>; /** Burst gate: slow scrolling noise, hard-edged — turns constant wobble into intermittent bursts. */ export declare const burstGate: import('typegpu').TgpuFn<(t: d.F32) => d.F32>; /** * Per-scanline fine noise: quantise UV.y into fields, hash each field. Luma/chroma get different * time-seeded hashes (additive seed, non-degenerate at t≈0). The burst gate scales the jitter * (`0.25 + burst·0.75`). Returns vec2(lumaRowOffset, chromaRowOffset). */ export declare const rowJitter: import('typegpu').TgpuFn<(uvY: d.F32, t: d.F32, scanlineNoise: d.F32, burst: d.F32) => d.Vec2f>; /** Tape waves (two-octave low-frequency wobble, always subtly present). */ export declare const tapeWave: import('typegpu').TgpuFn<(uvY: d.F32, t: d.F32, wobble: d.F32) => d.F32>; /** Tape crease: narrow horizontal band scrolling vertically, gated intermittently. */ export declare const creaseShift: import('typegpu').TgpuFn<(uvY: d.F32, t: d.F32, wobble: d.F32) => d.F32>; /** * Head-switching noise: strong, localised to the top ~5% of the frame. A `smoothstep(0.06, 0, uvY)` * band would have reversed edges (edge0 > edge1); written as `1 − smoothstep(0, 0.06, uvY)` * (provably identical, satisfies WGSL's edge0 d.Vec2f>; /** * All per-fragment tape geometry → the luma sample UV (.xy) + chroma base UV (.zw). t = time·speed. * Composes the tape parts: one burst gate feeds both the row jitter and the head switch (a shared * intermediate — computed once here), and the wave/crease/switch offsets fold into one global X. */ export declare const vhsSampleUVs: import('typegpu').TgpuFn<(uv: d.Vec2f, time: d.F32, speed: d.F32, wobble: d.F32, scanlineNoise: d.F32) => d.Vec4f>; /** AC beat: very subtle brightness pulse. mod(t, 2π) is safe with std.mod (truncated) because * t = time·speed ≥ 0 (speed ≥ 0.1), so floored ≡ truncated. */ export declare const vhsAcBeat: import('typegpu').TgpuFn<(uv: d.Vec2f, time: d.F32, speed: d.F32, wobble: d.F32) => d.F32>; /** One chroma smear tap UV: chromaUV shifted left by i·smearScale (smearScale = smear·0.0075). * Pure. Sign of smear flips the trailing side. */ export declare const vhsChromaTapUV: import('typegpu').TgpuFn<(chromaUV: d.Vec2f, smearScale: d.F32, i: d.F32) => d.Vec2f>; /** * YIQ recombine: sharp luma Y from the luma tap + smeared I/Q from the 6-tap chroma blur. The i=0 * tap has weight (0/5)·(2/6)=0, so it contributes nothing and is omitted — c1..c5 carry weights * i/15 (from `(i/(N-1))·(2/N)`, N=6), which sum to 1. Returns the recombined RGB (unclamped). * Deterministic given the samples. */ export declare const yiqRecombine: import('typegpu').TgpuFn<(luma: d.Vec4f, c1: d.Vec4f, c2: d.Vec4f, c3: d.Vec4f, c4: d.Vec4f, c5: d.Vec4f) => d.Vec3f>; /** Pulse the RGB by the beat factor and clamp to [0,1], preserving alpha. */ export declare const beatShade: import('typegpu').TgpuFn<(color: d.Vec4f, acBeat: d.F32) => d.Vec4f>; /** * Temporal pulse — bursts of glitch followed by calm. A cubed slow hash gates the major bursts, a * squared fast hash the minor flickers; both threshold against `1 − intensity`. */ export declare const burstPulse: import('typegpu').TgpuFn<(slowFrame: d.F32, fastFrame: d.F32, intensity: d.F32) => d.F32>; /** * One horizontal jitter band scale: hash the band row against a frame counter, gate it by the * glitch strength, and displace active bands. Returns vec3(displace, active, seed) — the seed is * exposed so the caller can derive correlated values (vertical jitter) for the same band. */ export declare const bandJitter: import('typegpu').TgpuFn<(bandY: d.F32, frame: d.F32, seedScale: d.F32, frameScale: d.F32, gateFactor: d.F32, hashOffset: d.F32, amplitude: d.F32, glitchStrength: d.F32) => d.Vec3f>; /** Coarse block displacement on a 4-column grid. Returns vec2(displace, active). */ export declare const blockShift: import('typegpu').TgpuFn<(colX: d.F32, bandY1: d.F32, slowFrame: d.F32, glitchStrength: d.F32) => d.Vec2f>; /** Mirror distortion — flip content horizontally/vertically in some active blocks. */ export declare const mirrorFlips: import('typegpu').TgpuFn<(displacedUV: d.Vec2f, colX: d.F32, bandY1: d.F32, slowFrame: d.F32, bandActive1: d.F32, mirrorChance: d.F32, glitchStrength: d.F32) => d.Vec2f>; /** * The shared glitch warp geometry: the burst pulse and band hashes feed the displacement, the * mirror flips, the RGB-split spread, AND the fill/scanline gates together, so they are computed * once here and exported as struct fields for the downstream parts. (Member reads re-emit the * call; Metal CSEs the identical `glitchGeom(...)` across them.) */ export declare const GlitchGeom: d.WgslStruct<{ /** The displaced + mirror-flipped sample coordinate. */ mirroredUV: d.Vec2f; /** `glitchStrength + |totalDisplaceX|·2` — scales the RGB-split offset. */ spread: d.F32; /** The burst-gated glitch strength. */ strength: d.F32; bandY1: d.F32; slowFrame: d.F32; /** bandActive1 — gates fills to active primary bands. */ bandGate: d.F32; /** blockActive — gates fills to active blocks. */ blockGate: d.F32; /** Any band active at any scale — confines the scanlines to distorted regions. */ distortion: d.F32; }>; export declare const glitchGeom: import('typegpu').TgpuFn<(uv: d.Vec2f, time: d.F32, intensity: d.F32, speed: d.F32, blockDensity: d.F32, mirrorChance: d.F32) => d.WgslStruct<{ /** The displaced + mirror-flipped sample coordinate. */ mirroredUV: d.Vec2f; /** `glitchStrength + |totalDisplaceX|·2` — scales the RGB-split offset. */ spread: d.F32; /** The burst-gated glitch strength. */ strength: d.F32; bandY1: d.F32; slowFrame: d.F32; /** bandActive1 — gates fills to active primary bands. */ bandGate: d.F32; /** blockActive — gates fills to active blocks. */ blockGate: d.F32; /** Any band active at any scale — confines the scanlines to distorted regions. */ distortion: d.F32; }>>; /** The two RGB-split tap UVs around the mirrored coordinate, clamped to [0,1]: * vec4(redUV.xy, blueUV.xy). The offset is `rgbShift·0.003·spread`. */ export declare const glitchSplitUVs: import('typegpu').TgpuFn<(mirroredUV: d.Vec2f, rgbShift: d.F32, spread: d.F32) => d.Vec4f>; /** * Colour fills — SMPTE bars or a solid neon hue per block, mixed into the colour in active * blocks. fillColor is a full-strength (unpremultiplied) neon colour — scaled by `color.w` * before mixing into premultiplied-space content, so the bar respects a semi-transparent * child's alpha instead of reading as fully opaque and then getting over-brightened by the * trailing unpremultiplyAlpha. */ export declare const fillBarsShade: import('typegpu').TgpuFn<(color: d.Vec4f, uv: d.Vec2f, bandY1: d.F32, slowFrame: d.F32, colorBarMix: d.F32, strength: d.F32, bandGate: d.F32, blockGate: d.F32) => d.Vec4f>; /** Scanlines confined to actively distorted regions (pixel-space sin wave, ×0.3 ceiling). */ export declare const distortScanShade: import('typegpu').TgpuFn<(color: d.Vec4f, uvY: d.F32, viewportY: d.F32, scanlines: d.F32, distortion: d.F32) => d.Vec4f>; //# sourceMappingURL=motionBlur.d.ts.map