import { Expr, GpuFragmentParams } from '../../gpu/contract'; import { PropRef } from '../values'; import { ArgSpec } from '../invoke'; /** A generator paint — what a `role: 'generator'` definition's `paint:` field takes. */ export type Paint = (params: GpuFragmentParams) => Expr; /** A scalar field over a coordinate. Metric fields take a vec2 UV; domain combinators may pass vec3. */ export type Field = (params: GpuFragmentParams, coord: Expr) => Expr; /** A colour lookup at a field parameter t ∈ [0,1]. Build via {@link pair} or {@link stops}. */ export type Palette = (t: Expr, params: GpuFragmentParams) => Expr; /** * A scalar slot: a prop/scalar/number, optionally affine-mapped — `{base, add, mul}` * resolves to `(base + add) * mul` (for props whose UI range needs remapping into the * field's own units, e.g. a 0–100 balance slider to a ±0.3 bias). */ export type FieldScalar = ArgSpec | { base: ArgSpec; add?: number; mul?: number; }; /** * Compile-time colour-space mode reader — robust to a raw string (a preset loaded before the * prop transform ran) as well as the bridge-mapped number. */ export declare function colorSpaceModeOf(raw: unknown): number; /** * Pick the colour-mix body for the compile-time colour space bound by `space` (linear when * absent). The mode is a compile-time prop value, so it JS-branches to a specialised variant * and participates in the structural hash. */ export declare function mixColorsIn(space: PropRef | undefined, params: GpuFragmentParams): import('typegpu').TgpuFn<(colorA: import('typegpu/data').Vec4f, colorB: import('typegpu/data').Vec4f, t: import('typegpu/data').F32) => import('typegpu/data').Vec4f> | import('typegpu').TgpuFn<(colorA: import('typegpu/data').Vec4f, colorB: import('typegpu/data').Vec4f, t: import('typegpu/data').F32) => import('typegpu/data').Vec4f> | import('typegpu').TgpuFn<(colorA: import('typegpu/data').Vec4f, colorB: import('typegpu/data').Vec4f, t: import('typegpu/data').F32) => import('typegpu/data').Vec4f> | import('typegpu').TgpuFn<(colorA: import('typegpu/data').Vec4f, colorB: import('typegpu/data').Vec4f, t: import('typegpu/data').F32) => import('typegpu/data').Vec4f> | import('typegpu').TgpuFn<(colorA: import('typegpu/data').Vec4f, colorB: import('typegpu/data').Vec4f, t: import('typegpu/data').F32) => import('typegpu/data').Vec4f> | import('typegpu').TgpuFn<(colorA: import('typegpu/data').Vec4f, colorB: import('typegpu/data').Vec4f, t: import('typegpu/data').F32) => import('typegpu/data').Vec4f>; /** * A 3-colour ladder A → B (by `t1`) → C (by `t2`) in the compile-time colour `space`, chaining * the space's mix variant. */ export declare function colorLadder3(slots: { a: PropRef; b: PropRef; c: PropRef; space: PropRef; }): (t1: Expr, t2: Expr, params: GpuFragmentParams) => Expr; /** Two endpoint colour props mixed in the structural `space`. */ export declare function pair(a: PropRef, b: PropRef, space: PropRef): Palette; /** * The standard stop ramp: when the `stops` prop packs >1 active stops (the fixed * `colorsArray`/`positionsArray`/`convertedColorsArray`/`stopCount` uniforms from * `colorStopsPropConfig`), the working-space accumulation loop runs; otherwise it falls * back to the `colorA`/`colorB` pair. Both in the structural `space`. */ export declare function stops(space: PropRef): Palette; /** * The generator paint: evaluate `field` at the composed UV and look its parameter up in * `palette`. With an `edges` slot (a structural prop) the parameter is edge-handled first — * stretch (clamp), transparent (alpha fades to 0 outside the [0,1] band), mirror, or wrap — * and clamped for the colour lookup. Without one, the field's parameter feeds the palette * raw (fields that bound themselves — rings, sweeps, tone — need no clamp). */ export declare function rampOver(field: Field, palette: Palette, opts?: { edges?: PropRef; }): Paint; /** Metric-distance field producers — each maps the screen UV to a raw gradient parameter. */ export declare const dist: { /** Projection onto the `from`→`to` axis, rotated by `angle` (degrees) about the midpoint. */ linear(slots: { from: PropRef; to: PropRef; angle: FieldScalar; }): Field; /** Elliptical radial distance from `center`, normalized by `radius`; `aspect` stretches, `skew` rotates the axis. */ radial(slots: { center: PropRef; radius: FieldScalar; aspect: FieldScalar; skew: FieldScalar; }): Field; /** Angular sweep around `center`, CCW from 3-o'clock, shifted by `rotation` (degrees). */ conic(slots: { center: PropRef; rotation: FieldScalar; }): Field; /** Diamond (L1 → L∞ via `roundness`) distance from `center`, tilted by `rotation`, normalized by `size`. */ diamond(slots: { center: PropRef; size: FieldScalar; rotation: FieldScalar; roundness: FieldScalar; }): Field; /** * Animated spiral stripe coverage around `center` (0 = background, 1 = stroke), spun by * the definition's `animatedTime` clock. Stays a fused kit body: its anti-aliasing reads * `fwidth` of the spiral parameter, so the offset must be derived inside the same * fragment-scope function the derivatives sample. */ spiral(slots: { center: PropRef; scale: FieldScalar; width: FieldScalar; falloff: FieldScalar; softness: FieldScalar; }): Field; }; /** Concentric repetition: `count` ≤ 1 clamps, above 1 tiles rings via fract (a runtime select). */ export declare function rings(field: Field, count: FieldScalar): Field; /** Wrapped repetition: every cycle tiles via fract (angular sweeps, starbursts). */ export declare function tiles(field: Field, count: FieldScalar): Field; /** * Tone-shape a unit field: `glow` spreads via pow, `contrast` is multiplicative around * mid-grey, `balance` is a percent-centred (0–100) shift, `invert` flips the result so a * multi-stop ramp's stop0…stopN reads in the expected direction. Currently the glow-gamma * inverted shape (the one the kit tone library implements for unit fields). */ export declare function tone(field: Field, opts: { glow: FieldScalar; contrast: FieldScalar; balance: FieldScalar; invert: true; }): Field; /** Soft threshold over a signed [-1,1] field: normalize to [0,1], add `bias`, smoothstep `low`→`high`. */ export declare function threshold(field: Field, opts: { low: number; high: number; bias?: FieldScalar; }): Field; /** * Share one field evaluation between consumers: the first read binds a WGSL local, later * reads reuse it (a threshold and a shimmer reading the same flow pattern must not * re-derive it). Cached per composition. */ export declare function share(field: Field): Field; /** Noise bases usable as a {@link noiseField} — unit-range ([0,1]) samples over a vec3 coordinate. */ declare const NOISE_BASES: { /** MaterialX 3D noise, unit-biased. Hash-based (bit-cast) → GPU-only. */ readonly mx3: { readonly fn: () => import('typegpu').TgpuFn<(pos: import('typegpu/data').Vec3f) => import('typegpu/data').F32>; readonly hint: "unitNoise3"; }; /** 3D Perlin gradient noise, ~[0,1]. Hash-based (bit-cast) → GPU-only. */ readonly perlin: { readonly fn: () => import('typegpu').TgpuFn<(p: import('typegpu/data').Vec3f) => import('typegpu/data').F32>; readonly hint: "perlin13"; }; /** 3D value noise — soft blocky cells (Quilez permutation), [0,1]. Pure float. */ readonly value: { readonly fn: () => import('typegpu').TgpuFn<(p: import('typegpu/data').Vec3f) => import('typegpu/data').F32>; readonly hint: "value13"; }; /** RAW MaterialX 3D noise, signed [-1,1] — pair with a signed tone. GPU-only. */ readonly mx3signed: { readonly fn: () => import('typegpu').TgpuFn<(p: import('typegpu/data').Vec3f) => import('typegpu/data').F32>; readonly hint: "mxNoiseFloat3"; }; }; export type NoiseBasis = keyof typeof NOISE_BASES; /** Sample a noise basis at the incoming (vec3) coordinate. Compose under a domain producer. */ export declare function noiseField(basis: NoiseBasis): Field; /** * Domain-warp the inner field's coordinate (Inigo-Quilez two-level warp over the given * noise basis): noise displaces the sampling position before feeding the field, which is * what turns smooth noise into flowing plasma. `amount` (optionally pre-scaled by * `amountScale`) sets the displacement; the warp evolves on the definition's * `animatedTime` clock scaled by `timeScale`. */ export declare function warped(field: Field, opts: { amount: FieldScalar; amountScale?: number; timeScale?: number; }): Field; /** Lift a vec3-coordinate field onto the screen: aspect-corrected z=0 slab, zoomed exponentially by `scale`. */ export declare function scaledVolume(field: Field, opts: { scale: FieldScalar; }): Field; /** * The layered trig flow pattern: three nested sin/cos layers, each domain-warping the * previous, combined into one signed [-1,1] field. Animated by the definition's * `animatedTime` clock; reads the raw coordinate it is given (no aspect correction — the * pattern is viewport-relative by design). */ export declare function flowField(slots: { detail: FieldScalar; }): Field; /** A subtle brightness pulse from a pattern field: `sin(t·speed + pattern·span)·depth + 1`. */ export declare function pulse(field: Field, opts: { speed: number; span: number; depth: number; }): Field; /** * The classic six-segment hue wheel: a cyclic hue coordinate (any real; wraps) → rgb. * The rotating-rainbow palette (Prism's fan, ColorWheel-class effects). */ export declare function hueWheel(h: Expr): Expr; /** Scale a paint's whole colour (rgb AND alpha) by a gain field evaluated at the raw canvas UV. */ export declare function shimmered(paint: Paint, gain: Field): Paint; /** * `scatterField` — a smooth scalar field blending unit values scattered organically across the * canvas (the mesh-gradient genre primitive): golden-spiral points, gently drifting, blended by * inverse distance. `softness` is the IDW exponent (higher = crisper cells); `count` gates the * fixed-8 GPU loop at runtime. */ export declare function scatterField(opts: { at: Expr; count: Expr | number; seed: Expr | number; drift: Expr | number; aspect: Expr | number; time: Expr | number; softness: Expr | number; /** * The constellation pre-computed on the CPU (see {@link scatteredAnchors}) — an * `array` extraField holding the 8 anchors packed 4-per-vec4. When given, the GPU * skips re-deriving every anchor per pixel (`drift`/`aspect`/`time` are then read on the CPU * side and ignored here). */ anchors?: Expr; }): Expr; /** * `scatteredAnchors` — drive an `array` extraField with the {@link scatterField} * constellation, computed ONCE per frame on the CPU (the pixel-invariant half of the field: * 8 anchor positions from count/seed/drift/aspect/animated time). The definition declares * `extraFields: {: {schema: schema.arrayOf(schema.vec4f, 4), initial: 16 zeros}}`; this word * registers the per-frame writer and returns the field's GPU accessor to pass as * `scatterField({anchors})`. Reads the node's live `_animTime` (the same accumulator the GPU * warp reads), so anchors and warp stay on one clock. Dirty-keyed: a static composition (speed 0, * no edits) writes nothing. In a GPU-free composition (tests) `_animTime` is unavailable and the * field keeps its initial value. */ export declare function scatteredAnchors(params: GpuFragmentParams, slots: { count: PropRef; seed: PropRef; drift: PropRef; field: string; }): Expr; /** * `wrapRamp` — traverse a palette through `cycles` half-cycles as `t` rises, folding back at the * ends (seam-free triangle wave; identity at cycles = 1); sub-pixel bands fade to the palette * mid instead of shimmering. Fragment-only (fwidth). */ export declare function wrapRamp(opts: { t: Expr; cycles: Expr | number; }): Expr; /** * `foldRamp` — fold an unbounded palette parameter back into [0, 1] as a seam-free triangle * wave (0→1→0 every 2 units of `t`). The derivative-free cousin of {@link wrapRamp}: no * sub-pixel fade, so it is safe inside a `guarded` branch (non-uniform control flow, where * `fwidth` is not). Scale `t` first to set the cycle length. */ export declare function foldRamp(t: Expr): Expr; /** * `warpedPoint` — the domain-warped position itself (two Inigo-Quilez warp levels over MaterialX * noise), for recipes that need the warped COORDINATE (to feed several fields) rather than one * warped field sample (`warped`). Same memoized 'warpDomain' instance as {@link warped}. */ export declare function warpedPoint(opts: { at: Expr; time: Expr | number; amount: Expr | number; levels?: 1 | 2; }): Expr; /** * `warpStep` — one chained Inigo-Quilez domain-warp level: displace a position by two * decorrelated noise reads (returned as `.z`/`.w` for tail stages to shade with). Chain steps * by feeding one step's `.xy` to the next. `offsets` are the two decorrelation offsets — the * caller's look data. */ export declare function warpStep(opts: { at: Expr; scale: number; z: Expr | number; offsets: [[number, number], [number, number]]; reach: number; strength: Expr | number; }): Expr; /** * The standard multi-stop / two-colour palette, read from the definition's standard palette * props (colorA/colorB/stops/colorSpace). The coordinate is consumed once — the stops loop * takes it as a fn parameter. */ export declare function standardPalette(t: Expr, params: GpuFragmentParams): Expr; /** * A 2D 4-colour blend: row1 = A→B by `t1`, row2 = C→D by `t1`, base = row1→row2 by `t2`, in * the compile-time colour `space`. For a non-linear space the four endpoint conversions are * pixel-invariant, so the word's per-frame driver preconverts them (dirty-keyed) into the * `convA`–`convD` vec3 extraFields the definition declares, and the GPU mixes the * preconverted values with a single back-conversion. */ export declare function quadBlend(slots: { a: PropRef; b: PropRef; c: PropRef; d: PropRef; space: PropRef; }): (t1: Expr, t2: Expr, params: GpuFragmentParams) => Expr; export {}; //# sourceMappingURL=fields.d.ts.map