Vanilla Three.js Integration Guide
This guide covers integrating 3Lens with vanilla Three.js applications—no frameworks, just pure JavaScript/TypeScript and Three.js.
Table of Contents
- Quick Start
- Installation
- Basic Setup
- Complete Example
- Advanced Features
- Transform Gizmos
- Camera Controls
- Multiple Scenes
- Production Builds
- Best Practices
- Troubleshooting
Quick Start
Get up and running in under 2 minutes:
// 1. Install dependencies
// npm install @3lens/core @3lens/overlay three
// 2. Import and set up
import * as THREE from 'three';
import { createProbe } from '@3lens/core';
import { bootstrapOverlay } from '@3lens/overlay';
// 3. Create your scene
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 4. Set up 3Lens
const probe = createProbe({ appName: 'My App' });
probe.observeRenderer(renderer);
probe.observeScene(scene);
bootstrapOverlay(probe);
// 5. Press Ctrl+Shift+D to toggle the devtools overlay!2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
That's it! The overlay will appear showing FPS, draw calls, scene hierarchy, and more.
Installation
Install the core package and overlay UI:
npm install @3lens/core @3lens/overlay threepnpm add @3lens/core @3lens/overlay threeyarn add @3lens/core @3lens/overlay threebun add @3lens/core @3lens/overlay threeBasic Setup
Step 1: Import 3Lens Packages
import * as THREE from 'three';
import { createProbe } from '@3lens/core';
import { bootstrapOverlay } from '@3lens/overlay';2
3
import * as THREE from 'three';
import { createProbe } from '@3lens/core';
import { bootstrapOverlay } from '@3lens/overlay';2
3
Step 2: Create Your Three.js Scene
// Standard Three.js setup
const scene = new THREE.Scene();
scene.name = 'MainScene'; // Naming helps in the devtool
const camera = new THREE.PerspectiveCamera(
60,
window.innerWidth / window.innerHeight,
0.1,
1000
);
camera.name = 'MainCamera';
camera.position.set(5, 5, 8);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
document.body.appendChild(renderer.domElement);2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Step 3: Create and Configure the Probe
const probe = createProbe({
appName: 'My Three.js App',
// Optional configuration
enabled: true,
sampling: {
frameInterval: 1, // Sample every frame
historyLength: 120, // Keep 2 seconds of history at 60fps
},
thresholds: {
maxDrawCalls: 200, // Warn if draw calls exceed this
maxTriangles: 1_000_000, // Warn if triangle count exceeds this
minFPS: 30, // Warn if FPS drops below this
}
});
// Connect renderer and scene
probe.observeRenderer(renderer);
probe.observeScene(scene);
// Set THREE reference for advanced features (optional but recommended)
probe.setThreeReference(THREE);2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Step 4: Bootstrap the Overlay
// Create the visual devtools panel
bootstrapOverlay(probe);2
Step 5: Toggle the Panel
Press Ctrl+Shift+D (or Cmd+Shift+D on macOS) to toggle the devtools panel.
Complete Example
Here's a complete vanilla Three.js setup with 3Lens:
import * as THREE from 'three';
import { createProbe } from '@3lens/core';
import { bootstrapOverlay } from '@3lens/overlay';
// Create your three.js scene
const scene = new THREE.Scene();
scene.name = 'MainScene';
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
camera.name = 'MainCamera';
camera.position.set(5, 5, 8);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
document.body.appendChild(renderer.domElement);
// Add lighting
const ambientLight = new THREE.AmbientLight(0x404040, 0.5);
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(5, 5, 5);
directionalLight.castShadow = true;
scene.add(directionalLight);
// Add objects
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshStandardMaterial({
name: 'CubeMaterial',
color: 0x60a5fa,
roughness: 0.3,
metalness: 0.7,
});
const cube = new THREE.Mesh(geometry, material);
cube.name = 'AnimatedCube';
cube.castShadow = true;
cube.position.set(0, 0, 0);
scene.add(cube);
// 🔧 Set up 3Lens
const probe = createProbe({
appName: 'Vanilla Three.js Example',
});
probe.observeRenderer(renderer);
probe.observeScene(scene);
probe.setThreeReference(THREE);
bootstrapOverlay(probe);
// Animation loop
function animate() {
requestAnimationFrame(animate);
// Your animation logic
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
// Render the scene
renderer.render(scene, camera);
}
animate();
// Handle window resize
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
Advanced Features
Transform Gizmos
Enable interactive transform controls to manipulate objects directly in the scene:
// Initialize transform gizmo (must be async)
await probe.initializeTransformGizmo(camera, renderer.domElement);
// Now you can select objects in the scene tree and use the gizmo
// to translate, rotate, and scale them interactively2
3
4
5
Camera Controls
Enable camera controller for viewport navigation:
// Initialize camera controller
await probe.initializeCameraController(camera, renderer.domElement);
// This enables camera controls similar to OrbitControls
// You can navigate the scene directly from the devtools2
3
4
5
WebGPU Support
3Lens automatically detects WebGPU renderers:
import { WebGPURenderer } from 'three/addons/renderers/WebGPURenderer.js';
const renderer = new WebGPURenderer();
// ... rest of setup
// 3Lens will automatically use the WebGPU adapter
probe.observeRenderer(renderer);2
3
4
5
6
7
Multiple Scenes
You can observe multiple scenes with a single probe:
const mainScene = new THREE.Scene();
const uiScene = new THREE.Scene();
const backgroundScene = new THREE.Scene();
const probe = createProbe();
probe.observeRenderer(renderer);
// Observe all scenes
probe.observeScene(mainScene);
probe.observeScene(uiScene);
probe.observeScene(backgroundScene);
bootstrapOverlay(probe);2
3
4
5
6
7
8
9
10
11
12
13
All scenes will appear in the scene hierarchy tree, organized by their names.
Production Builds
For production, you should exclude 3Lens to reduce bundle size:
Development-Only Setup
import * as THREE from 'three';
let probe: DevtoolProbe | null = null;
if (import.meta.env.DEV) {
const { createProbe } = await import('@3lens/core');
const { bootstrapOverlay } = await import('@3lens/overlay');
probe = createProbe({ appName: 'My App' });
probe.observeRenderer(renderer);
probe.observeScene(scene);
bootstrapOverlay(probe);
}2
3
4
5
6
7
8
9
10
11
12
13
import * as THREE from 'three';
let probe = null;
if (import.meta.env.DEV) {
const { createProbe } = await import('@3lens/core');
const { bootstrapOverlay } = await import('@3lens/overlay');
probe = createProbe({ appName: 'My App' });
probe.observeRenderer(renderer);
probe.observeScene(scene);
bootstrapOverlay(probe);
}2
3
4
5
6
7
8
9
10
11
12
13
Vite Configuration
If using Vite, you can use environment variables:
if (import.meta.env.DEV) {
// 3Lens setup
}2
3
Webpack Configuration
For Webpack, use process.env.NODE_ENV:
if (process.env.NODE_ENV === 'development') {
// 3Lens setup
}2
3
Best Practices
1. Name Your Objects
Setting object.name makes the scene tree much more readable:
const cube = new THREE.Mesh(geometry, material);
cube.name = 'AnimatedCube'; // ✅ Good
scene.add(cube);
// vs
scene.add(new THREE.Mesh(geometry, material)); // ❌ Hard to identify2
3
4
5
6
7
2. Name Materials and Geometries
Helps identify resources in the devtool panels:
const material = new THREE.MeshStandardMaterial({
name: 'CubeMaterial', // ✅ Good
color: 0x60a5fa,
});
const geometry = new THREE.BoxGeometry(1, 1, 1);
geometry.name = 'CubeGeometry'; // ✅ Good2
3
4
5
6
7
3. Share Geometries
Multiple meshes can share the same geometry instance to save memory:
const sharedGeometry = new THREE.BoxGeometry(1, 1, 1);
const cube1 = new THREE.Mesh(sharedGeometry, material1);
const cube2 = new THREE.Mesh(sharedGeometry, material2);
const cube3 = new THREE.Mesh(sharedGeometry, material3);
// All three cubes share the same geometry instance2
3
4
5
6
7
4. Set THREE Reference
Always call probe.setThreeReference(THREE) for advanced features:
probe.setThreeReference(THREE);This enables:
- Better type detection
- Advanced introspection features
- Material and shader inspection
5. Handle Window Resize
Make sure to update camera and renderer on resize:
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});2
3
4
5
Troubleshooting
Panel doesn't appear
- Make sure you called
bootstrapOverlay(probe)after creating the probe - Check the browser console for errors
- Try pressing
Ctrl+Shift+Dto toggle visibility - Ensure your renderer is initialized before calling
observeRenderer()
Performance impact
3Lens is designed to have minimal performance impact, but you can reduce it further:
const probe = createProbe({
sampling: {
frameInterval: 2, // Sample every other frame
historyLength: 60, // Reduce history buffer
}
});2
3
4
5
6
Transform gizmo not working
Make sure you've initialized the gizmo:
await probe.initializeTransformGizmo(camera, renderer.domElement);The gizmo requires the camera and renderer DOM element to function properly.
Objects not appearing in scene tree
- Ensure you've called
probe.observeScene(scene)after adding objects - Check that objects are actually added to the scene (
scene.add(object)) - Verify the scene is being rendered (
renderer.render(scene, camera))
WebGPU not detected
If you're using WebGPU, make sure:
- Your browser supports WebGPU
- You're using
WebGPURendererfrom Three.js - The renderer is initialized before calling
observeRenderer()
Next Steps
Now that you have 3Lens set up with vanilla Three.js, explore these topics:
- Scene Inspection - Navigate and understand your scene
- Performance Debugging - Find and fix bottlenecks
- Memory Profiling - Track and prevent memory leaks
- Transform Gizmos - Interactive object manipulation
- Material Editing - Live-edit materials and uniforms
See Also
- Live Example: Vanilla Three.js - Complete working example
- Getting Started Guide - General setup instructions
- Configuration Guide - All configuration options