import { GpuComputeNode, GpuFragmentParams, KitTexture, Expr } from '../../gpu/contract'; import { DirectionFrame } from '../frames'; /** * Evaluate `inner` only where `cond` holds; elsewhere the (cheap) `fallback`. Emits * `var x = fallback; if (cond) { …inner hoists…; x = inner; }`. Values hoisted BEFORE the guard * (emitted by `cond`/`fallback`, or by earlier expressions) stay in the enclosing scope and remain * visible inside; values first used inside are declared inside and must not be re-read outside. * A `local()` shared between the guarded interior and any later expression MUST be listed in * `deps` — that emits it in the enclosing scope first (a hoist whose first use is inside the * branch would otherwise be block-scoped and unreachable afterwards). */ export declare function guarded(cond: Expr, inner: Expr, fallback: Expr, hint?: string, deps?: Expr[]): Expr; export { reflect, refract, exp2 } from '../math'; /** The material-body early-exit condition as vocabulary: NOT outside the shape by > 2 device * pixels (the exact complement of the kit's `outsideShape` early-exit test). */ export declare function insideShape(sdf: Expr, pxH: Expr): Expr; /** The resolved per-fragment frame the `surface:` slot shades. */ export interface SurfaceFrame { /** Placement-space UV (`sdfSpaceUV` over center/scale/rotation) — undefined for `stencil: 'none'`. */ sdfUV?: Expr; /** Centre field tap (`.x` sdf/−chord, `.y/.z` pattern coords or baked gradients, `.w` depth). */ surf0?: Expr; /** Forward/central stencil neighbour taps (per the declared `stencil`). */ surfX?: Expr; surfY?: Expr; /** Central-stencil extras (−eps taps); only with `stencil: {kind: 'central'}`. */ surfL?: Expr; surfD?: Expr; /** Centre-quality field sampler (materials with `stencil: 'none'` take their own taps). */ sampler: (uv: Expr) => Expr; /** Neighbour-tap sampler (cheap bilinear on the volumetric path unless `gradSampler: 'same'`). */ gradSampler: (uv: Expr) => Expr; /** Unfiltered nearest-texel tap — for discrete payload a pre-march packs into the field * (the voxel G-buffer's face/cell channels). Aliases `sampler` on the flat paths. */ texelSampler: (uv: Expr) => Expr; /** Build-time: the active shape resolved to the compute-marched volumetric path. */ volumetric: boolean; /** `volumetric` as the runtime 0/1 f32 the composite bodies `std.select` on. */ volFlag: Expr; /** Build-time: the sampler carries analytic/baked gradients in `.g/.b` (skip FD taps). */ bakedGradients: boolean; /** Child RTT (with `child: 'required'`) — compute-created when a consumer prepass made one. */ childTexture?: KitTexture; } export interface ShapedSurfaceSpec { /** Surface-pattern coords the volumetric pre-march bakes into `.g/.b` (default 'none'). */ pattern?: 'none' | 'raw' | 'triplanar'; /** Chord measure along the march ray (default 'span'; 'firstLobe' = front-wall thickness). */ chord?: 'span' | 'firstLobe'; /** Neighbour-tap sampler quality (default 'fast'; 'same' = centre sampler everywhere). */ gradSampler?: 'fast' | 'same'; /** Baked-gradient routing (default 'none'); see `ShapeFieldSamplerOptions`. */ bakedGradients?: 'none' | 'volumetric' | 'all'; /** The field-tap frame to resolve for the material (default forward stencil at eps 0.01). */ stencil?: 'none' | 'centre' | { kind: 'forward' | 'central'; eps: number; }; /** * Which sampler takes the CENTRE tap (default 'quality' — bicubic on the volumetric path). * 'fast' takes the cheap bilinear neighbour sampler instead: for a material whose open-canvas * pixels only gate on the centre value (coverage, an outside branch) and that takes its own * quality tap inside the branches that need one — the metals' bicubic-per-pixel is 16 texel * loads at every canvas pixel on a 3D shape. */ centreTap?: 'quality' | 'fast'; /** Displace the screen UV before placement (returns the UV fed to `sdfSpaceUV`). */ placeUV?: (params: GpuFragmentParams) => Expr; /** Resolve the child RTT into the frame; without a child the fragment returns transparent. */ child?: 'required'; /** THE MATERIAL: shade the resolved frame. */ surface: (frame: SurfaceFrame, params: GpuFragmentParams) => Expr; } /** The three definition halves the spine contributes — spread into the definition. */ export interface ShapedSurfaceEffect { extraFields: Record; compute: GpuComputeNode; gpu: { fragment: (params: GpuFragmentParams) => Expr; }; } /** The shape-effect spine noun. See the module header. */ export declare function shapedSurface(spec: ShapedSurfaceSpec): ShapedSurfaceEffect; export interface SurfaceField { /** Centre / forward-x / forward-y field taps, locals-bound. */ s0: Expr; sX?: Expr; sY?: Expr; /** Signed distance (centre tap `.x`, divided by `scale` when given). */ sdf: Expr; /** One pixel in UV height units. */ pxH: Expr; /** Viewport aspect (width / height). */ aspect: Expr; } /** The opening block of every material: bind the field taps + sdf + pixel size to locals. */ export declare function surfaceField(frame: SurfaceFrame, params: GpuFragmentParams, opts?: { scale?: Expr; }): SurfaceField; /** * The geometric surface normal, resolved at build time: marched volumetric shapes take the * field-tap normal; flat shapes take the gradient normal tilted by the bevel profile. */ export declare function geometricNormal(frame: SurfaceFrame, field: SurfaceField, opts: { bevelWidth: Expr; bevelShape: Expr; sharpness?: number; eps?: number; hint?: string; }): Expr; /** Surface-pattern coordinates (the coords a pattern rides the geometry in), locals-bound. */ export declare function surfacePattern(frame: SurfaceFrame, field: SurfaceField, opts?: { uv?: Expr; }): Expr; /** The in-plane field gradient (the outward direction a flat shape's shading rides). */ export declare function fieldSlope(field: SurfaceField, eps?: number): Expr; /** The perspective view ray for a pseudo-3D surface, locals-bound. */ export declare function viewRay(params: GpuFragmentParams, field: SurfaceField, fov?: number): Expr; /** How edge-on the surface is to the view (0 face-on → 1 grazing), locals-bound. */ export declare function grazingOf(n: Expr, view: Expr): Expr; /** Tilt a normal within a direction frame: `along`/`across` are slope amounts per axis. */ export declare function tiltNormal(n: Expr, frame: DirectionFrame, slopes: { along?: Expr; across?: Expr; }, hint?: string): Expr; /** The shared 5-softbox studio bank, looked up at a reflected direction. */ export declare function studioSoftboxes(x: Expr, y: Expr, opts: { /** The studio rotation as a `direction()` vector. */ rotation: Expr; keyRadius: Expr | number; drift: Expr | number; strength: Expr | number; skyGain: number; }): Expr; /** * Grain-space noise: one octave of value noise over a direction frame's coordinates, with a * frequency per axis. Octave sums, gains, and drift terms are algebra at the call site — they * are the look; this is the sampling. */ export declare function grainNoise(coords: { along: Expr; across: Expr; }, opts: { freq: [Expr | number, Expr | number]; offset?: [number, number]; drift?: Expr; }): Expr; /** * A gaussian-weighted directional gather: sample `taps` points spread along `axis` around * `center`, summed with baked normalized weights. The anisotropic smear of any 2D lookup — * a reflected environment along a brush grain, a streaked highlight, a motion smear. */ export declare function smearAlong(opts: { center: Expr; axis: Expr; spread: Expr; taps?: number; sigma?: number; hint?: string; }, sample: (x: Expr, y: Expr) => Expr): Expr; /** A 3D light direction from a `direction()` vector and an eye-tuned elevation z. */ export declare function lightVec3(dir: Expr, z: number, hint?: string): Expr; /** The house roughness/anisotropy → Ward lobe-width mapping (stretch along, squeeze across). */ export declare function wardAlphas(roughness: Expr, anisotropy: Expr): { along: Expr; across: Expr; }; /** * Anisotropic (Ward) specular lobe: stretched along `tangent`, widths per axis from `alphas` * (see {@link wardAlphas} for the designer-terms mapping). */ export declare function anisoSpecular(opts: { normal: Expr; /** The grain/fibre tangent (2D — in-plane). */ tangent: Expr; /** Normalized 3D light direction (see {@link lightVec3}). */ light: Expr; view: Expr; alphas: { along: Expr; across: Expr; }; gain?: Expr | number; }): Expr; /** Tilt a normal along one in-plane axis by a slope amount. */ export declare function tiltAlong(n: Expr, axis: Expr, amount: Expr, hint?: string): Expr; /** Fresnel edge lift: `1 + grazing^power · amount`. */ export declare function fresnelBoost(grazing: Expr, opts: { power?: number; amount: Expr | number; }): Expr; /** A two-tone tint ramp: dark → light by a lighting term (Duotone's ramp as material tint). */ export declare function tintRamp(t: Expr, dark: Expr, light: Expr): Expr; /** The soft silhouette alpha at the shape boundary. */ export declare function silhouette(field: SurfaceField, edgeSoftness: Expr): Expr; /** The neutral filmic tonemap shoulder (exposure grading's final step). */ export declare function neutralTone(rgb: Expr): Expr; /** Nudge a normal by screen-space slope deltas (the isotropic cousin of `tiltNormal`). */ export declare function nudgeNormal(n: Expr, dx: Expr, dy: Expr, hint?: string): Expr; /** The volumetric field-tap normal (marched shapes). Flat shapes shape their own — see * {@link geometricNormal} for the standard bevelled path. */ export declare function marchedNormal(field: SurfaceField, sharpness?: number, hint?: string): Expr; /** The key-light frame from a `direction()` vector: `.L` light dir, `.H` half vector. * `elevation` is the material's eye-tuned z (the fleet uses −0.6 … −0.9). */ export declare function keyLightAt(dir: Expr, elevation: number, hint?: string): Expr; /** {@link keyLightAt} from explicit in-plane components (shimmered / cross lights). */ export declare function keyLightXY(x: Expr, y: Expr, elevation: number, hint?: string): Expr; /** Grazing factor for the fixed −z view (the fresnel input when no perspective ray exists). */ export declare function grazingFlat(n: Expr): Expr; /** Sharp key-light glint lobe. */ export declare function sharpGlint(ndh: Expr, sharpness: Expr, cfg: Expr): Expr; /** Clamped perlin slope — the pressed/molten waviness gradient two metals nudge normals with. */ export declare function perlinSlope(q: Expr, gain: Expr | number): Expr; /** Optical body thickness of the shape field (chord on marched shapes, rim proxy on flat). */ export declare function opticalThickness(field: SurfaceField, frame: SurfaceFrame): Expr; /** Beer–Lambert transmission: `exp(−thickness · absorb)` per channel. */ export declare function beerLambert(thickness: Expr, absorb: Expr): Expr; /** The shared incommensurate-frequency flow-warp offset (molten folds / wind-driven waves). */ export declare function flowWarp(warpInput: Expr, flowT: Expr): Expr; /** Signed value noise sampled at a surface point (the material grain/crumple basis). */ export declare function surfaceNoise(x: Expr | number, y: Expr | number): Expr; /** {@link surfaceNoise} at a pre-built vec2 point. */ export declare function surfaceNoiseAt(p: Expr): Expr; /** Signed noise sampled at an interior volume point (vec3) — the 3D cousin of * {@link surfaceNoiseAt}: the basis for anything sampled THROUGH a body rather than * across its surface (gas, smoke, inclusions, subsurface density). */ export declare function volumeNoiseAt(p: Expr): Expr; /** IQ cosine palette: a smooth rainbow ramp with per-channel phase offsets. */ export declare function cosineRainbow(t: Expr, phases: [number, number, number]): Expr; /** Worley (cellular) noise at a surface point — the facet/crack cell basis. */ export declare function cellNoiseAt(p: Expr): Expr; /** * Finite-difference slope of any scalar surface field: the field's value at `p` plus its * x/y derivatives at step `eps` — the relief-to-normal bridge every bump recipe rides. */ export declare function fdSlope(sampleAt: (p: Expr) => Expr, p: Expr, eps: number, hint?: string): { value: Expr; dx: Expr; dy: Expr; }; /** Unsigned white-noise hash of a 2D point (film grain, flicker, per-pixel jitter). */ export declare function hashNoise(x: Expr | number, y: Expr | number): Expr; /** * Interleaved gradient noise over device pixels: a [0,1) pattern whose neighbouring pixels are * maximally different (Jimenez 2014) — the low-discrepancy cousin of {@link hashNoise} for * jittering samples, where white noise clumps into visible grain. `clock` advances the pattern * by the golden ratio per unit so successive frames decorrelate. */ export declare function interleavedNoise(pixel: Expr, clock?: Expr | number): Expr; /** Unsigned smooth value noise at a surface point (the [0,1] cousin of {@link surfaceNoise}). */ export declare function valueNoise(x: Expr | number, y: Expr | number): Expr; /** * How rotated the 3D shape is, as an in-plane pan vector: one field tap at the placement * centre reads the surface-locked pattern coords of the centre hit (zero at rest on every * shape, growing with 3D rotation). Spatially constant per frame, so it pans content * (star planes, interior backdrops) without shearing it; flat shapes gate to zero. * Requires `pattern: 'raw'`. */ export declare function rotationSensor(frame: SurfaceFrame): { x: Expr; y: Expr; }; /** * Interior coordinates bent at the shell: centered placement coords displaced along the * surface normal's in-plane tilt. `n.xy` is ~0 on a flat face and large at bevels and * silhouettes, so the bend concentrates where real glass would bend the interior — the * cheap single-interface cousin of a full refraction trace. Also returns the unbent * centered coords for anything anchored to the container rather than the interior. */ export declare function shellRefract(frame: SurfaceFrame, n: Expr, amount: Expr): { x: Expr; y: Expr; centered: { x: Expr; y: Expr; }; }; /** Schlick fresnel reflectance: `r0 + grazing^power · gain`. Physical glass is * `{r0: 0.04, gain: 0.96}`; lower the gain to keep grazing faces from curtaining * an interior behind full mirror. */ export declare function schlickFresnel(grazing: Expr, opts: { r0?: number; gain: Expr | number; power?: number; }): Expr; /** A per-element shimmer factor around 1: `1 − amount + sin(t·rate + phase·spread)·amount`. * `phase` decorrelates elements (a per-star/per-flake variation field). */ export declare function twinkle(t: Expr, phase: Expr, opts: { amount: Expr; rate: number; spread: number; }): Expr; /** * A plane of point glints — stars, glitter, bokeh dust: worley feature points lit only * within a tiny radius, gated to a sparse subset and sized/brightened per point by a slow * variation field. Returns the glint intensity and the variation field (for tinting). * The worley metric is squared distance in cell units, so radii are in those units. */ export declare function pointStars(p: Expr, opts: { /** Frequency of the per-point variation field relative to `p` (slow: ~0.1). */ variationFreq: number; /** Point radius: base + variation · jitter (squared-distance units). */ radius: [number, number]; /** smoothstep band of the variation field that keeps a point at all (sparsity). */ keep: [number, number]; /** Brightness: base + variation² · gain. */ brightness: [number, number]; /** Per-point shimmer factor, built from the variation field (see {@link twinkle}). */ shimmer?: (variation: Expr) => Expr; /** Overall gain. */ gain: Expr; /** Colour the glints: variation mixes `from` → `to`, scaled by the glint × `gain`. */ tint?: { from: [number, number, number]; to: [number, number, number]; gain: number; }; hint?: string; }): { glint: Expr; variation: Expr; rgb?: Expr; }; /** * A `transformPosition` prop mapped into the shape's placement (sdfUV) space — the same * aspect/rotation/scale placement the field is sampled in, so a light, anchor or pointer position * can be compared against field coordinates directly. Placement-space distances are the field's * units (the shape's own scale), not screen units. */ export declare function placementPoint(params: GpuFragmentParams, position: Expr, hint?: string): Expr; /** * The field continued beyond its texture. The flat SVG sampler clamps to its 0–1 square, so a * far-reaching effect (a glow, a cast shadow) would see a plateau past it. The continuation is a * sphere-trace-safe LOWER bound — `max(beyond, border − beyond)`, the shape being inside the * square — not `border + beyond`, which is an upper bound that a march overshoots through * (analytic fields need nothing). Returns the continued distance at the pixel, the outward push vector (zero within the square) to add to any * gradient taken from the clamped taps, and `at(uv)` — the continued distance anywhere (fast * neighbour-quality taps, flow-safe: the sampler for ray marches and shadow rays). Expects an * unscaled {@link surfaceField}. */ export declare function continuedField(frame: SurfaceFrame, field: SurfaceField, params: GpuFragmentParams): { sdf: Expr; outward: Expr; at: (uv: Expr) => Expr; }; /** * The nearest point of the shape boundary to this pixel and the outward unit normal there — where * a rim glow, contact shadow or edge light originates for pixels outside the shape. `slope` is * the in-plane field gradient (see {@link fieldSlope}); its length is guarded. */ export declare function nearestEdge(sdfUV: Expr, sdf: Expr, slope: Expr, hint?: string): { point: Expr; normal: Expr; }; /** * A point light in placement space as seen from `at` (a 2D placement point on the shape plane): * the unit 3D light vector in the material convention (z negative = toward the viewer, matching * {@link lightVec3}), the in-plane unit direction toward the light, and the in-plane distance. */ export declare function pointLightFrom(light: { position: Expr; height: Expr | number; }, at: Expr, hint?: string): { L: Expr; toLight: Expr; distance: Expr; }; /** * Diffuse (Lambert) response of a normal to a unit light vector (2D or 3D pairs alike), with * optional wrap lighting: `wrap` 0 = strict hemisphere, 1 = the light reaches all the way round. */ export declare function lambert(normal: Expr, light: Expr, opts?: { wrap?: Expr | number; }): Expr; /** Inverse-square attenuation of a point light: 1 at the source, half strength at `range`. */ export declare function inverseSquare(distance: Expr, range: Expr | number): Expr; /** * Photographic exposure response `1 − e^(−rgb)`: light piles up toward white the way a bright * emitter burns out on film, instead of clipping per channel (the HDR → display step of any * emissive look; {@link neutralTone} is the graded-image cousin). */ export declare function exposureTone(rgb: Expr): Expr; /** * Multiplicative sensor grain `rgb · (1 + (hash − 0.5) · amount)`, keyed per device pixel and * re-rolled by `clock` — the photon-noise floor that makes rendered light read as photographed. */ export declare function sensorGrain(rgb: Expr, opts: { amount: Expr | number; pixel: Expr; clock: Expr | number; }): Expr; /** * Two-lobe specular glint — a tight hot core plus a wide dim halo. `softness` widens or * tightens both lobes around the authored exponents (0.5 is neutral: the exponents as * given; 0 is ~4× sharper, 1 is ~4× softer). */ export declare function dualLobeGlint(ndh: Expr, opts: { /** [exponent, gain] of the hot core lobe. */ core: [number, number]; /** [exponent, gain] of the wide halo lobe. */ halo: [number, number]; softness?: Expr; gain: Expr; }): Expr; //# sourceMappingURL=materials.d.ts.map