threejs-scene-setup
gamedev-skills/awesome-gamedev-agent-skills
Bootstrap a three.js scene with camera, renderer, animation loop, and OrbitControls.
What is threejs-scene-setup?
Sets up the foundational three.js scene: ES module loading with import maps, the Scene/Camera/Renderer trio, a render loop with Timer, responsive resizing, and orbit camera controls. Use this when starting a three.js project or fixing a blank canvas.
- Create a WebGL renderer, scene, and perspective camera with proper sizing and pixel ratio
- Establish a frame-rate-independent render loop using setAnimationLoop and Timer
- Handle window resize to keep the camera aspect and renderer in sync
- Add OrbitControls for interactive orbit, pan, and zoom camera movement
- Configure ES module imports for three.js and addons via import maps or bundlers
How to install threejs-scene-setup
npx skills add https://github.com/gamedev-skills/awesome-gamedev-agent-skills --skill threejs-scene-setup- Node.js and npm (if using a bundler like Vite or webpack)
- A browser with WebGL support
- Basic familiarity with ES modules and JavaScript
How to use threejs-scene-setup
- 1.Set up an import map in HTML (or use a bundler) to resolve 'three' and 'three/addons/' specifiers
- 2.Create a WebGLRenderer, Scene, and PerspectiveCamera, then add them to the DOM
- 3.Position the camera away from the origin and add a test mesh (e.g., a cube with MeshNormalMaterial)
- 4.Implement the render loop using renderer.setAnimationLoop() with a Timer for delta time
- 5.Add a resize listener to update camera.aspect, call updateProjectionMatrix(), and renderer.setSize()
- 6.Import and instantiate OrbitControls, enable damping, and call controls.update() each frame
Use cases
- Bootstrap a new three.js project from scratch with all core components
- Fix a blank or black canvas by verifying camera position and lighting setup
- Make a canvas responsive to window resizing without distortion
- Add interactive camera controls to an existing three.js scene for development
- Debug three.js apps by confirming the render loop and scene graph are working
- Game developers building 3D web experiences
- 3D visualization engineers setting up interactive scenes
- Web developers new to three.js who need a working foundation
- Technical artists prototyping 3D concepts in the browser
threejs-scene-setup FAQ
Use this skill to set up the scene foundation. Use threejs-materials-lighting for lights, shadows, and PBR materials; use threejs-gltf-loading for loading .gltf/.glb models and animations.
You are missing an import map or bundler configuration. Add an import map in HTML with both 'three' and 'three/addons/' (note the trailing slash on addons), or use npm install three with a bundler like Vite.
The camera is likely at the origin (inside or behind your object), or you used a lit material without a light. Move the camera back with camera.position.set(...), or use MeshNormalMaterial to test geometry without lighting.
On window resize, update camera.aspect, call camera.updateProjectionMatrix(), and then renderer.setSize(). Skipping updateProjectionMatrix() causes squashing or stretching.
If you enabled damping (enableDamping = true), you must call controls.update() every frame inside the render loop.
Full instructions (SKILL.md)
Source of truth, from gamedev-skills/awesome-gamedev-agent-skills.
name: threejs-scene-setup description: > Stand up a three.js scene: import maps and the three/addons path, the Scene/PerspectiveCamera/WebGLRenderer trio, the setAnimationLoop render loop, responsive resize, and OrbitControls. Use when starting or debugging a three.js app — when the user mentions three.js, THREE.Scene, WebGLRenderer, PerspectiveCamera, the render loop, resizing, or OrbitControls. For models use threejs-gltf-loading; for materials/lights use threejs-materials-lighting.
three.js Scene Setup
Create the foundation of a three.js app: module loading, the
scene/camera/renderer trio, the render loop, responsive resizing, and camera
controls. Patterns target r186. Read the installed three version before
changing an existing project because examples and addons move across releases.
When to use
- Use when bootstrapping a three.js scene, fixing a blank/black canvas, making the
canvas responsive, setting up the animation loop, or adding
OrbitControls. - Use when
package.jsondepends onthreeand code doesimport * as THREE from 'three'.
When not to use: loading .gltf/.glb models or skinned animation →
threejs-gltf-loading. Materials, lights, shadows, environment maps →
threejs-materials-lighting. 2D rendering → pixijs-rendering.
Core workflow
- Load three.js as an ES module with an import map. Since r147 the bare
specifier
'three'and'three/addons/'must be mapped (in HTML or by a bundler). Addons (controls, loaders) live underthree/addons/.... - Create the trio. A
Scene(root of the graph), aPerspectiveCamera(fov, aspect, near, far)moved back from the origin, and aWebGLRendererwhosedomElementis in the DOM. Set size andpixelRatio. - Add a mesh.
new Mesh(geometry, material)andscene.add(mesh). With a lit material you also need a light (seethreejs-materials-lighting). - Drive a render loop with
renderer.setAnimationLoop(fn). It's the modern, WebXR-/WebGPU-safe replacement for hand-rolledrequestAnimationFrame. Use aTimerfor delta time (Clockis deprecated since r183). - Handle resize so the camera aspect and renderer match the canvas; update
camera.aspect, callupdateProjectionMatrix(), andrenderer.setSize(...). - Add
OrbitControlsfor orbit/pan/zoom while developing. Confirm something actually renders (a lit cube, the controls responding) before assuming success.
Patterns
1. HTML import map + module entry (no bundler)
<canvas id="c"></canvas>
<script type="importmap">
{
"imports": {
"three": "https://cdn.jsdelivr.net/npm/three@0.186.0/build/three.module.js",
"three/addons/": "https://cdn.jsdelivr.net/npm/three@0.186.0/examples/jsm/"
}
}
</script>
<script type="module" src="./main.js"></script>
With a bundler (Vite/webpack), skip the import map and just
npm i three; the same import statements resolve.
2. Scene + camera + renderer
// main.js
import * as THREE from 'three';
const canvas = document.querySelector('#c');
const renderer = new THREE.WebGLRenderer({ canvas, antialias: true });
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)); // cap for perf
renderer.setSize(window.innerWidth, window.innerHeight);
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x101018);
const camera = new THREE.PerspectiveCamera(
60, // vertical field of view (degrees)
window.innerWidth / window.innerHeight, // aspect
0.1, // near
100 // far
);
camera.position.set(3, 2, 5);
camera.lookAt(0, 0, 0);
const cube = new THREE.Mesh(
new THREE.BoxGeometry(1, 1, 1),
new THREE.MeshNormalMaterial() // unlit; shows orientation without a light
);
scene.add(cube);
3. The render loop (setAnimationLoop + Timer)
const timer = new THREE.Timer(); // replaces the deprecated THREE.Clock (r183+)
timer.connect(document); // optional: no huge delta after a hidden tab
renderer.setAnimationLoop((time) => {
timer.update(time); // call once per frame, before getDelta()
const dt = timer.getDelta(); // seconds since last frame
cube.rotation.x += dt; // frame-rate independent
cube.rotation.y += dt * 0.7;
renderer.render(scene, camera);
});
// renderer.setAnimationLoop(null); // stop the loop
4. Responsive resize
function onResize() {
const w = window.innerWidth, h = window.innerHeight;
camera.aspect = w / h;
camera.updateProjectionMatrix(); // required after changing aspect
renderer.setSize(w, h);
}
window.addEventListener('resize', onResize);
5. OrbitControls (orbit / pan / zoom)
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true; // inertial feel
controls.target.set(0, 0, 0);
renderer.setAnimationLoop(() => {
controls.update(); // needed every frame when damping is on
renderer.render(scene, camera);
});
Pitfalls
Failed to resolve module specifier "three"→ missing import map (or bundler config). Map both"three"and"three/addons/"; addon paths must end with/.- Black canvas, no errors → camera is at the origin (inside/behind the object),
or you used a lit material (
MeshStandardMaterial) with no light. Move the camera back; useMeshNormalMaterial/MeshBasicMaterialto verify geometry first. - Nothing animates → you never called
renderer.renderinside the loop, or you callsetAnimationLoopbut render outside it. - Stretched / squashed view on resize → you resized the renderer but didn't
update
camera.aspect+updateProjectionMatrix(). - Blurry or jagged on HiDPI → set
renderer.setPixelRatio(...); cap it (≈2) so 4K/retina screens don't tank performance. - OrbitControls feel dead → with
enableDamping = trueyou must callcontrols.update()every frame. - Old tutorials use
<script src="three.min.js">→ since r147 three.js ships ES modules only; usetype="module"+ import maps.
References
- For coordinate conventions, the scene-graph (
Group, parent/child transforms,Object3Dadd/remove),OrthographicCamerafor 2.5D, and disposing of geometries/materials/textures to avoid leaks, readreferences/scene-graph.md.
Related skills
threejs-materials-lighting— give surfaces a lit look (lights, shadows, PBR).threejs-gltf-loading— load 3D models and play their animations.pixijs-rendering— 2D rendering in the browser.fps-shooter— a 3D genre template that composes three.js skills.
Related skills
More from gamedev-skills/awesome-gamedev-agent-skills and the wider catalog.

tower-defense
Build tower defense games with enemy pathing, wave spawning, tower targeting, and economy systems.

unity-animation
Drive character animation in Unity 6.3 LTS with Animator Controllers, parameters, blend trees, and IK.

unity-build-pipeline
Configure, script, and automate Unity 6.3 LTS player builds with platform targets, scripting backends, and CI integration.

unity-csharp-scripting
Write correct Unity 6 MonoBehaviour scripts with proper lifecycle, component caching, and coroutines.

unity-input-system
Wire player input in Unity 6.3 LTS with action-based, device-agnostic Input System package.

unity-navmesh
Add AI pathfinding to Unity 6.3 LTS with NavMesh baking and agent steering.