@momentchan/particle-system
v1.0.0
Published
Modular particle system library for React Three Fiber
Readme
Particle System Library
A comprehensive, modular particle system library for React Three Fiber that allows easy customization of both initial data and behaviors through a class-based architecture.
Features
- Modular Architecture: Well-organized modules for configurations, behaviors, and shaders
- Class-Based Customization: Extend base classes to create custom particle configurations and behaviors
- Built-in Patterns: Pre-built configurations for common particle patterns
- Custom Shaders: Support for custom GLSL shaders with utility functions
- TypeScript Support: Full type safety and IntelliSense support
- Performance Optimized: GPU-based particle simulation using WebGL
- Easy Integration: Simple API that works seamlessly with React Three Fiber
Quick Start
import { ParticleSystem, SpherePositionConfig, RadialVelocityConfig, GradientColorConfig } from './particle-system';
function MyScene() {
return (
<ParticleSystem
count={256}
config={{
position: new SpherePositionConfig(2.0, [0, 0, 0]),
velocity: new RadialVelocityConfig(0.2),
color: new GradientColorConfig([1, 0, 0], [0, 1, 0]),
size: new UniformSizeConfig(0.1)
}}
behavior={new GravityBehavior()}
/>
);
}Architecture
Core Modules
- Configuration Module (
./config/): Handles initial particle data - Behavior Module (
./behaviors/): Defines particle movement and interaction - Shader Module (
./shaders/): Provides shader utilities and templates - Main Component (
ParticleSystem.tsx): The main React component
Configuration Classes
Position Configurations
GridPositionConfig: Arranges particles in a grid patternRandomPositionConfig: Randomly distributes particles within boundsSpherePositionConfig: Positions particles on a sphere surfaceCubePositionConfig: Randomly distributes particles within a cube
Velocity Configurations
ZeroVelocityConfig: No initial velocityRandomVelocityConfig: Random velocities with specified magnitudeRadialVelocityConfig: Velocities pointing outward from centerTangentialVelocityConfig: Velocities perpendicular to radial direction
Color Configurations
UniformColorConfig: Single color for all particlesRandomColorConfig: Random colors within specified rangesGradientColorConfig: Smooth color transition across particles
Size Configurations
UniformSizeConfig: Same size for all particlesRandomSizeConfig: Random sizes within specified range
Behavior Classes
Built-in Behaviors
DefaultBehavior: Simple movement with dampingGravityBehavior: Gravity simulation with bouncing boundariesSwirlBehavior: Swirling motion around centerAttractorBehavior: Particles attracted to a specific pointWaveBehavior: Wave-like motionExplosionBehavior: Explosion-like outward force
Creating Custom Configurations
Custom Position Configuration
class SpiralPositionConfig extends ParticlePositionConfig {
constructor(
private radius: number = 2.0,
private height: number = 1.0,
private turns: number = 3.0
) {
super();
}
generatePosition(index: number, totalCount: number, size: number): [number, number, number, number] {
const t = index / totalCount;
const angle = t * this.turns * Math.PI * 2;
const r = t * this.radius;
const x = Math.cos(angle) * r;
const y = t * this.height - this.height / 2;
const z = Math.sin(angle) * r;
return [x, y, z, 0.0];
}
}Custom Behavior
class FireBehavior extends ParticleBehavior {
getName(): string {
return 'Fire';
}
getPositionShader(): string {
return /*glsl*/ `
uniform float time;
uniform float delta;
uniform sampler2D positionTex;
uniform sampler2D velocityTex;
void main() {
vec2 uv = gl_FragCoord.xy / resolution.xy;
vec4 pos = texture2D(positionTex, uv);
vec4 vel = texture2D(velocityTex, uv);
pos.xyz += vel.xyz * delta;
// Reset particles that go too high
if (pos.y > 5.0) {
pos.y = -5.0;
pos.x = (uv.x - 0.5) * 2.0;
pos.z = (uv.y - 0.5) * 2.0;
}
pos.w = mod(pos.w + delta, 1.0);
gl_FragColor = pos;
}
`;
}
getVelocityShader(): string {
return /*glsl*/ `
uniform float time;
uniform float delta;
uniform sampler2D positionTex;
uniform sampler2D velocityTex;
void main() {
vec2 uv = gl_FragCoord.xy / resolution.xy;
vec4 vel = texture2D(velocityTex, uv);
vec4 pos = texture2D(positionTex, uv);
// Fire-like upward motion with turbulence
vel.y += 0.1 * delta;
// Add turbulence
float noise1 = sin(pos.x * 0.1 + time) * 0.05;
float noise2 = cos(pos.z * 0.1 + time * 0.7) * 0.05;
vel.x += noise1;
vel.z += noise2;
// Damping
vel.xyz *= 0.98;
gl_FragColor = vel;
}
`;
}
}Shader Utilities
Using ShaderBuilder
import { ShaderBuilder, ShaderTemplates } from './particle-system';
const customShader = new ShaderBuilder()
.setPositionShader(ShaderTemplates.gravity.position)
.setVelocityShader(ShaderTemplates.gravity.velocity)
.addUniform('gravity', -0.2)
.addUniform('damping', 0.99)
.build();Using Shader Templates
import { ShaderTemplates, ShaderUtils } from './particle-system';
// Use built-in template with customizations
const customGravityShader = ShaderUtils.createCustomShader(
ShaderTemplates.gravity.velocity,
{ gravity: -0.2, damping: 0.99 }
);Examples
Basic Usage
import { BasicExamples } from './examples/BasicExamples';
function App() {
return <BasicExamples />;
}Custom Configurations
import { CustomExamples } from './examples/CustomExamples';
function App() {
return <CustomExamples />;
}Advanced Features
import { AdvancedExamples } from './examples/AdvancedExamples';
function App() {
return <AdvancedExamples />;
}API Reference
ParticleSystem Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| count | number | 1024 | Number of particles |
| config | ParticleSystemConfig | undefined | Initial data configuration |
| behavior | ParticleBehavior | DefaultBehavior | Particle behavior |
| positionShader | string | undefined | Custom position shader (legacy) |
| velocityShader | string | undefined | Custom velocity shader (legacy) |
ParticleSystemConfig Interface
interface ParticleSystemConfig {
position?: ParticlePositionConfig;
velocity?: ParticleVelocityConfig;
color?: ParticleColorConfig;
size?: ParticleSizeConfig;
age?: ParticleAgeConfig;
}Base Classes
ParticlePositionConfig
abstract class ParticlePositionConfig {
abstract generatePosition(index: number, totalCount: number, size: number): [number, number, number, number];
}ParticleVelocityConfig
abstract class ParticleVelocityConfig {
abstract generateVelocity(index: number, totalCount: number, size: number): [number, number, number, number];
}ParticleColorConfig
abstract class ParticleColorConfig {
abstract generateColor(index: number, totalCount: number): [number, number, number];
}ParticleSizeConfig
abstract class ParticleSizeConfig {
abstract generateSize(index: number, totalCount: number): number;
}ParticleBehavior
abstract class ParticleBehavior {
abstract getPositionShader(): string;
abstract getVelocityShader(): string;
abstract getName(): string;
}Performance Considerations
- Particle Count: Higher particle counts require more GPU memory and processing power
- Shader Complexity: Complex shaders can impact performance
- Update Frequency: The system updates at 60fps by default
- Memory Usage: Each particle uses 4 floats for position and 4 floats for velocity
Browser Support
- WebGL 2.0 support required
- Modern browsers (Chrome 56+, Firefox 51+, Safari 15+)
- Mobile browsers with WebGL support
Contributing
- Fork the repository
- Create a feature branch
- Add your custom configurations or behaviors
- Write tests and documentation
- Submit a pull request
License
MIT License - see LICENSE file for details.
