import type { BodyConfig, SurfaceLook } from '../../types/body.types'; /** * Deterministic visual variation for a planet's ring system. * * A single annular mesh is painted using a macroscopic radial profile (8 opacity * samples, lerp-interpolated) combined with 1D micro-banding noise. The profile * is drawn from a rich archetype pool — the combination of archetype choice, * per-sample jitter, palette swaps and noise parameters produces hundreds of * visually distinct looks (thin shepherd bands, solid dense bands, icy halos, * dusty outer rings, …) without bespoke shaders. */ export interface RingVariation { /** Inner edge radius as a multiple of the planet visual radius. */ innerRatio: number; /** Outer edge radius as a multiple of the planet visual radius. */ outerRatio: number; /** Inner-edge tint (radial gradient start). */ colorInner: string; /** Outer-edge tint (radial gradient end). */ colorOuter: string; /** 8 opacity samples along the radial axis (t=0 at inner edge, t=1 at outer edge). */ profile: readonly [number, number, number, number, number, number, number, number]; /** Micro-banding frequency (number of fine rings visible across the strip). */ bandFreq: number; /** Micro-banding contrast [0..1]. Higher = sharper bright/dark alternation. */ bandContrast: number; /** Dustiness [0..1] — blend toward a diffuse uniform field (halo/nebulous look). */ dustiness: number; /** Grain amount [0..1] — amplitude of the 2D high-frequency speckle/grain layer. */ grainAmount: number; /** Grain frequency — radial scale of the speckle pattern (higher = finer grain). */ grainFreq: number; /** Global alpha multiplier [0..1]. */ opacity: number; /** Strength of the low-frequency azimuthal lobes [0..1]. Higher = more angular asymmetry. */ lobeStrength: number; /** * Keplerian differential rotation [0..1]. At 0 the ring rotates as a rigid * block (texture locked to the mesh); at 1 each radial band drifts at its * own Kepler rate (ω ∝ r^-3/2), so outer bands visibly lag behind inner * ones over time — producing Saturn-like shear spirals. */ keplerShear: number; /** Seed used by the 1D hash-noise in the shader — keeps patterns deterministic. */ noiseSeed: number; /** Archetype label — purely informational, useful for tests / debug. */ archetype: RingArchetype; } /** * Named ring-shape archetype. Each archetype maps to a fixed 8-sample * radial opacity envelope in {@link ARCHETYPE_PROFILES}, which the ring * shader then jitters per body for variety. */ export type RingArchetype = 'broad' | 'double' | 'narrow' | 'dusty' | 'triple' | 'outer' | 'shepherd' | 'quadruple' | 'skewedIn' | 'skewedOut' | 'dense' | 'sparse'; /** * Eight-sample radial opacity envelope (inner → outer). Passed verbatim to * the ring shader which interpolates between the samples along the ring * strip. */ export type Profile8 = readonly [number, number, number, number, number, number, number, number]; /** * Lookup table of 8-sample radial opacity envelopes keyed by * {@link RingArchetype}. Values are in [0, 1] and are sampled from inner to * outer edge of the ring strip. Shared between the generator and tests. */ export declare const ARCHETYPE_PROFILES: Record; /** * Canonical ordered list of all ring archetypes. Used by the generator to * uniformly pick an archetype from a PRNG draw; exposed for tests and * gallery displays. */ export declare const RING_ARCHETYPES: readonly RingArchetype[]; /** * Probability (per surface look) that a body carrying `hasRings=true` actually * produces a `RingVariation`. Physics flag is the gate; these weights merely * bias the *appearance* distribution given a candidate planet. Stars opt out * via `strategy.canHaveRings` and do not appear here. * * These could eventually be consumed by the seed generator to decide * `hasRings` itself — today the flag is set externally. */ export declare const RING_SPAWN_WEIGHTS: Record; /** * Numeric bounds used by {@link generateRingVariation}. Exposed so test * fixtures and UI sliders can share the exact `[min, max]` bounds without * hard-coding duplicates. */ export declare const RING_RANGES: { readonly innerRatio: { readonly min: 1.1; readonly max: 1.75; }; /** Thin-mode thickness added on top of innerRatio. */ readonly thinThick: { readonly min: 0.05; readonly max: 0.35; }; /** Wide-mode thickness added on top of innerRatio. */ readonly wideThick: { readonly min: 0.4; readonly max: 2.5; }; readonly opacity: { readonly min: 0.28; readonly max: 0.95; }; readonly bandFreq: { readonly min: 3; readonly max: 48; }; readonly bandContrast: { readonly min: 0.08; readonly max: 0.85; }; readonly dustiness: { readonly min: 0; readonly max: 0.9; }; readonly grainAmount: { readonly min: 0.2; readonly max: 0.95; }; readonly grainFreq: { readonly min: 90; readonly max: 520; }; readonly lobeStrength: { readonly min: 0.06; readonly max: 0.42; }; readonly keplerShear: { readonly min: 0; readonly max: 1; }; }; /** * Generates a ring variation from the shared planet PRNG. Draws the same * number of random values regardless of `hasRings`, so enabling/disabling * the flag never drifts the rest of the planet appearance. * * @param config - Planet physics config (drives palette + rejects star bodies). * @param rng - Planet-scoped PRNG (same instance as planetVariation). * @returns - A fully-populated RingVariation, or null when rings are disabled. */ export declare function generateRingVariation(config: BodyConfig, rng: () => number): RingVariation | null; //# sourceMappingURL=ringVariation.d.ts.map