import { Vector3, Vector4 } from 'three/webgpu'; import type { TSLFloatInput, TSLFloatNode, TSLUniformNode, TSLVec2Node, TSLVec3Node } from '../types/tsl.cjs'; export interface OceanWaveSample { x: TSLFloatInput; z: TSLFloatInput; heightAboveBed: TSLFloatInput; time: TSLFloatInput; } export interface OceanWaveDisplacementSample extends Omit { time?: TSLFloatInput | undefined; } export interface OceanSurfaceSample { x: TSLFloatInput; z: TSLFloatInput; time: TSLFloatInput; } export type OceanWaveDirection = readonly [x: number, z: number] | { x?: number | undefined; y?: number | undefined; z?: number | undefined; }; export interface OceanWaveComponentOptions { kx?: number | undefined; kz?: number | undefined; wavelength?: number | undefined; direction?: OceanWaveDirection | undefined; amplitude?: number | undefined; phase?: number | undefined; } export interface OceanWavesOptions { gravity?: number | undefined; depth?: number | undefined; components?: readonly OceanWaveComponentOptions[] | undefined; energy?: number | undefined; } export interface ResolvedOceanWaveComponent { kx: number; kz: number; amplitude: number; phase: number; k?: number; omega?: number; sinhKH?: number; } export interface OceanWaveUniforms { energy: TSLUniformNode<'float', number>; wave: TSLUniformNode<'vec4', Vector4>[]; profile: TSLUniformNode<'vec4', Vector4>[]; } export interface OceanEnvironmentOptions { gravity?: number | undefined; depth?: number | undefined; } export interface OceanComponentUpdate { amplitude?: number | undefined; phase?: number | undefined; } /** * Dispersion-matched multi-component ocean swell spectrum. * * One `OceanWaves` instance is a small set of linear (Airy) wave components in * intermediate water depth, each matched to ω = √(g·k·tanh(k·h)) in world * units so grid forcing drives free waves instead of fighting them. The same * spectrum is consumed with matched phase by every subscriber — the MLS-MPM * wavemaker (`WaterVolume`), the in-phase particle seed, a far-field skirt, * and CPU height queries — so there are no seams between them. * * All spectral constants live in uniforms: changing gravity, depth, energy, or * amplitudes never rebuilds a kernel. The number of components is fixed at * construction. * * This implementation-level API is intentionally internal and has no public package import. * * @short Dispersion-matched swell spectrum shared by MPM forcing, seeding, far field, and height queries. * @category TSL * @tags WebGPU, TSL, Water, Ocean */ export declare class OceanWaves { gravity: number; depth: number; components: ResolvedOceanWaveComponent[]; uniforms: OceanWaveUniforms; /** * @param {Object} [options] * @param {number} [options.gravity=9.81] World gravity magnitude (m/s²). * @param {number} [options.depth=1] Still-water depth (world units) used by the dispersion relation. * @param {Array} [options.components] Wave components. Each entry provides * `amplitude` (world units at energy 1), optional `phase` (radians), and a wave vector as * either `{ wavelength, direction: [x, z] }` or raw `{ kx, kz }` (radians per world unit). * @param {number} [options.energy=1] Global amplitude multiplier (uniform, animatable). */ constructor({ gravity, depth, components, energy }?: OceanWavesOptions); /** Normalize a component spec into a raw world-space wave vector + amplitude/phase. */ static resolveComponent(component: OceanWaveComponentOptions): ResolvedOceanWaveComponent; /** Global amplitude multiplier (drives every subscriber in lockstep). */ get energy(): number; set energy(value: number); /** * Re-derive the dispersion relation, e.g. after gravity or depth changes. * Uniform values update in place; no kernel rebuilds. * * @param {Object} [options] * @param {number} [options.gravity] New world gravity magnitude (m/s²). * @param {number} [options.depth] New still-water depth (world units). * @returns {this} */ setEnvironment({ gravity, depth }?: OceanEnvironmentOptions): this; /** * Update a component's amplitude and/or phase in place. * * @param {number} index Component index. * @param {Object} values `{ amplitude?, phase? }`. * @returns {this} */ setComponent(index: number, { amplitude, phase }?: OceanComponentUpdate): this; _refreshDispersion(): void; /** * @param {number} index * @param {import('../types/tsl.js').TSLFloatInput} x * @param {import('../types/tsl.js').TSLFloatInput} z * @param {import('../types/tsl.js').TSLFloatInput} time * @returns {import('../types/tsl.js').TSLFloatNode} */ _phase(index: number, x: TSLFloatInput, z: TSLFloatInput, time: TSLFloatInput): TSLFloatNode; /** * TSL: analytic orbital velocity of the summed components at a world-space * sample, using cosh/sinh depth profiles over the water column. Multiplied * by the energy uniform. * * @tsl * @param {OceanWaveSample} sample `{ x, z, heightAboveBed, time }` — world-space nodes; * `heightAboveBed` is the sample height above the sea bed, pre-clamped by the caller. * @returns {import('../types/tsl.js').TSLVec3Node} World-space orbital velocity (x, y, z), world units/s. */ orbitalVelocity({ x, z, heightAboveBed, time }: OceanWaveSample): TSLVec3Node; /** * TSL: analytic orbital displacement (ξ along the wave vector, ζ vertical) at * a world-space sample. Used to seed particles in phase at t = 0 and to * displace far-field skirt geometry. Multiplied by the energy uniform. * * @tsl * @param {OceanWaveDisplacementSample} sample `{ x, z, heightAboveBed, time }` — world-space nodes. * @returns {import('../types/tsl.js').TSLVec3Node} World-space displacement (x, y, z), world units. */ orbitalDisplacement({ x, z, heightAboveBed, time }: OceanWaveDisplacementSample): TSLVec3Node; /** * TSL: linear surface elevation η above still water at a world XZ position. * * @tsl * @param {OceanSurfaceSample} sample `{ x, z, time }` — world-space nodes. * @returns {import('../types/tsl.js').TSLFloatNode} Surface elevation, world units. */ surfaceHeight({ x, z, time }: OceanSurfaceSample): TSLFloatNode; /** * TSL: exact world-XZ gradient `(∂η/∂x, ∂η/∂z)` of the summed * linear surface spectrum. This is the shading-normal counterpart to * {@link OceanWaves#surfaceHeight}; it adds no finite-difference texture reads. * * @tsl * @param {OceanSurfaceSample} sample `{ x, z, time }` — world-space nodes. * @returns {import('../types/tsl.js').TSLVec2Node} Surface slope in world units/world unit. */ surfaceSlope({ x, z, time }: OceanSurfaceSample): TSLVec2Node; /** * CPU mirror of {@link OceanWaves#surfaceHeight}: surface elevation η above * still water, world units, including the energy multiplier. * * @param {number} x World X. * @param {number} z World Z. * @param {number} time Simulation time (s). * @returns {number} Surface elevation (world units). */ getSurfaceHeightAt(x: number, z: number, time: number): number; /** * CPU mirror of {@link OceanWaves#orbitalVelocity}. * * @param {Vector3} target Receives the world-space orbital velocity. * @param {number} x World X. * @param {number} z World Z. * @param {number} heightAboveBed Sample height above the sea bed (world units). * @param {number} time Simulation time (s). * @returns {Vector3} `target`. */ getOrbitalVelocityAt(target: Vector3 | undefined, x: number, z: number, heightAboveBed: number, time: number): Vector3; }