import { EffectConstants, EffectField, EffectSchema, EffectSchemaValue, EffectValues, SchemaToNodeType, UniformKeys } from "../materials/MaterialEffect.js"; import { Vector2, Vector3, Vector4 } from "three"; import { Entity, Trait } from "koota"; import Node from "three/src/nodes/core/Node.js"; import UniformNode from "three/src/nodes/core/UniformNode.js"; //#region src/pipeline/PassEffect.d.ts /** A post-processing pass function that transforms scene color. */ type PassEffectFn = (input: Node<'vec4'>, uv: Node<'vec2'>) => Node<'vec4'>; /** Context passed to a PassEffect's static buildPass method. */ interface PassEffectContext { /** TSL uniform nodes for each uniform schema field, keyed by field name. */ uniforms: { [K in UniformKeys]: SchemaToNodeType; }; /** Read-only constants from factory function fields. */ constants: EffectConstants; } interface FlatlandLike { _markPostPassDirty(): void; } type UniformNodeValue = UniformNode<'float', number> | UniformNode<'vec2', Vector2> | UniformNode<'vec3', Vector3> | UniformNode<'vec4', Vector4>; /** * Base class for post-processing pass effects. * * Mirrors the MaterialEffect pattern: class-based, schema-driven, with property * accessors. Uses TSL `uniform()` nodes for zero-cost runtime parameter updates — * changing a parameter updates the uniform value directly without rebuilding the * node graph. * * @example Class-based definition: * ```typescript * class CRTEffect extends PassEffect { * static readonly passName = 'crt' * static readonly passSchema = { curvature: 0.1, scanlineIntensity: 0.2 } as const * declare curvature: number * declare scanlineIntensity: number * * static buildPass({ uniforms }: PassEffectContext): PassEffectFn { * return (input, uv) => crtComplete(input, uv, { * curvature: uniforms.curvature, * scanlineIntensity: uniforms.scanlineIntensity, * }) * } * } * ``` * * @example Factory definition: * ```typescript * const VignetteEffect = createPassEffect({ * name: 'vignette', * schema: { intensity: 0.5 }, * pass: ({ uniforms }) => (input, uv) => vignette(input, uv, uniforms.intensity), * }) * ``` */ declare abstract class PassEffect { /** Unique pass name. Must be overridden by subclass. */ static readonly passName: string; /** Per-pass data schema with default values. Must be overridden by subclass. */ static readonly passSchema: EffectSchema; /** @internal Auto-generated Koota trait from schema. */ static _trait: Trait; /** @internal Computed field metadata from schema. */ static _fields: EffectField[]; /** @internal Total float slots needed for this pass's data. */ static _totalFloats: number; /** @internal Whether static initialization has been performed. */ static _initialized: boolean; /** * Build the pass function. Must be overridden by subclass (class-based path). * Called once when the pass is added to Flatland. The returned function closes * over uniform nodes for zero-cost parameter updates. */ static buildPass(_context: PassEffectContext): PassEffectFn; /** @internal Factory functions for constant fields (keyed by field name). */ static _constantFactories: Record unknown>; /** * Initialize static metadata from the schema (called once per subclass, lazily). * @internal */ static _initialize(): void; /** Pass name (from static). */ readonly name: string; /** @internal The Flatland instance this pass is attached to. */ _flatland: FlatlandLike | null; /** @internal The ECS entity for this pass. */ _entity: Entity | null; /** @internal Snapshot defaults for pre-enrollment staging. */ _defaults: Record; /** @internal Per-instance constant values (from factory function schema fields). */ _constants: Record; /** @internal TSL uniform nodes — one per uniform schema field. */ _uniforms: Record; /** @internal Cached result of buildPass(). */ _passFn: PassEffectFn | null; /** @internal Sort order (set by addPass). */ _order: number; /** @internal Whether this pass is enabled. */ private _enabled; constructor(); /** Whether this pass is enabled in the chain. */ get enabled(): boolean; /** Toggle enabled state. This is a structural change — rebuilds the chain. */ set enabled(value: boolean); /** * Attach this pass to a Flatland instance. * @internal Called by Flatland.addPass() */ _attach(flatland: FlatlandLike): void; /** * Detach this pass from its Flatland instance. * @internal Called by Flatland.removePass() */ _detach(): void; /** * Build and cache the pass function by calling the static buildPass() once. * The returned function closes over uniform nodes and constants. * @internal */ _buildPassFn(): PassEffectFn; /** * Read a field value. * If attached with an entity, reads from ECS trait. Otherwise reads from defaults. * @internal */ _getField(name: string): number | number[]; /** * Write a field value. * 1. Writes to ECS trait (if enrolled) * 2. Updates uniform.value directly (zero-cost, no rebuild) * 3. Also updates snapshot defaults * @internal */ _setField(name: string, value: number | number[]): void; } /** Configuration passed to createPassEffect(). */ interface PassEffectConfig { /** Unique name for this pass effect. */ name: string; /** Per-pass data schema — default values define types and initial values. */ schema: S; /** Pass builder: receives uniform nodes, returns a PassEffectFn. */ pass: (context: PassEffectContext) => PassEffectFn; } /** * Type for a PassEffect class created by the factory. * Instances have typed properties matching the schema. */ type PassEffectClass = { new (): PassEffect & EffectValues & EffectConstants; readonly passName: string; readonly passSchema: S; readonly _trait: Trait; readonly _fields: EffectField[]; readonly _totalFloats: number; readonly _constantFactories: Record unknown>; readonly _initialized: boolean; _initialize(): void; buildPass(context: PassEffectContext): PassEffectFn; }; /** * Create a PassEffect class from a configuration object. * * @example * ```typescript * const VignetteEffect = createPassEffect({ * name: 'vignette', * schema: { intensity: 0.5 }, * pass: ({ uniforms }) => (input, uv) => vignette(input, uv, uniforms.intensity), * }) * * const v = new VignetteEffect() * flatland.addPass(v) * v.intensity = 0.8 // zero-cost uniform update * ``` */ declare function createPassEffect(config: PassEffectConfig): PassEffectClass; //#endregion export { type EffectConstants, type EffectField, type EffectSchema, type EffectSchemaValue, type EffectValues, PassEffect, PassEffectClass, PassEffectContext, PassEffectFn, type UniformKeys, createPassEffect }; //# sourceMappingURL=PassEffect.d.ts.map