import { d } from '../kit/index'; import { TgpuRoot } from 'typegpu'; import { KitComputePipeline } from '../compute'; /** The irradiance texture format — filterable, so the fragment samples it bilinearly. */ export declare const IRRADIANCE_FORMAT: "rgba16float"; /** The fixed capacity of the light list in the params ABI (a list prop's `maxItems` must not exceed it). */ export declare const MAX_LIGHTS = 8; /** The per-frame params ABI the gather kernels read. */ export declare const IrradianceParams: d.WgslStruct<{ /** Shape placement (transformPosition-stored center). */ center: d.Vec2f; /** The lights: position lanes in PLACEMENT (sdfUV) space, colour lanes (linear rgb, intensity in .w), live count. */ lightPos: d.WgslArray; lightColor: d.WgslArray; lightCount: d.F32; scale: d.F32; rotation: d.F32; aspect: d.F32; /** Gather controls. */ reach: d.F32; wrap: d.F32; lightRange: d.F32; shadowSoftness: d.F32; /** One device pixel in field units (hit threshold, minimum step). */ eps: d.F32; /** Texels per side of the (square) irradiance texture. */ res: d.F32; /** Progressive sample index (0 on a fresh scene, +1 per accumulated frame). */ frame: d.F32; /** Rays cast per texel THIS frame (a per-frame budget: burst on a change, fewer while refining). */ rays: d.F32; /** Analytic SDF sub-props (the `_sa*` bundle). */ saRadius: d.F32; saSides: d.F32; saRounding: d.F32; saInnerRatio: d.F32; saRotation: d.F32; saHeight: d.F32; saOffset: d.F32; saAperture: d.F32; /** Volumetric field domain (the `_vf*` bundle). */ vfOriginX: d.F32; vfOriginY: d.F32; vfSpanX: d.F32; vfSpanY: d.F32; vfActiveRes: d.F32; vfRBound: d.F32; }>; export declare const irradianceAnalyticLayout: import('typegpu').TgpuBindGroupLayout<{ params: { uniform: d.WgslStruct<{ /** Shape placement (transformPosition-stored center). */ center: d.Vec2f; /** The lights: position lanes in PLACEMENT (sdfUV) space, colour lanes (linear rgb, intensity in .w), live count. */ lightPos: d.WgslArray; lightColor: d.WgslArray; lightCount: d.F32; scale: d.F32; rotation: d.F32; aspect: d.F32; /** Gather controls. */ reach: d.F32; wrap: d.F32; lightRange: d.F32; shadowSoftness: d.F32; /** One device pixel in field units (hit threshold, minimum step). */ eps: d.F32; /** Texels per side of the (square) irradiance texture. */ res: d.F32; /** Progressive sample index (0 on a fresh scene, +1 per accumulated frame). */ frame: d.F32; /** Rays cast per texel THIS frame (a per-frame budget: burst on a change, fewer while refining). */ rays: d.F32; /** Analytic SDF sub-props (the `_sa*` bundle). */ saRadius: d.F32; saSides: d.F32; saRounding: d.F32; saInnerRatio: d.F32; saRotation: d.F32; saHeight: d.F32; saOffset: d.F32; saAperture: d.F32; /** Volumetric field domain (the `_vf*` bundle). */ vfOriginX: d.F32; vfOriginY: d.F32; vfSpanX: d.F32; vfSpanY: d.F32; vfActiveRes: d.F32; vfRBound: d.F32; }>; }; outTex: { readonly storageTexture: d.WgslStorageTexture2d<"rgba16float", string>; }; }>; export declare const irradianceSvgLayout: import('typegpu').TgpuBindGroupLayout<{ params: { uniform: d.WgslStruct<{ /** Shape placement (transformPosition-stored center). */ center: d.Vec2f; /** The lights: position lanes in PLACEMENT (sdfUV) space, colour lanes (linear rgb, intensity in .w), live count. */ lightPos: d.WgslArray; lightColor: d.WgslArray; lightCount: d.F32; scale: d.F32; rotation: d.F32; aspect: d.F32; /** Gather controls. */ reach: d.F32; wrap: d.F32; lightRange: d.F32; shadowSoftness: d.F32; /** One device pixel in field units (hit threshold, minimum step). */ eps: d.F32; /** Texels per side of the (square) irradiance texture. */ res: d.F32; /** Progressive sample index (0 on a fresh scene, +1 per accumulated frame). */ frame: d.F32; /** Rays cast per texel THIS frame (a per-frame budget: burst on a change, fewer while refining). */ rays: d.F32; /** Analytic SDF sub-props (the `_sa*` bundle). */ saRadius: d.F32; saSides: d.F32; saRounding: d.F32; saInnerRatio: d.F32; saRotation: d.F32; saHeight: d.F32; saOffset: d.F32; saAperture: d.F32; /** Volumetric field domain (the `_vf*` bundle). */ vfOriginX: d.F32; vfOriginY: d.F32; vfSpanX: d.F32; vfSpanY: d.F32; vfActiveRes: d.F32; vfRBound: d.F32; }>; }; outTex: { readonly storageTexture: d.WgslStorageTexture2d<"rgba16float", string>; }; sdfSource: { texture: d.WgslTexture2d; }; samp: { sampler: "filtering"; }; }>; export declare const irradianceFieldLayout: import('typegpu').TgpuBindGroupLayout<{ params: { uniform: d.WgslStruct<{ /** Shape placement (transformPosition-stored center). */ center: d.Vec2f; /** The lights: position lanes in PLACEMENT (sdfUV) space, colour lanes (linear rgb, intensity in .w), live count. */ lightPos: d.WgslArray; lightColor: d.WgslArray; lightCount: d.F32; scale: d.F32; rotation: d.F32; aspect: d.F32; /** Gather controls. */ reach: d.F32; wrap: d.F32; lightRange: d.F32; shadowSoftness: d.F32; /** One device pixel in field units (hit threshold, minimum step). */ eps: d.F32; /** Texels per side of the (square) irradiance texture. */ res: d.F32; /** Progressive sample index (0 on a fresh scene, +1 per accumulated frame). */ frame: d.F32; /** Rays cast per texel THIS frame (a per-frame budget: burst on a change, fewer while refining). */ rays: d.F32; /** Analytic SDF sub-props (the `_sa*` bundle). */ saRadius: d.F32; saSides: d.F32; saRounding: d.F32; saInnerRatio: d.F32; saRotation: d.F32; saHeight: d.F32; saOffset: d.F32; saAperture: d.F32; /** Volumetric field domain (the `_vf*` bundle). */ vfOriginX: d.F32; vfOriginY: d.F32; vfSpanX: d.F32; vfSpanY: d.F32; vfActiveRes: d.F32; vfRBound: d.F32; }>; }; outTex: { readonly storageTexture: d.WgslStorageTexture2d<"rgba16float", string>; }; silhouetteTex: { texture: d.WgslTexture2d; }; samp: { sampler: "filtering"; }; }>; type Layout = typeof irradianceAnalyticLayout | typeof irradianceSvgLayout | typeof irradianceFieldLayout; /** A signed-distance source in placement (sdfUV) space. */ type FieldFn = (uv: d.v2f) => number; /** Analytic source: the baked SDF fn for `shapeType`, sub-props from params. */ export declare function analyticField(shapeType: string): FieldFn; /** * SVG source: hardware-bilinear sample of the SDF data texture (exact inside its unit square), * continued beyond it with a sphere-trace-safe LOWER bound. `border + beyond` — the obvious * continuation — is an UPPER bound (triangle inequality), and a march through an upper bound * overshoots and skips the shape, differently on each side of the square's edge lines. The shape * lives inside the square, so `beyond` (distance to the square) is a lower bound, and so is * `border − beyond` (reverse triangle inequality); their max is tight where the border is far from * the outline and safe where it touches it. */ export declare const svgField: FieldFn; /** * Volumetric source: the shape's SILHOUETTE distance field — the exact 2D signed distance to the * marched outline, jump-flooded over the marched domain (see below) — sampled bilinearly, and * outside the domain the largest of three sphere-trace-safe lower bounds (distance to the domain, * distance to the bounding circle, the border's silhouette distance less the distance to it). * * Why not the marched field's own `.r`: outside the silhouette it holds the minimum 3D distance * met along the view ray, which is ≥ the projected 2D distance — an UPPER bound that a 2D march * overshoots through (accurate beside the shape where the ray samples densely at its depth, badly * inflated toward the domain edges where the ray misses the bounding sphere). */ export declare const volumetricField: FieldFn; export declare const SilhouetteParams: d.WgslStruct<{ vfOriginX: d.F32; vfOriginY: d.F32; vfSpanX: d.F32; vfSpanY: d.F32; vfActiveRes: d.F32; vfRBound: d.F32; /** Texels per side of the silhouette texture. */ res: d.F32; /** Jump-flood step for this pass, in texels. */ step: d.F32; }>; export declare const silhouetteSeedLayout: import('typegpu').TgpuBindGroupLayout<{ params: { uniform: d.WgslStruct<{ vfOriginX: d.F32; vfOriginY: d.F32; vfSpanX: d.F32; vfSpanY: d.F32; vfActiveRes: d.F32; vfRBound: d.F32; /** Texels per side of the silhouette texture. */ res: d.F32; /** Jump-flood step for this pass, in texels. */ step: d.F32; }>; }; fieldTex: { texture: d.WgslTexture2d; sampleType: string; }; out: { readonly storageTexture: d.WgslStorageTexture2d<"rgba16float", string>; }; }>; export declare const silhouetteStepLayout: import('typegpu').TgpuBindGroupLayout<{ params: { uniform: d.WgslStruct<{ vfOriginX: d.F32; vfOriginY: d.F32; vfSpanX: d.F32; vfSpanY: d.F32; vfActiveRes: d.F32; vfRBound: d.F32; /** Texels per side of the silhouette texture. */ res: d.F32; /** Jump-flood step for this pass, in texels. */ step: d.F32; }>; }; src: { texture: d.WgslTexture2d; }; out: { readonly storageTexture: d.WgslStorageTexture2d<"rgba16float", string>; }; }>; /** Seed: boundary texels seed themselves (distance 0); others start "no seed" (x < 0, far). */ export declare const silhouetteSeedKernel: import('typegpu').TgpuFn<(cx: d.U32, cy: d.U32) => d.Void>; /** One jump-flood pass: adopt the nearest seed among the 3×3 neighbours at `step` texels. */ export declare const silhouetteStepKernel: import('typegpu').TgpuFn<(cx: d.U32, cy: d.U32) => d.Void>; export interface IrradianceKernelOptions { /** Sphere-trace step cap per ray. */ steps: number; /** Shadow-ray step cap (0 = no shadow rays). */ shadowSteps: number; namePrefix: string; } /** * The gather kernel over `layout`, reading the field through `fieldAt`. Per texel: map to screen * UV → placement UV; texels inside the shape are pushed to just outside the boundary so bilinear * upsampling across the silhouette has valid neighbours; then the stratified ray fan (see the module * header) with the point light's Lambert × inverse-square × shadow-ray visibility at each hit; the * mean (rgb — every light's colour lands where it falls), faded toward `reach`, is stored * premultiplied by the outside mask (`.rgb` = E·m, `.a` = m). The estimate is noisy per texel by * design — read the result through the denoise blur, never raw, and divide `.rgb` by `.a`. */ export declare function buildIrradianceKernel(layout: Layout, fieldAt: FieldFn, opts: IrradianceKernelOptions): import('typegpu').TgpuFn<(cx: d.U32, cy: d.U32) => d.Void>; /** The gather kernel as a guarded 2D compute pass over the res×res irradiance texture. */ export declare function createIrradiancePass(root: TgpuRoot, kernel: (cx: number, cy: number) => void, opts: { res: number; bindGroup: unknown; }): KitComputePipeline; export declare const AccumulateParams: d.WgslStruct<{ /** Blend weight of the new sample: 1 replaces, 1/(n+1) is the running mean. */ weight: d.F32; }>; export declare const accumulateLayout: import('typegpu').TgpuBindGroupLayout<{ sample: { texture: d.WgslTexture2d; }; prev: { texture: d.WgslTexture2d; }; out: { readonly storageTexture: d.WgslStorageTexture2d<"rgba16float", string>; }; params: { uniform: d.WgslStruct<{ /** Blend weight of the new sample: 1 replaces, 1/(n+1) is the running mean. */ weight: d.F32; }>; }; }>; /** `out = prev + (sample − prev) · weight` — the running mean of a progressive estimate. */ export declare const accumulateKernel: import('typegpu').TgpuFn<(cx: d.U32, cy: d.U32) => d.Void>; export declare const copyLayout: import('typegpu').TgpuBindGroupLayout<{ src: { texture: d.WgslTexture2d; }; out: { readonly storageTexture: d.WgslStorageTexture2d<"rgba16float", string>; }; }>; /** Texture copy (the accumulation's write target back to its read source for the next frame). */ export declare const copyKernel: import('typegpu').TgpuFn<(cx: d.U32, cy: d.U32) => d.Void>; export {}; //# sourceMappingURL=radiance.d.ts.map