Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/vaneenige/phenomenon/llms.txt

Use this file to discover all available pages before exploring further.

This example demonstrates how to create a basic particle system with Phenomenon. You’ll learn how to set up the renderer, define attributes, and render particles to the screen.

View live demo

See this example running on CodePen

Complete example

Here’s a complete working example that creates a particle system with 10,000 particles:
import Phenomenon from 'phenomenon';

// Create the renderer
const phenomenon = new Phenomenon({
  settings: {
    devicePixelRatio: 1,
    position: { x: 0, y: 0, z: 3 },
  },
});

// The amount of particles to create
const multiplier = 10000;

// Define attributes for each particle
const attributes = [
  {
    name: 'aPosition',
    data: () => [
      Math.random() * 2 - 1,  // x
      Math.random() * 2 - 1,  // y
      Math.random() * 2 - 1   // z
    ],
    size: 3,
  },
  {
    name: 'aColor',
    data: () => [
      Math.random(),  // r
      Math.random(),  // g
      Math.random()   // b
    ],
    size: 3,
  },
];

// Vertex shader
const vertex = `
  attribute vec3 aPosition;
  attribute vec3 aColor;

  uniform mat4 uProjectionMatrix;
  uniform mat4 uModelMatrix;
  uniform mat4 uViewMatrix;

  varying vec3 vColor;

  void main(){
    gl_Position = uProjectionMatrix * uModelMatrix * uViewMatrix * vec4(aPosition, 1.0);
    gl_PointSize = 1.0;
    vColor = aColor;
  }
`;

// Fragment shader
const fragment = `
  precision mediump float;

  varying vec3 vColor;

  void main(){
    gl_FragColor = vec4(vColor, 1.0);
  }
`;

// Add the particle instance
phenomenon.add('particles', {
  attributes,
  multiplier,
  vertex,
  fragment,
});

Breaking down the code

Create the renderer

The renderer is the main entry point for Phenomenon:
const phenomenon = new Phenomenon({
  settings: {
    devicePixelRatio: 1,
    position: { x: 0, y: 0, z: 3 },
  },
});
  • devicePixelRatio - Controls the resolution (1 for best performance)
  • position - Camera position in 3D space

Define attributes

Attributes store data for each particle:
const attributes = [
  {
    name: 'aPosition',     // Name used in shaders
    data: () => [...],     // Function that returns data
    size: 3,               // Number of values (x, y, z)
  },
];
The data function is called once for each particle. It should return an array of values matching the specified size.
Use the multiplier parameter to control how many times the attributes are generated. This creates the total number of particles.

Write shaders

Vertex shader

The vertex shader positions each particle in 3D space:
attribute vec3 aPosition;
attribute vec3 aColor;

uniform mat4 uProjectionMatrix;
uniform mat4 uModelMatrix;
uniform mat4 uViewMatrix;

varying vec3 vColor;

void main(){
  gl_Position = uProjectionMatrix * uModelMatrix * uViewMatrix * vec4(aPosition, 1.0);
  gl_PointSize = 1.0;
  vColor = aColor;
}
  • Attributes are read from the GPU buffers
  • Uniforms are shared across all particles
  • gl_PointSize controls particle size
  • vColor passes data to the fragment shader

Fragment shader

The fragment shader determines the color of each particle:
precision mediump float;

varying vec3 vColor;

void main(){
  gl_FragColor = vec4(vColor, 1.0);
}

Add the instance

Finally, add the particle instance to the renderer:
phenomenon.add('particles', {
  attributes,
  multiplier,
  vertex,
  fragment,
});
The renderer will automatically start rendering the particles.

Next steps

Transitions

Learn how to animate particles between positions

Shapes

Create 3D shapes with particles

Build docs developers (and LLMs) love