import { Storage3DTexture } from 'three/webgpu'; import type { ComputeNode, Node } from 'three/webgpu'; interface SmokeScalarTextureResource { texture: Storage3DTexture; } /** Minimal simulation controls and resources consumed by the multigrid projection graph. */ export interface SmokeMultigridSource { simRes: number; multigridMinResolution: number; multigridMaxLevels: number; subcellSolidFractions: boolean; neighborStride: Node<'float'>; inverseCellSizeSquared: Node<'vec3'>; pressureFactor: Node<'float'>; multigridCorrectionScale: Node<'float'>; multigridRecursiveCorrectionScale: Node<'float'>; _pressure3D: SmokeScalarTextureResource; _divergence3D: SmokeScalarTextureResource; } /** One resolution level in the smoke pressure V-cycle. */ export interface SmokeMultigridLevel { index: number; resolution: number; gridScale: number; dimensions: Node<'uvec3'>; dispatch: [number, number, number]; pressureTexture: Storage3DTexture; rhsTexture: Storage3DTexture; solidTexture: Storage3DTexture | null; residualTexture: Storage3DTexture | null; pressureRed?: ComputeNode; pressureBlack?: ComputeNode; residual?: ComputeNode; restrict?: ComputeNode; prolong?: ComputeNode; } /** Owned hierarchy and lifecycle returned by {@link createSmokeMultigridProjectionPasses}. */ export interface SmokeMultigridProjectionPasses { levels: SmokeMultigridLevel[]; dispose(): void; } /** * Build the multigrid V-cycle passes for the smoke pressure projection. * * Every level owns a single r32float pressure texture that the red-black SOR sweeps update in * place, so the hierarchy needs no ping-pong bookkeeping and half as many pipelines as a * two-texture design. Scalar transfer textures (rhs/residual) are r32float as well; only the * optional restricted solid field keeps four channels for its velocity payload. */ declare function createSmokeMultigridProjectionPasses(smoke: SmokeMultigridSource, solidTexture?: Storage3DTexture | null): SmokeMultigridProjectionPasses; export { createSmokeMultigridProjectionPasses };