import { Expr, GpuComputeNode, GpuFragmentParams } from '../../gpu/contract'; /** What `gatherIrradiance` needs. */ export interface GatherSpec { /** The pixel, as a 2D point in the shape field's coordinates. */ origin: Expr; /** The shape as a signed distance: given a point, how far it is from the edge (negative inside). */ field: (at: Expr) => Expr; /** How many directions to look in. 16 is nearly noise-free. Fixed when the shader compiles. */ cones: number; /** The most steps each direction may take toward the shape. */ steps: number; /** The distance beyond which light no longer counts, in field units. */ reach: Expr | number; /** Where each direction starts looking. The pixel's own distance to the shape is the natural start. */ start: Expr | number; /** How close counts as touching the edge, about one device pixel in field units. */ surfaceEps: Expr | number; /** A per-pixel 0–1 value that turns the fan of directions so its structure becomes fine grain. */ jitter: Expr | number; /** How bright the edge is where a direction touches it, as a single number. */ emission: (hit: { point: Expr; normal: Expr; distance: Expr; coverage: Expr; }) => Expr; /** Values from outside that `emission` also uses. List them here or they are out of scope. */ deps?: Expr[]; hint?: string; } /** * The light arriving at a pixel from a glowing shape edge, with the shape's body blocking it. * * Looks out from the pixel in `cones` directions, finds where each touches the shape, and * averages the `emission` there. Edges facing away or hidden behind the body contribute * nothing. Returns one number: the brightness at this pixel. It runs per pixel per frame, so * prefer `irradianceField` unless the light must be live. * * @example * ```ts * const light = gatherIrradiance({origin: frame.sdfUV!, field: far.at, cones: 16, steps: 24, reach: 3, start: far.sdf, surfaceEps: px, jitter: hash, emission: ({normal}) => math.max(math.dot(normal, lightDir), 0), deps: [lightDir]}) * ``` * @tip Any value computed outside `emission` and read inside it must be listed in `deps`. * @see irradianceField, shadowVisibility */ export declare function gatherIrradiance(spec: GatherSpec): Expr; /** What `shadowVisibility` needs. */ export interface ShadowSpec { /** The point being lit, moved a couple of pixels off the shape's edge along its normal. */ from: Expr; /** Where the light is, in the same coordinates. */ toward: Expr; /** The shape as a signed distance: given a point, how far it is from the edge (negative inside). */ field: (at: Expr) => Expr; /** The most steps the ray may take. 12 is typical. */ steps: number; /** How close counts as hitting the shape, about one device pixel in field units. */ surfaceEps: Expr | number; /** How wide the soft edge of the shadow is, 0–1. 0 is a hard shadow. */ softness?: Expr | number; hint?: string; } /** * How much of a light reaches a point, 1 when nothing is in the way and 0 when the shape blocks it. * * Casts a ray from `from` toward the light and stops at the shape. Values between 0 and 1 * are the soft edge of the shadow, wider with `softness`. Multiply a light's contribution by * it. * * @example * ```ts * const lit = math.mul(strength, shadowVisibility({from: math.add(edge.point, math.mul(edge.normal, math.mul(px, 2))), toward: light.uv, field: far.at, steps: 12, surfaceEps: px, softness: u.shadowSoftness})) * ``` * @tip Start `from` two pixels off the edge along its normal or the point shadows itself. * @see gatherIrradiance, irradianceField */ export declare function shadowVisibility(spec: ShadowSpec): Expr; /** What `irradianceField` needs. Every string is the name of one of your props. */ export interface IrradianceFieldSpec { /** * How many rays each texel casts per frame: `burst` on the first frame after something * changes, `motion` while changes keep coming, then `refine` for each of `refineFrames` * frames once the scene is still. After that nothing runs until the next change. */ rays: { burst: number; motion: number; refine: number; refineFrames: number; }; /** The most steps a ray may take toward the shape (default 32). */ steps?: number; /** The most steps a shadow ray may take. 0 turns shadows off entirely (default 12). */ shadowSteps?: number; /** The size of the square light texture, in texels per side. 512 is plenty; it is a smooth field. */ resolution: number; /** * Your list prop of lights (made with `listPropConfig`) and the names of its item fields: a * `position`, a `color` and a `number` for intensity. A light's position may be driven by the mouse. */ lights: { prop: string; position: string; color: string; intensity: string; }; /** The prop holding how far from the shape light is gathered, relative to the shape. */ reach: string; /** The prop holding how far light wraps around edges facing away from it, 0–1. */ wrap: string; /** The prop holding each light's range: the distance at which it falls to half strength. */ lightRange: string; /** The prop holding the shadow's soft-edge width, 0–1. */ shadowSoftness: string; /** The name the texture is published under for other compute passes (default 'irradianceTexture'). */ outputKey?: string; namePrefix?: string; } /** * The light spilling from a shape's edges, gathered once into a texture and read per pixel. * * Returns two halves. Put `compute` on your definition's `compute:` field. In your material, * call `sample(params)` for the rgb light at the pixel. It returns `undefined` when there is no * GPU to gather on, so write `sample(params) ?? splat3(0)`. It reads your standard shape props * (`center`, `scale`, `rotation`, `shape`, `shapeSdfUrl`, `shapeType`) plus the props named in * the spec. The texture only re-gathers when a light or the shape changes. * * @example * ```ts * const spill = irradianceField(GATHER).sample(params) ?? math.splat3(0) * ``` * @tip Build the spec once as a constant and use it for both `compute:` and `sample`. * @see gatherIrradiance, shadowVisibility */ export declare function irradianceField(spec: IrradianceFieldSpec): { compute: GpuComputeNode; sample: (params: GpuFragmentParams) => Expr | undefined; }; //# sourceMappingURL=radiance.d.ts.map