
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
three-cluster-lights
Advanced tools

The core library files for the three-cluster-lights system - a high-performance WebAssembly-powered clustered lighting solution for Three.js.
This library enables thousands of light supporting point lights, rect area lights and spotlights. Point lights support goes up to 32,000 lights in the frustum. Includes experimental shadow support via screen-space ray marching and atlas-based shadow maps.
This is only relevant if you plan on building from the source. Otherwise the npm package is far easier to consume.
lib/
├── index.js # Main entry point - exports all public APIs
├── index.d.ts # TypeScript definitions
├── package.json # NPM package configuration
├── README.md # This file
│
├── core/ # Core lighting system
│ ├── cluster-lighting-system.js # Main ClusterLightingSystem class
│ ├── cluster-shaders.js # GLSL shaders and materials
│ └── shadow-atlas.js # Shadow atlas manager (experimental)
│
├── performance/ # Performance monitoring and optimization
│ ├── performance-metrics.js # Metrics (GPUQuery, FPSMeter, etc.)
│ ├── performance-tracker.js # Unified performance tracker
│ └── adaptive-tile-span.js # Adaptive performance tuning
│
├── utils/ # Utilities
│ └── wasm-loader.js # WASM loading with fallback
│
├── visual/ # Visual debugging
│ └── light-markers.js # Visual light markers
│
└── wasm/ # WebAssembly binaries
├── cluster-lights-simd.wasm # SIMD-optimized version
├── cluster-lights.wasm # Standard version
├── cluster-lights-asm.js # JavaScript fallback
└── cluster-lights.c # Source code
import {
ClusterLightingSystem,
LightMarkers,
PerformanceTracker,
loadWasm,
LightType,
Animation
} from 'three-cluster-lights';
// Import only what you need
import { ClusterLightingSystem } from 'three-cluster-lights/core';
import { PerformanceTracker } from 'three-cluster-lights/performance';
import { loadWasm } from 'three-cluster-lights/utils';
import { LightMarkers } from 'three-cluster-lights/visual';
core/ - Core Lighting Systemcluster-lighting-system.jsMain clustered lighting system implementation. Manages light data, WASM integration, GPU clustering, and shader patching.
Main Class: ClusterLightingSystem
cluster-shaders.jsGLSL shader code specifically for clustered lighting. Includes material patching functions and shader variants.
Exports:
lights_physical_pars_fragment - Shader preamblelights_fragment_begin - Full-featured fragment shaderlights_fragment_begin_optimized - Optimized fragment shaderShaderVariants - Automatic shader variant selectiongetListMaterial() - Material for list visualizationgetMasterMaterial() - Material for master textureperformance/ - Performance Monitoringperformance-metrics.jsLow-level performance monitoring primitives for GPU timing, FPS tracking, CPU time, and memory usage.
Classes:
GPUQuery - GPU timing using WebGL timer queriesFPSMeter - Frames per second with min/max trackingCPUTimer - CPU frame time measurementMemoryMonitor - JavaScript heap memory trackingperformance-tracker.jsHigh-level unified performance tracker with automatic HTML/CSS injection.
Class: PerformanceTracker
adaptive-tile-span.jsAdaptive performance tuning that automatically adjusts rendering quality based on target FPS.
Class: AdaptiveTileSpan
visual/ - Visual Debugginglight-markers.jsVisual markers for displaying light positions in the scene with instanced rendering.
Class: LightMarkers
utils/ - Utilitieswasm-loader.jsHelper utility for loading WebAssembly modules with automatic SIMD detection and ASM.js fallback.
Function: loadWasm(options)
The library includes pre-compiled WASM binaries, but you can rebuild them if needed.
Install Emscripten:
# Install emsdk
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk
./emsdk install latest
./emsdk activate latest
source ./emsdk_env.sh
From the lib/ directory:
# Build standard WASM (no SIMD)
npm run build:wasm
# Build SIMD-optimized WASM (requires SIMD support)
npm run build:wasm-simd
# Build ASM.js fallback (for environments without WebAssembly)
npm run build:asm
# Build all versions
npm run build:all
wasm/cluster-lights.wasm - Standard WebAssembly module (~50KB)wasm/cluster-lights-simd.wasm - SIMD-optimized version (~55KB)wasm/cluster-lights-asm.js - JavaScript fallback (~100KB)The WASM modules are compiled from wasm/cluster-lights.c, which implements:
The SIMD version includes:
-msimd128 - Enable 128-bit SIMD operations-msse, -msse2, -msse3, -msse4.1 - Enable SSE instructions--closure 1 - Google Closure Compiler optimizations-flto - Link-time optimizationHigh-performance clustered lighting system powered by WebAssembly.
const lights = new ClusterLightingSystem(
renderer, // THREE.WebGLRenderer
wasmModule, // WebAssembly module instance
near, // Camera near plane
far, // Camera far plane
sliceX, // Cluster grid X resolution
sliceY, // Cluster grid Y resolution
sliceZ, // Cluster grid Z resolution
performanceMode // Optional: enable performance optimizations (default: true)
);
// Add a light (returns global light index)
const index = lights.addLight({
type: LightType.POINT, // or 'point', 'spot', 'rect'
position: new THREE.Vector3(0, 5, 0),
color: new THREE.Color(1, 0, 0),
intensity: 10,
radius: 15,
decay: 2,
visible: true,
animation: {
circular: { speed: 1, radius: 5 },
pulse: { speed: 1, amount: 0.5, target: PulseTarget.INTENSITY }
}
});
// Fast light addition (skips some checks for bulk operations)
lights.addFastLight(lightConfig);
// Remove a light
lights.removeLight(globalIndex);
lights.updateLightPosition(globalIndex, position);
lights.updateLightColor(globalIndex, color);
lights.updateLightIntensity(globalIndex, intensity);
lights.updateLightRadius(globalIndex, radius);
lights.updateLightDecay(globalIndex, decay);
lights.updateLightVisibility(globalIndex, visible);
lights.updateLightAnimation(globalIndex, animationConfig);
// Pulse animation
lights.updatePulseSpeed(globalIndex, speed);
lights.updatePulseAmount(globalIndex, amount);
// Flicker animation
lights.updateFlickerIntensity(globalIndex, intensity);
lights.updateFlickerSpeed(globalIndex, speed);
// Wave animation
lights.updateWaveSpeed(globalIndex, speed);
lights.updateWaveAmplitude(globalIndex, amplitude);
// Circular animation
lights.updateCircularSpeed(globalIndex, speed);
lights.updateCircularRadius(globalIndex, radius);
// Rotation animation
lights.updateRotationSpeed(globalIndex, speed);
// Linear animation
lights.updateLinearDuration(globalIndex, duration);
// Generic property update
lights.updateLightAnimationProperty(globalIndex, animationType, property, value);
// Patch a material to use clustered lighting
lights.patchMaterial(material);
// Enable/disable dynamic cluster resolution
lights.setDynamicClusters(enabled);
// Set LOD bias (affects quality/performance tradeoff)
lights.setLODBias(bias);
const bias = lights.getLODBias();
Two shadow modes are available: screen-space (ray marching against depth buffer) and atlas (budget-based shadow map atlas). Both can be used with any light count, but screen-space is better suited for high light counts where per-light shadow maps are impractical.
// Set shadow mode: 'off', 'screenspace', or 'atlas'
lights.setShadowMode('screenspace');
// Screen-space shadow intensity (0–1, controls global shadow darkness)
lights.setScreenSpaceShadowIntensity(0.5);
const intensity = lights.getScreenSpaceShadowIntensity();
// Atlas shadow budget (max simultaneous shadow-casting lights, renders per frame)
lights.setShadowBudget(8, 4);
// Enable per-light shadow casting (atlas mode)
lights.setLightShadow('point', lightIndex, true, 0.7);
// Query shadow stats
const stats = lights.getShadowStats();
// stats.activeCandidates, stats.cacheSize, stats.atlasSize,
// stats.maxSlots, stats.usedSlots, stats.shadowsPerFrame
Note: Shadow support is experimental and may change in future releases. Screen-space shadows use scale-relative thresholds and work across different scene sizes. Atlas shadows use a temporal cache with importance-based budget allocation.
// Call in your render loop
function animate() {
const time = clock.getElapsedTime();
lights.update(time, camera);
renderer.render(scene, camera);
}
Visual markers for light positions using instanced rendering.
const markers = new LightMarkers(lightsSystem, {
visible: true,
showGlow: true,
glowRadius: 0.5,
pointGlowRadius: 0.5,
spotGlowRadius: 0.5,
rectGlowRadius: 0.5,
markerScale: 0.05,
colorOverride: null // THREE.Vector3 or null
});
markers.init(scene); // Add markers to scene
markers.update(scene); // Update marker positions
markers.dispose(scene); // Remove and cleanup
markers.reinit(scene); // Dispose and reinit
// Configuration
markers.setVisible(visible);
markers.setShowGlow(show);
markers.setGlowRadius(radius);
markers.setMarkerScale(scale);
markers.setColorOverride(color);
All-in-one performance monitoring with automatic UI injection.
const tracker = new PerformanceTracker(renderer, {
container: document.body,
showFPS: true,
showCPU: true,
showGPU: true,
showMemory: true,
showWASM: true,
showCluster: true,
showRender: true
});
tracker.begin(); // Call at start of render loop
tracker.end(); // Call at end of render loop
tracker.dispose(); // Cleanup
const query = new GPUQuery(renderer, "#element-id");
query.start();
// ... GPU work ...
query.end(time);
query.dispose();
const fps = new FPSMeter("#fps", "#minFps", "#maxFps");
fps.update(time);
const cpu = new CPUTimer("#cpu-value");
cpu.begin();
// ... work ...
cpu.end(time);
const mem = new MemoryMonitor("#mem-value", "#mem-unit");
mem.update(time);
LightType.POINT // 0
LightType.SPOT // 1
LightType.RECT // 2
Animation.NONE // 0x00
Animation.CIRCULAR // 0x01
Animation.LINEAR // 0x02
Animation.WAVE // 0x04
Animation.FLICKER // 0x08
Animation.PULSE // 0x10
Animation.ROTATE // 0x20
LinearMode.ONCE // 0 - Play once
LinearMode.LOOP // 1 - Loop continuously
LinearMode.PINGPONG // 2 - Bounce back and forth
PulseTarget.INTENSITY // 0x01
PulseTarget.RADIUS // 0x02
PulseTarget.BOTH // 0x03
RotateMode.CONTINUOUS // 0 - Continuous rotation
RotateMode.SWING // 1 - Swing back and forth
LODLevel.SKIP // 0 - Don't render
LODLevel.SIMPLE // 1 - Minimal quality
LODLevel.MEDIUM // 2 - Medium quality
LODLevel.FULL // 3 - Full quality
import * as THREE from 'three';
import {
ClusterLightingSystem,
PerformanceTracker,
loadWasm,
LightType,
Animation
} from 'three-cluster-lights';
// Setup renderer
const renderer = new THREE.WebGLRenderer({ antialias: true });
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
// Load WASM
const wasm = await loadWasm({ preferSIMD: true });
// Create lighting system
const lights = new ClusterLightingSystem(
renderer,
wasm,
0.1, // near
1000, // far
32, 16, 32, // cluster resolution
true // performance mode
);
// Add lights
lights.addLight({
type: LightType.POINT,
position: new THREE.Vector3(0, 5, 0),
color: new THREE.Color(1, 0.5, 0),
intensity: 10,
radius: 15,
animation: {
circular: { speed: 1, radius: 5 }
}
});
// Patch materials
const material = new THREE.MeshStandardMaterial({ color: 0x808080 });
lights.patchMaterial(material);
// Performance tracking
const tracker = new PerformanceTracker(renderer, {
showFPS: true,
showCPU: true,
showGPU: true,
showMemory: true
});
// Render loop
const clock = new THREE.Clock();
function animate() {
requestAnimationFrame(animate);
tracker.begin();
const time = clock.getElapsedTime();
lights.update(time, camera);
renderer.render(scene, camera);
tracker.end();
}
animate();
(Simple but aesthetically pleasing instanced light objects)
import { ClusterLightingSystem, LightMarkers } from 'three-cluster-lights';
// ... setup lights ...
// Add visual markers
const markers = new LightMarkers(lights, {
visible: true,
showGlow: true,
glowRadius: 0.5
});
markers.init(scene);
// Update in render loop
function animate() {
// ...
markers.update(scene);
// ...
}
// Add many lights efficiently
for (let i = 0; i < 1000; i++) {
lights.addFastLight({
type: LightType.POINT,
position: new THREE.Vector3(
Math.random() * 100 - 50,
Math.random() * 20,
Math.random() * 100 - 50
),
color: new THREE.Color(Math.random(), Math.random(), Math.random()),
intensity: 5 + Math.random() * 10,
radius: 10 + Math.random() * 20
});
}
The library includes WebAssembly modules for high-performance light processing:
// Option 1: Using loadWasm helper (recommended) no config required or manual wasm additions
import { loadWasm } from 'three-cluster-lights';
const wasm = await loadWasm({
preferSIMD: true // Auto-detect and use SIMD if available
});
// Option 2: You can manually override this and load
const wasm = await WebAssembly.instantiateStreaming(
fetch('/node_modules/three-cluster-lights/wasm/cluster-lights-simd.wasm'),
{ env: { emscripten_notify_memory_growth: () => {} } }
);
// Option 3: If you do this, you can set this up in various ways
import wasmUrl from 'three-cluster-lights/wasm/cluster-lights-simd.wasm?url';
const wasm = await WebAssembly.instantiateStreaming(
fetch(wasmUrl),
{ env: { emscripten_notify_memory_growth: () => {} } }
);
The loadWasm() helper automatically detects SIMD support and loads the appropriate version.
The WASM source is included for transparency and custom builds:
# Build standard version
npm run build:wasm
# Build SIMD version
npm run build:wasm-simd
# Build both and copy to public/
npm run build:wasm:all
Requirements: Emscripten SDK (emcc) must be installed
├── index.js # Main entry point
├── index.d.ts # TypeScript definitions
├── package.json # NPM package configuration
├── README.md # This file
│
├── core/ # Core lighting system
│ ├── cluster-lighting-system.js # Main ClusterLightingSystem class
│ ├── cluster-shaders.js # GLSL shaders and materials
│ └── shadow-atlas.js # Shadow atlas manager (experimental)
│
├── performance/ # Performance monitoring
│ ├── performance-metrics.js # Low-level performance primitives
│ ├── performance-tracker.js # High-level performance tracker
│ └── adaptive-tile-span.js # Adaptive performance tuning
│
├── utils/ # Utilities
│ └── wasm-loader.js # WASM loading with fallback
│
├── visual/ # Visual debugging
│ └── light-markers.js # Visual light position markers
│
└── wasm/ # WebAssembly modules
├── cluster-lights.c # WASM source code
├── cluster-lights.wasm # Compiled WASM (standard)
├── cluster-lights-simd.wasm # Compiled WASM (SIMD optimized)
└── cluster-lights-asm.js # JavaScript fallback
addFastLight() for bulk operations - Skips some validation checkssetLODBias())setDynamicClusters(true))For older browser support, the library will gracefully degrade performance monitoring features.
PerformanceTracker auto-injects its own CSS — no external stylesheet neededFAQs
Thousands of clustered lighting for Three.js
We found that three-cluster-lights demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.