/** * SubsurfaceScattering.ts * * Subsurface scattering (SSS) implementation: * - Burley/Christensen normalized diffusion profile * - Multi-channel RGB scatter radii (skin: R large, G medium, B small) * - Multi-layer SSS (epidermis / dermis) * - Thin-slab transmission approximation * - Thickness map sampling (Float32Array or constant) * - Separable SSS blur kernel (screen-space blur weights via Gaussian sum) * - Pre-built material profiles (skin, wax, jade, marble, leaves) * * No WebGPU — fully CPU-testable in Vitest. * * @module rendering */ export type RGB = [number, number, number]; export type SSSModel = 'burley' | 'christensen' | 'separable_sss'; export interface SSSLayer { /** Weight of this layer (0–1, sum of all layers should ≤ 1) */ weight: number; /** Per-channel (R, G, B) scattering radius in world units */ scatterRadius: RGB; /** Base scatter color (tint) */ color: RGB; } export interface SSSConfig { model: SSSModel; /** Diffusion radius falloff shape (1 = linear, 2 = quadratic like Burley) */ falloffPower: number; /** Transmission (0 = opaque, 1 = fully transparent thin slab) */ transmission: number; /** Constant thickness if no thickness map provided (0–1) */ thickness: number; layers: SSSLayer[]; } /** * Burley normalized diffusion profile: R(r) = A/r * (e^(-r/d) + e^(-r/(3d))) * Returns relative diffusion weight at distance r for a given mean free path d. * * Reference: Burley 2015, "Extending the Disney BRDF to a BSDF with Integrated Subsurface Scattering" */ export declare function burleyProfile(r: number, d: number, A?: number): number; /** * Sample Burley profile across R, G, B channels. * scatterRadius = mean free path per channel. */ export declare function burleyProfileRGB(r: number, scatterRadius: RGB): RGB; /** * Christensen–Burley profile (fitted polynomial, cheaper to evaluate). * From "An Approximate Reflectance Profile for Efficient Subsurface Scattering" * * R(r) = (e^(-A*r/d) + e^(-A*r/(3d))) * A / (8πd) */ export declare function christensenProfile(r: number, d: number, A?: number): number; /** * Gaussian sum blur weights (Jimenez 2012 Separable SSS). * Returns N weight-variance pairs [{ weight, variance }] per channel. * * The kernel width is controlled by scatterRadius. */ export declare function buildSeparableSSSKernel(scatterRadius: RGB, numGaussians?: number): Array<{ weight: number; stddev: RGB; }>; /** * Evaluate a separable Gaussian blur at offset x (signed, in world units). * Returns RGB weight. */ export declare function evalSeparableKernel(kernel: Array<{ weight: number; stddev: RGB; }>, x: number): RGB; /** * Thin-slab transmission amount using Beer-Lambert approximation. * thickness: 0 = thin (high transmission), 1 = thick (low transmission). * Returns transmission factor [0, 1]. */ export declare function thinSlabTransmission(thickness: number, config: Pick): RGB; export declare class SSSMaterial { private config; constructor(config?: Partial); getConfig(): Readonly; setModel(model: SSSModel): void; setTransmission(t: number): void; setThickness(t: number): void; addLayer(layer: SSSLayer): void; getLayerCount(): number; /** * Evaluate SSS diffusion at a surface point for a given light exit radius. * r: distance between light entry and exit point on the surface. */ evaluate(r: number): RGB; /** Evaluate thin-slab transmission at the material's configured thickness */ getTransmission(thicknessOverride?: number): RGB; /** Get Separable SSS kernel for this material (first layer) */ getKernel(numGaussians?: number): ReturnType; } export declare const SSS_PRESETS: { /** Human skin: epidermis (yellow tint) + dermis (red) */ humanSkin: () => SSSMaterial; /** Wax candle (high SSS, warm light transmission) */ wax: () => SSSMaterial; /** Jade gemstone (cool, dense SSS) */ jade: () => SSSMaterial; /** Marble (dense, RGB-balanced) */ marble: () => SSSMaterial; /** Leaf / plant (very thin, high transmission) */ leaf: () => SSSMaterial; }; //# sourceMappingURL=SubsurfaceScattering.d.ts.map