import type { AutoExposureConfig } from "./colorPipeline.js"; /** * Renderer tone-mapping curve applied by the post chain's output stage. `"agx"` is the pipeline * default: it keeps hue in saturated highlights and rolls a sun-lit surface off gradually, where * `"aces"` skews bright colours toward white. */ export type ToneMappingMode = "aces" | "agx" | "reinhard" | "cineon" | "linear" | "none"; /** * A baked display-space LUT cube: `size³` RGB entries with red varying fastest, three bytes per entry * in 0..255. Kept as plain data so a scene document can author one and a test can assert on it. */ export interface LutCube { /** Edge length of the cube, 2..16. */ size: number; /** `size³ × 3` bytes, red fastest, then green, then blue. */ data: Uint8Array; } /** A grade's LUT: a strip PNG (one `size`-wide tile per blue slice) or a baked cube. */ export type GradeLut = { url: string; size?: number; } | { cube: LutCube; }; /** UnrealBloom stage — soft HDR glow around bright pixels (sun, glints, emissive). */ export interface BloomConfig { /** Glow intensity. Default 0.32. */ strength?: number; /** Glow spread radius, 0..1. Default 0.55. */ radius?: number; /** * Luminance above which a pixel blooms. Default 0.85. Measured on raw HDR * before the tone-map/exposure stage, so lowering `exposure` does not change * which pixels bloom — push past 1.0 to select only emissives. */ threshold?: number; } /** Ground-truth ambient occlusion stage — darkens contact creases and cavities for depth. */ export interface AoConfig { /** Sample radius in world units. Default 1.8. */ radius?: number; /** Occlusion strength multiplier. Default 2.4. */ intensity?: number; /** Distance over which occlusion fades out, world units. Default 3.6. */ distanceFalloff?: number; /** Blend the AO onto the beauty at this fraction, 0..1. Default 1. */ blend?: number; } /** Final colour-grade stage: lift/gain/gamma, saturation, vignette, film grain — applied in display space after tone mapping. */ export interface GradeConfig { /** * Colour LUT applied after the numeric grade, in display space. Either a strip PNG (one * `size`-wide tile per blue slice, trilinearly sampled) or a baked {@link LutCube} such as the one * a scene document's authored grading produces. */ lut?: GradeLut; /** Additive shadow tint (RGB, ~0..0.1). Default cool [0.012, 0.010, 0.018]. */ lift?: readonly [number, number, number]; /** Multiplicative highlight tint (RGB, ~1). Default warm [1.05, 1.02, 0.98]. */ gain?: readonly [number, number, number]; /** Output gamma. Default 0.96. */ gamma?: number; /** Saturation multiplier around luma. Default 1.12. */ saturation?: number; /** Vignette darkening strength at the corners, 0..1. Default 0.2. */ vignette?: number; /** Animated film-grain amplitude. Default 0.012. */ grain?: number; /** Chromatic-aberration RGB split, in fractions of the frame (~0..0.01), scaled toward the edges. Default 0 (off). */ chromaticAberration?: number; } /** Depth-of-field (bokeh) stage — throws the fore/background out of focus around a focus distance. */ export interface DofConfig { /** Focus distance from the camera in world units. Default 18. */ focus?: number; /** Aperture — larger blurs a shallower slice more aggressively. Default 0.00025. */ aperture?: number; /** Maximum blur radius, 0..1. Default 0.01. */ maxBlur?: number; } /** Ink outlines traced from depth and surface-normal edges — silhouettes plus interior creases. */ export interface OutlineConfig { /** Line colour (CSS). Default near-black "#101014". */ color?: string; /** Line thickness in render pixels. Default 1. */ thickness?: number; /** Line opacity, 0..1. Default 1. */ opacity?: number; /** Relative depth jump that counts as a silhouette edge. Lower draws more lines. Default 0.08. */ depthThreshold?: number; /** Normal difference (1 − cos angle) that counts as a crease. Lower draws more lines. Default 0.35. */ normalThreshold?: number; /** Distance in world units at which lines have faded out, so far scenery stays clean. Default 160. */ fadeDistance?: number; } /** * Art-style stage that turns the same models and lighting into a different look without * touching materials: ink outlines (comic / Borderlands), cel bands (cartoon), pixelation (retro). * Runs after tone mapping, before the grade. */ export interface StylizeConfig { /** Ink outlines. Omitted or `false` draws none. */ outline?: OutlineConfig | false; /** Quantize brightness into this many cel-shading bands, keeping hue. 0 or omitted is off; 3–6 reads as cartoon. */ bands?: number; /** Snap the frame to blocks of this many render pixels for a retro look. 0, 1 or omitted is off. */ pixelSize?: number; } /** * Edge antialiasing for the post chain. SMAA runs in linear-sRGB before the output * tone-map and cleans alpha-tested foliage/particles that MSAA samples alone leave crawling. * `"msaa"` keeps only the render-target multisample resolve; `false` disables AA stages. */ export type PostAaMode = "smaa" | "msaa" | false; /** * Declarative post-processing chain (RenderPass → AO → Bloom → SMAA → tone-map output → * Grade). Present on a game means the shell mounts an `EffectComposer` and owns * the render; absent means the renderer draws directly (unchanged). Each stage is * a config object, `false` to skip, or omitted for its default. Pure data — no * three.js types leak into core. */ export interface PostProcessingConfig { /** Master switch; a config object with `enabled: false` mounts nothing. Default true. */ enabled?: boolean; /** Tone-mapping curve the output stage applies. Default "agx". */ toneMapping?: ToneMappingMode; /** * Exposure multiplier applied before tone mapping. Default 1. With `autoExposure` on this is the * baseline the meter corrects around, not a fixed value. */ exposure?: number; /** * Clamped auto-exposure: meters the rendered frame and adapts exposure toward * {@link import("./colorPipeline.js").MID_GREY}, bounded by `min`/`max`. Omitted uses * {@link import("./colorPipeline.js").DEFAULT_AUTO_EXPOSURE} on every tier; `false` pins `exposure`. */ autoExposure?: AutoExposureConfig | false; /** * Antialiasing. Default `"smaa"` (plus a light MSAA resolve on the beauty target). * Set `"msaa"` to skip the SMAA pass, or `false` for neither. */ aa?: PostAaMode; bloom?: BloomConfig | false; /** * Ambient occlusion (contact shading). Omitted runs {@link DEFAULT_AO} on graphics tiers whose * `postStages.ao` is on (medium and up); `false` turns it off everywhere. */ ao?: AoConfig | false; /** Depth-of-field / bokeh. Heavier stage — omit or `false` to skip. Default off (omitted). */ dof?: DofConfig | false; grade?: GradeConfig | false; /** Art-style stage: outlines, cel bands, pixelation. Default off (omitted). */ stylize?: StylizeConfig | false; } /** Contact shading used when a post chain leaves `ao` unset: soft creases, no dark halos. */ export declare const DEFAULT_AO: Readonly; /** * A cinematic "product shot" post preset — the full chain on (contact-AO, soft bloom, a warm film * grade with vignette + a touch of grain + chromatic aberration). Meant for a `StudioStage` where a * single parametric asset is framed on a backdrop, so every studio reads shipped, not intern-tier. DoF * is left off by default (it needs a per-scene focus distance); set `dof` to enable it. */ export declare const STUDIO_STAGE_POST: PostProcessingConfig;