3Lens API Documentation
This guide covers the public API for integrating 3Lens into your three.js application.
Table of Contents
Installation
npm install @3lens/core @3lens/overlayNote: Packages are currently in alpha and not yet published to npm.
Core Package (@3lens/core)
The core package provides the probe SDK that collects performance metrics and scene data from your three.js application.
createProbe()
Factory function to create a DevtoolProbe instance.
import { createProbe } from '@3lens/core';
const probe = createProbe({
appName: 'My Game',
debug: false,
rules: {
maxDrawCalls: 500,
maxTriangles: 250_000,
maxFrameTimeMs: 16.67,
},
});2
3
4
5
6
7
8
9
10
11
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
config | ProbeConfig | Yes | Configuration object |
ProbeConfig
interface ProbeConfig {
/**
* Application name for identification in DevTools
*/
appName: string;
/**
* Environment identifier
* @default 'development'
*/
env?: 'development' | 'staging' | 'production' | string;
/**
* Enable verbose console logging
* @default false
*/
debug?: boolean;
/**
* Performance rules and thresholds
*/
rules?: RulesConfig;
/**
* Sampling configuration
*/
sampling?: SamplingConfig;
/**
* Custom tags for organization
*/
tags?: Record<string, string>;
}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
RulesConfig
interface RulesConfig {
/**
* Maximum draw calls before warning
*/
maxDrawCalls?: number;
/**
* Maximum triangles before warning
*/
maxTriangles?: number;
/**
* Maximum frame time (ms) before warning
* @example 16.67 for 60 FPS target
*/
maxFrameTimeMs?: number;
/**
* Maximum textures before warning
*/
maxTextures?: number;
/**
* Maximum total texture memory (bytes)
*/
maxTextureMemory?: number;
}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
DevtoolProbe
The main probe class returned by createProbe().
Observing Renderers
// Observe a WebGL renderer (auto-wraps render calls)
probe.observeRenderer(renderer);
// For selection highlighting, provide the THREE reference
probe.setThreeReference(THREE);2
3
4
5
Observing Scenes
// Start observing a scene
probe.observeScene(scene);
// Stop observing
probe.unobserveScene(scene);
// Get all observed scenes
const scenes = probe.getObservedScenes();2
3
4
5
6
7
8
Selection
// Select an object programmatically
probe.selectObject(mesh);
// Clear selection
probe.selectObject(null);
// Get currently selected object
const selected = probe.getSelectedObject();
// Listen for selection changes
const unsubscribe = probe.onSelectionChanged((object, meta) => {
if (object) {
console.log(`Selected: ${object.name || object.type}`);
}
});2
3
4
5
6
7
8
9
10
11
12
13
14
15
Frame Stats
// Get the latest frame statistics
const stats = probe.getLatestFrameStats();
console.log(`${stats.drawCalls} draw calls, ${stats.triangles} triangles`);
// Get history (last N frames)
const history = probe.getFrameStatsHistory(60); // Last 60 frames
// Subscribe to frame updates
const unsubscribe = probe.onFrameStats((stats) => {
if (stats.violations?.length > 0) {
console.warn('Performance violations:', stats.violations);
}
});2
3
4
5
6
7
8
9
10
11
12
13
Snapshots
// Take a manual snapshot of all observed scenes
const snapshot = probe.takeSnapshot();
console.log(`Snapshot contains ${snapshot.scenes.length} scenes`);2
3
4
Cleanup
// Dispose of the probe and clean up all hooks
probe.dispose();2
Frame Stats
The FrameStats object contains per-frame performance metrics.
interface FrameStats {
frame: number; // Frame number
timestamp: number; // Unix timestamp (ms)
// Timing
cpuTimeMs: number; // CPU time for this frame
gpuTimeMs?: number; // GPU time (when available)
// Rendering counts
triangles: number; // Total triangles rendered
drawCalls: number; // Number of draw calls
points: number; // Points rendered
lines: number; // Lines rendered
// Object counts
objectsVisible: number; // Visible objects
objectsTotal: number; // Total objects in scene
materialsUsed: number; // Unique materials used
// Backend info
backend: 'webgl' | 'webgpu';
// Rule violations (if any)
violations?: RuleViolation[];
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Rule Violations
interface RuleViolation {
ruleId: string; // e.g., 'maxDrawCalls'
message: string; // Human-readable message
severity: 'info' | 'warning' | 'error';
value?: number; // Current value
threshold?: number; // Configured threshold
}2
3
4
5
6
7
Scene Snapshots
Snapshots capture the current state of observed scenes.
interface SceneSnapshot {
snapshotId: string; // Unique identifier
timestamp: number; // When snapshot was taken
scenes: SceneNode[]; // Root scene nodes
}
interface SceneNode {
ref: TrackedObjectRef; // Object reference
transform: TransformData;
visible: boolean;
children: SceneNode[]; // Nested children
// Type-specific data
meshData?: MeshNodeData;
lightData?: LightNodeData;
cameraData?: CameraNodeData;
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Overlay Package (@3lens/overlay)
The overlay package provides an in-app floating panel UI.
createOverlay()
Creates and mounts the overlay UI.
import { createOverlay } from '@3lens/overlay';
const overlay = createOverlay(probe, {
position: 'right',
collapsed: false,
});2
3
4
5
6
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
probe | DevtoolProbe | Yes | The probe instance |
options | OverlayOptions | No | Configuration options |
OverlayOptions
interface OverlayOptions {
/**
* Panel position
* @default 'right'
*/
position?: 'left' | 'right';
/**
* Start with panel collapsed
* @default false
*/
collapsed?: boolean;
}2
3
4
5
6
7
8
9
10
11
12
13
bootstrapOverlay()
One-call setup that creates both probe and overlay.
import { bootstrapOverlay } from '@3lens/overlay';
const { probe, overlay } = bootstrapOverlay({
renderer,
scene,
appName: 'My App',
probeConfig: {
rules: {
maxDrawCalls: 500,
},
},
overlay: {
position: 'left',
},
three: THREE, // Optional: enables selection highlighting
});2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
BootstrapOptions
interface OverlayBootstrapOptions {
renderer: THREE.WebGLRenderer;
scene: THREE.Scene;
appName?: string;
probeConfig?: Partial<ProbeConfig>;
overlay?: Partial<OverlayOptions>;
three?: typeof THREE; // For selection highlighting
}2
3
4
5
6
7
8
ThreeLensOverlay
The overlay instance provides these methods:
// Show the panel
overlay.show();
// Hide the panel
overlay.hide();
// Toggle visibility
overlay.toggle();
// Check if visible
const isVisible = overlay.isVisible;
// Completely remove from DOM
overlay.destroy();2
3
4
5
6
7
8
9
10
11
12
13
14
Types Reference
TrackedObjectRef
Reference to a three.js object.
interface TrackedObjectRef {
debugId: string; // Stable internal ID
threeUuid: string; // Object's three.js UUID
type: string; // Object type (e.g., 'Mesh', 'Group')
name?: string; // Object name (if set)
path?: string; // Scene path (e.g., '/Scene/Player/Mesh')
}2
3
4
5
6
7
TransformData
Object transform information.
interface TransformData {
position: { x: number; y: number; z: number };
rotation: { x: number; y: number; z: number; order: string };
scale: { x: number; y: number; z: number };
}2
3
4
5
MeshNodeData
Mesh-specific data.
interface MeshNodeData {
geometryRef: string; // Geometry reference ID
materialRefs: string[]; // Material reference IDs
vertexCount: number;
faceCount: number;
castShadow: boolean;
receiveShadow: boolean;
}2
3
4
5
6
7
8
LightNodeData
Light-specific data.
interface LightNodeData {
lightType: 'ambient' | 'directional' | 'point' | 'spot' | 'hemisphere' | 'rect';
color: number;
intensity: number;
castShadow: boolean;
distance?: number; // For point/spot lights
angle?: number; // For spot lights
}2
3
4
5
6
7
8
Examples
Basic Integration
import * as THREE from 'three';
import { createProbe } from '@3lens/core';
import { createOverlay } from '@3lens/overlay';
// Setup three.js
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight);
const renderer = new THREE.WebGLRenderer();
document.body.appendChild(renderer.domElement);
// Add some objects
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshStandardMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
cube.name = 'MyCube';
scene.add(cube);
// Setup 3Lens
const probe = createProbe({
appName: 'Cube Demo',
rules: {
maxDrawCalls: 100,
maxFrameTimeMs: 16.67,
},
});
probe.setThreeReference(THREE);
probe.observeRenderer(renderer);
probe.observeScene(scene);
const overlay = createOverlay(probe);
// Animation loop
function animate() {
requestAnimationFrame(animate);
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
}
animate();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
Performance Monitoring
// Log stats every second
setInterval(() => {
const stats = probe.getLatestFrameStats();
if (stats) {
console.log(`FPS: ${Math.round(1000 / stats.cpuTimeMs)}`);
console.log(`Draw calls: ${stats.drawCalls}`);
console.log(`Triangles: ${stats.triangles.toLocaleString()}`);
}
}, 1000);2
3
4
5
6
7
8
9
Conditional Loading (Production)
// Only load in development
if (import.meta.env.DEV) {
const { createProbe } = await import('@3lens/core');
const { createOverlay } = await import('@3lens/overlay');
const probe = createProbe({ appName: 'My App' });
probe.observeRenderer(renderer);
probe.observeScene(scene);
createOverlay(probe);
}2
3
4
5
6
7
8
9
10
Troubleshooting
Overlay Not Showing
- Ensure the probe is connected to both renderer and scene
- Check if
overlay.isVisibleis true - Look for CSS conflicts (z-index issues)
No Stats Appearing
- Verify
probe.observeRenderer()was called - Check that rendering is happening (animation loop running)
- Enable debug mode:
{ debug: true }
Performance Impact
3Lens is designed for minimal overhead (~1-3%). For production:
// Skip 3Lens entirely in production
if (import.meta.env.PROD) {
// Don't import or initialize 3Lens
}2
3
4
Next Steps
- API Specification — Full TypeScript interfaces
- Architecture — System design details
- Contributing — How to contribute