UNPKG

@wolffo/three-fire

Version:

Modern TypeScript volumetric fire effect for Three.js and React Three Fiber with WebGPU support.

263 lines (258 loc) 6.97 kB
import React from 'react'; import { ReactThreeFiber } from '@react-three/fiber'; import { Texture, Color, Matrix4, Vector3, Vector4, Mesh, ShaderMaterial } from 'three'; /** * Uniforms interface for the fire shader */ interface FireShaderUniforms { /** Fire texture (grayscale mask) */ fireTex: { value: Texture | null; }; /** Fire color tint */ color: { value: Color; }; /** Current time for animation */ time: { value: number; }; /** Random seed for fire variation */ seed: { value: number; }; /** Inverse model matrix for ray marching */ invModelMatrix: { value: Matrix4; }; /** Scale of the fire object */ scale: { value: Vector3; }; /** Noise scaling parameters [x, y, z, time] */ noiseScale: { value: Vector4; }; /** Fire shape intensity */ magnitude: { value: number; }; /** Noise lacunarity (frequency multiplier) */ lacunarity: { value: number; }; /** Noise gain (amplitude multiplier) */ gain: { value: number; }; } /** * Properties for creating a Fire instance */ interface FireProps$1 { /** Fire texture (grayscale mask defining fire shape) */ fireTex: Texture; /** Fire color tint (default: 0xeeeeee) */ color?: Color | string | number; /** Ray marching iterations - higher = better quality, lower performance (default: 20) */ iterations?: number; /** Noise octaves for turbulence (default: 3) */ octaves?: number; /** Noise scaling parameters [x, y, z, time] (default: [1, 2, 1, 0.3]) */ noiseScale?: [number, number, number, number]; /** Fire shape intensity (default: 1.3) */ magnitude?: number; /** Noise lacunarity - frequency multiplier (default: 2.0) */ lacunarity?: number; /** Noise gain - amplitude multiplier (default: 0.5) */ gain?: number; } /** * Volumetric fire effect using ray marching shaders * * Creates a procedural fire effect that renders as a translucent volume. * The fire shape is defined by a grayscale texture, with white areas being * the most dense part of the fire. * * @example * ```ts * const texture = textureLoader.load('fire.png') * const fire = new Fire({ * fireTex: texture, * color: 0xff4400, * magnitude: 1.5 * }) * scene.add(fire) * * // In animation loop * fire.update(time) * ``` */ declare class Fire extends Mesh { material: ShaderMaterial & { uniforms: FireShaderUniforms; }; private _time; /** * Creates a new Fire instance * * @param props - Configuration options for the fire effect */ constructor({ fireTex, color, iterations, octaves, noiseScale, magnitude, lacunarity, gain, }: FireProps$1); /** * Updates the fire animation and matrix uniforms * * Call this method in your animation loop to animate the fire effect. * * @param time - Current time in seconds (optional) * * @example * ```ts * function animate() { * fire.update(performance.now() / 1000) * renderer.render(scene, camera) * requestAnimationFrame(animate) * } * ``` */ update(time?: number): void; /** * Current animation time in seconds */ get time(): number; set time(value: number); /** * Fire color tint * * @example * ```ts * fire.fireColor = 'orange' * fire.fireColor = 0xff4400 * fire.fireColor = new Color(1, 0.5, 0) * ``` */ get fireColor(): Color; set fireColor(color: Color | string | number); /** * Fire shape intensity * * Higher values create more dramatic fire shapes. * Range: 0.5 - 3.0, Default: 1.3 */ get magnitude(): number; set magnitude(value: number); /** * Noise lacunarity (frequency multiplier) * * Controls how much the frequency increases for each noise octave. * Range: 1.0 - 4.0, Default: 2.0 */ get lacunarity(): number; set lacunarity(value: number); /** * Noise gain (amplitude multiplier) * * Controls how much the amplitude decreases for each noise octave. * Range: 0.1 - 1.0, Default: 0.5 */ get gain(): number; set gain(value: number); } declare module '@react-three/fiber' { interface ThreeElements { fire: ReactThreeFiber.Object3DNode<Fire, typeof Fire>; } } /** * Props for the Fire React component */ interface FireProps extends Omit<FireProps$1, 'fireTex'> { /** Fire texture URL or Three.js Texture object */ texture: string | Texture; /** Auto-update time from useFrame (default: true) */ autoUpdate?: boolean; /** Custom update function called each frame */ onUpdate?: (fire: Fire, time: number) => void; /** Child components */ children?: React.ReactNode; /** Position in 3D space */ position?: [number, number, number]; /** Rotation in radians */ rotation?: [number, number, number]; /** Scale factor (uniform or per-axis) */ scale?: [number, number, number] | number; } /** * Ref interface for imperative fire control */ interface FireRef { /** Fire mesh instance */ fire: Fire | null; /** Update fire animation manually */ update: (time?: number) => void; } /** * React Three Fiber component for volumetric fire effect * * Creates a procedural fire effect that can be easily integrated into R3F scenes. * The component automatically handles texture loading, animation updates, and * provides props for all fire parameters. * * @example * ```tsx * <Canvas> * <Fire * texture="/fire.png" * color="orange" * magnitude={1.5} * scale={[2, 3, 2]} * position={[0, 0, 0]} * /> * </Canvas> * ``` * * @example With custom animation * ```tsx * <Fire * texture="/fire.png" * onUpdate={(fire, time) => { * fire.fireColor.setHSL((time * 0.1) % 1, 1, 0.5) * }} * /> * ``` */ declare const FireComponent: React.ForwardRefExoticComponent<FireProps & React.RefAttributes<FireRef>>; /** * Hook for easier access to fire instance and controls * * Provides a ref and helper methods for controlling fire imperatively. * * @returns Object with ref, fire instance, and update method * * @example * ```tsx * function MyComponent() { * const fireRef = useFire() * * const handleClick = () => { * if (fireRef.fire) { * fireRef.fire.magnitude = 2.0 * } * } * * return ( * <Fire ref={fireRef.ref} texture="/fire.png" /> * ) * } * ``` */ declare const useFire: () => { /** Ref to pass to Fire component */ ref: React.RefObject<FireRef>; /** Fire mesh instance (null until mounted) */ fire: Fire | null; /** Update fire animation manually */ update: (time?: number) => void | undefined; }; export { FireComponent as Fire, useFire }; export type { FireProps, FireRef };