three.quarks

repository·master·Indexed 21 days ago

https://github.com/alchemist0823/three.quarks

A high-performance particle system and visual effects library for three.js designed for real-time VFX in games and interactive web applications. It features a BatchedRenderer for optimized draw calls, various emitter shapes (Point, Sphere, Cone, etc.), and particle behaviors for animating size, color, and speed over lifetime. The ecosystem includes the main three.quarks package, a zero-dependency core (quarks.core), and a declarative React Three Fiber integration (quarks.r3f) providing components like <QuarksProvider>, <ParticleSystem>, and <QuarksEffect>.

Tokens
31.9K
Snippets
105
Records
133
Agent score
77%

What's inside three.quarks

  1. Configure particle behaviors and emitter shapes

    master

    Particle systems in quarks.r3f use classes from three.quarks to define how particles behave over time and where they are emitted.

    Behaviors

    Use behaviors like SizeOverLife, ColorOverLife, and SpeedOverLife to animate particles. These often take PiecewiseBezier or Gradient objects.

    import {
        SizeOverLife,
        ColorOverLife,
        SpeedOverLife,
        Gradient,
        PiecewiseBezier,
        Bezier,
        Vector4,
    } from 'three.quarks'
    
    const behaviors = useMemo(() => [
        // Size fades out
        new SizeOverLife(new PiecewiseBezier([[new Bezier(1, 0.8, 0.4, 0), 0]])),
    
        // Color gradient
        new ColorOverLife(new Gradient([
            [new Vector4(1, 0.8, 0.2, 1), 0],
            [new Vector4(1, 0.3, 0.1, 1), 0.5],
            [new Vector4(0.5, 0.1, 0.1, 0), 1],
        ])),
    
        // Speed decay
        new SpeedOverLife(new PiecewiseBezier([[new Bezier(1, 0.5, 0.2, 0), 0]])),
    ], [])
    
    <ParticleSystem behaviors={behaviors} ... />

    Emitter Shapes

    Import shapes from three.quarks to define the emission volume:

    • ConeEmitter: Good for fire or fountains. Requires angle, radius, and arc.
    • SphereEmitter: Good for explosions or magic effects. Requires radius and thickness.
    • PointEmitter: Emits from a single point.
    import { ConeEmitter, SphereEmitter, PointEmitter } from 'three.quarks'
    
    const cone = new ConeEmitter({ angle: 0.3, radius: 0.2, arc: Math.PI * 2 })
    const sphere = new SphereEmitter({ radius: 0.5, thickness: 0.2 })
    const point = new PointEmitter()
    import {
        SizeOverLife,
        ColorOverLife,
        SpeedOverLife,
        Gradient,
        PiecewiseBezier,
        Bezier,
        Vector4,
    } from 'three.quarks'
    
    const behaviors = useMemo(() => [
        new SizeOverLife(new PiecewiseBezier([[new Bezier(1, 0.8, 0.4, 0), 0]])),
        new ColorOverLife(new Gradient([
            [new Vector4(1, 0.8, 0.2, 1), 0],
            [new Vector4(1, 0.3, 0.1, 1), 0.5],
            [new Vector4(0.5, 0.1, 0.1, 0), 1],
        ])),
        new SpeedOverLife(new PiecewiseBezier([[new Bezier(1, 0.5, 0.2, 0), 0]])),
    ], [])
    
    <ParticleSystem behaviors={behaviors} ... />
  2. Configure particle systems with functions, shapes, and behaviors

    master

    When defining or extending particle systems, you can utilize several modular components found in quarks.core:

    • Functions: Use these as parameters within a particle system to define dynamic values or types.
    • Shapes: Predefined emitter shapes that determine the spatial distribution of particles when they are emitted.
    • Behaviors: Predefined logic that can be attached to a ParticleSystem to modify particle properties over time. For example, SizeOverLife allows a particle's size to change throughout its lifespan.
  3. Understand the core components of three.quarks

    master

    The three.quarks library is built around several key abstractions that manage the lifecycle, simulation, and rendering of particle effects:

    • ParticleEmitter: A three.js Object3D that serves as the reference point for particle emission. It can be attached to any existing Object3D in your scene.
    • ParticleSystem: Represents an individual instance of a particle or trail system. It is responsible for simulating the particles within that specific system.
    • BatchedRenderer: A central manager that handles the rendering of all particle systems. To optimize performance, a three.js scene should only contain one BatchedRenderer. It groups all ParticleSystem instances that share the same rendering pipeline into a single VFXBatch to minimize draw calls.
    • QuarksLoader: A utility used to load particle systems from JSON files. The JSON format used is compatible with the standard three.js JSON format.
  4. How `<QuarksProvider>` works

    master

    <QuarksProvider> is a required wrapper component. It manages the BatchedRenderer used by all child particle systems to ensure efficient rendering. All <ParticleSystem /> or <QuarksEffect /> components must be descendants of a <QuarksProvider> within your <Canvas>.

    <Canvas>
        <QuarksProvider>
            {/* All particle systems must be children of QuarksProvider */}
            <ParticleSystem ... />
        </QuarksProvider>
    </Canvas>
  5. Use quarks.r3f with React Three Fiber

    master

    For declarative React integration, use the quarks.r3f package.

    Installation:

    npm install quarks.r3f three.quarks

    Usage: Wrap your application in a <QuarksProvider> and use the <ParticleSystem /> component. You can pass props like duration, looping, startLife (as an array), startSize, startColor (as an object), and behaviors (as an array of behavior instances).

    import { Canvas } from '@react-three/fiber'
    import { QuarksProvider, ParticleSystem } from 'quarks.r3f'
    import { ConeEmitter, SizeOverLife, PiecewiseBezier, Bezier, RenderMode } from 'three.quarks'
    
    function FireEffect() {
        const shape = useMemo(() => new ConeEmitter({ angle: 0.3, radius: 0.2 }), [])
        const behaviors = useMemo(() => [
            new SizeOverLife(new PiecewiseBezier([[new Bezier(1, 0.5, 0.2, 0), 0]]))
        ], [])
    
        return (
            <ParticleSystem
                duration={5}
                looping
                startLife={[1, 2]}
                startSpeed={[2, 4]}
                startSize={0.5}
                startColor={{ r: 1, g: 0.5, b: 0.2, a: 1 }}
                emissionOverTime={40}
                shape={shape}
                renderMode={RenderMode.BillBoard}
                behaviors={behaviors}
                position={[0, 0, 0]}
                autoPlay
            />
        )
    }
    
    function App() {
        return (
            <Canvas>
                <QuarksProvider>
                    <FireEffect />
                </QuarksProvider>
            </Canvas>
        )
    }
  6. Install quarks.r3f and three.quarks

    master

    To use the React Three Fiber integration for particle systems, install both quarks.r3f and the core three.quarks package via npm:

    npm install quarks.r3f three.quarks
  7. Load VFX from JSON

    master

    You can export particle effects from the three.quarks-editor and load them at runtime using QuarksLoader.

    To play multiple instances of a loaded effect:

    1. Use loadedEffect.clone() to create a new instance.
    2. Add the instance to the scene.
    3. Register it with the BatchedRenderer using QuarksUtil.addToBatchRenderer(instance, batchRenderer).
    4. (Optional) Use QuarksUtil.setAutoDestroy(instance, true) to automatically clean up the instance when it finishes playing.
    5. Call QuarksUtil.play(instance) to start the effect.
    import { QuarksLoader, QuarksUtil, BatchedRenderer } from 'three.quarks';
    
    const batchRenderer = new BatchedRenderer();
    const loader = new QuarksLoader();
    
    loader.load('effects/explosion.json', (effect) => {
        QuarksUtil.addToBatchRenderer(effect, batchRenderer);
        scene.add(effect);
    });
    
    scene.add(batchRenderer);
    
    // Playing multiple instances
    const instance = effect.clone();
    scene.add(instance);
    QuarksUtil.addToBatchRenderer(instance, batchRenderer);
    QuarksUtil.setAutoDestroy(instance, true);
    QuarksUtil.play(instance);
  8. Quick Start with three.quarks

    master

    To use three.quarks in a vanilla Three.js project, follow these steps:

    1. Initialize a BatchedRenderer: This object manages all particle systems and optimizes draw calls. Add it to your Three.js scene.
    2. Define a ParticleSystem: Configure properties like duration, looping, startLife, startSpeed, startSize, startColor, maxParticle, emissionOverTime, shape, material, and renderMode.
    3. Add to Scene: Add the particles.emitter to the scene and register the system with the batchRenderer using batchRenderer.addSystem(particles).
    4. Update Loop: In your animation loop, call batchRenderer.update(delta) using the clock delta.
    import * as THREE from 'three';
    import {
        BatchedRenderer,
        ParticleSystem,
        ConstantValue,
        IntervalValue,
        ConstantColor,
        PointEmitter,
        RenderMode
    } from 'three.quarks';
    
    // 1. Create the batch renderer (manages all particle systems)
    const batchRenderer = new BatchedRenderer();
    scene.add(batchRenderer);
    
    // 2. Define your particle system
    const particles = new ParticleSystem({
        duration: 2,
        looping: true,
        startLife: new IntervalValue(1, 2),
        startSpeed: new ConstantValue(5),
        startSize: new IntervalValue(0.1, 0.3),
        startColor: new ConstantColor(new THREE.Vector4(1, 1, 1, 1)),
        maxParticle: 100,
        emissionOverTime: new ConstantValue(20),
        shape: new PointEmitter(),
        material: new THREE.MeshBasicMaterial({
            map: yourTexture,
            transparent: true
        }),
        renderMode: RenderMode.BillBoard
    });
    
    // 3. Add to scene and renderer
    scene.add(particles.emitter);
    batchRenderer.addSystem(particles);
    
    // 4. Update in your animation loop
    function animate() {
        const delta = clock.getDelta();
        batchRenderer.update(delta);
        renderer.render(scene, camera);
        requestAnimationFrame(animate);
    }
  9. Core components of three.quarks

    master

    The three.quarks package provides a comprehensive suite of tools for managing particle systems and visual effects (VFX) in Three.js. The main exported modules include:

    • Emitter & System Management: ParticleEmitter, ParticleSystem, and MeshSurfaceEmitter for controlling particle generation.
    • Batching & Rendering: VFXBatch, SpriteBatch, TrailBatch, BatchedRenderer, and BatchedParticleRenderer for high-performance rendering of many particles or effects.
    • Asset Loading: QuarksLoader and QuarksPrefab for loading pre-configured VFX assets.
    • Utilities & Shaders: QuarksUtil, along with various shader chunks and materials specifically designed for particle effects.
  10. Manage unified timelines with QuarksPrefab

    master

    The QuarksPrefab class (extending THREE.Group) allows you to manage multiple animations in a single unified timeline. It can synchronize both standard Three.js animations and three.quarks particle system animations.

    Key features include:

    • Unified Playback Control: Use .play(), .pause(), and .stop() to control all registered animations simultaneously.
    • Timeline Management: Set specific start times and durations for each animation component.
    • Time Seeking: Use .setTime(time) to jump to a specific point in the timeline.
    • Serialization: Save and load complex animation sequences using .toJSON() and QuarksPrefab.fromJSON(json).
    import { QuarksPrefab } from 'three.quarks';
    
    const prefab = new QuarksPrefab();
    // ... add animations ...
    prefab.play();
    
    // In your animation loop:
    function animate() {
      requestAnimationFrame(animate);
      prefab.update(); // Updates the internal clock and all animations
      renderer.render(scene, camera);
    }
  11. Understand the Particle interfaces

    master

    The project defines two primary interfaces for particle data:

    1. IParticle: The base interface containing core properties: position, velocity, age, life, size, rotation (number or Quaternion), uvTile, color, memory, and the died getter.

    2. Particle: Extends IParticle with properties required for more complex behaviors, such as speedModifier, emissionState, parentMatrix, startSpeed, startColor, and startSize.