Blog & Insights

Thoughts, tutorials, and explorations at the intersection of mathematics, visualization, and web development.

Creating Immersive 3D Experiences with Three.js

Published: April 22, 2025Category: Three.js

Creating Immersive 3D Experiences with Three.js

Three.js has revolutionized the way developers create 3D content for the web. This powerful JavaScript library abstracts away the complexities of WebGL, making it accessible to create stunning 3D visualizations and interactive experiences directly in the browser.

Introduction to Three.js

Three.js is a cross-browser JavaScript library that makes it easier to create and display animated 3D computer graphics in a web browser. It uses WebGL under the hood, but provides a much more developer-friendly API.

Three.js was created by Ricardo Cabello (also known as Mr.doob) in 2010 and has since grown into one of the most popular 3D libraries for the web with over 80,000 stars on GitHub.

Setting Up Your First Three.js Scene

Creating a basic Three.js scene involves several key components:

  1. Scene: The container that holds all objects, cameras, and lights
  2. Camera: Defines what we see (perspective, field of view, etc.)
  3. Renderer: Renders the scene using WebGL
  4. Objects: 3D models, geometries, and meshes
  5. Lights: Illuminate the scene

Here's a simple example to get started:

1// Import Three.js
2import * as THREE from 'three';
3
4// Create a scene
5const scene = new THREE.Scene();
6
7// Create a camera
8const camera = new THREE.PerspectiveCamera(
9  75, // Field of view
10  window.innerWidth / window.innerHeight, // Aspect ratio
11  0.1, // Near clipping plane
12  1000 // Far clipping plane
13);
14camera.position.z = 5;
15
16// Create a renderer
17const renderer = new THREE.WebGLRenderer({ antialias: true });
18renderer.setSize(window.innerWidth, window.innerHeight);
19document.body.appendChild(renderer.domElement);
20
21// Create a cube
22const geometry = new THREE.BoxGeometry(1, 1, 1);
23const material = new THREE.MeshStandardMaterial({ color: 0x6495ed });
24const cube = new THREE.Mesh(geometry, material);
25scene.add(cube);
26
27// Add lighting
28const light = new THREE.DirectionalLight(0xffffff, 1);
29light.position.set(1, 1, 1);
30scene.add(light);
31
32const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
33scene.add(ambientLight);
34
35// Animation loop
36function animate() {
37  requestAnimationFrame(animate);
38  
39  // Rotate the cube
40  cube.rotation.x += 0.01;
41  cube.rotation.y += 0.01;
42  
43  // Render the scene
44  renderer.render(scene, camera);
45}
46
47animate();
48

Advanced Techniques in Three.js

Working with 3D Models

Three.js supports various 3D model formats, with GLTF (GL Transmission Format) being the recommended format:

1import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
2
3const loader = new GLTFLoader();
4loader.load(
5  'path/to/model.gltf',
6  (gltf) => {
7    // Model loaded successfully
8    scene.add(gltf.scene);
9  },
10  (progress) => {
11    // Loading progress
12    console.log((progress.loaded / progress.total) * 100 + '% loaded');
13  },
14  (error) => {
15    // Error loading model
16    console.error('An error happened:', error);
17  }
18);
19

Creating Realistic Materials

Three.js offers various material types to create realistic-looking objects:

1// Standard material with physical properties
2const standardMaterial = new THREE.MeshStandardMaterial({
3  color: 0xff0000,
4  roughness: 0.7,
5  metalness: 0.2
6});
7
8// Physical material for even more realism
9const physicalMaterial = new THREE.MeshPhysicalMaterial({
10  color: 0x049ef4,
11  roughness: 0.5,
12  metalness: 0.7,
13  clearcoat: 0.3,
14  clearcoatRoughness: 0.25
15});
16

Implementing Post-Processing Effects

Post-processing effects can significantly enhance the visual quality of your scene:

1import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js';
2import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass.js';
3import { UnrealBloomPass } from 'three/examples/jsm/postprocessing/UnrealBloomPass.js';
4
5// Create a composer
6const composer = new EffectComposer(renderer);
7
8// Add render pass
9const renderPass = new RenderPass(scene, camera);
10composer.addPass(renderPass);
11
12// Add bloom pass
13const bloomPass = new UnrealBloomPass(
14  new THREE.Vector2(window.innerWidth, window.innerHeight),
15  1.5, // strength
16  0.4, // radius
17  0.85 // threshold
18);
19composer.addPass(bloomPass);
20
21// Use composer instead of renderer in animation loop
22function animate() {
23  requestAnimationFrame(animate);
24  composer.render();
25}
26

Integrating Three.js with React

Using Three.js with React can be simplified with libraries like React Three Fiber:

1import React, { useRef } from 'react';
2import { Canvas, useFrame } from '@react-three/fiber';
3import { OrbitControls } from '@react-three/drei';
4
5function Box(props) {
6  const meshRef = useRef();
7  
8  useFrame(() => {
9    meshRef.current.rotation.x += 0.01;
10    meshRef.current.rotation.y += 0.01;
11  });
12  
13  return (
14    <mesh {...props} ref={meshRef}>
15      <boxGeometry args={[1, 1, 1]} />
16      <meshStandardMaterial color="#6495ed" />
17    </mesh>
18  );
19}
20
21export default function ThreeScene() {
22  return (
23    <Canvas>
24      <ambientLight intensity={0.5} />
25      <directionalLight position={[10, 10, 5]} intensity={1} />
26      <Box position={[0, 0, 0]} />
27      <OrbitControls />
28    </Canvas>
29  );
30}
31

Optimizing Three.js Performance

3D graphics can be resource-intensive. Here are some tips to optimize performance:

1. Use Instancing for Repeated Objects

1const geometry = new THREE.BoxGeometry(0.2, 0.2, 0.2);
2const material = new THREE.MeshNormalMaterial();
3
4// Create instanced mesh
5const instancedMesh = new THREE.InstancedMesh(geometry, material, 1000);
6
7// Position each instance
8for (let i = 0; i < 1000; i++) {
9  const position = new THREE.Vector3(
10    Math.random() * 10 - 5,
11    Math.random() * 10 - 5,
12    Math.random() * 10 - 5
13  );
14  
15  const matrix = new THREE.Matrix4();
16  matrix.setPosition(position);
17  
18  instancedMesh.setMatrixAt(i, matrix);
19}
20
21scene.add(instancedMesh);
22

2. Implement Level of Detail (LOD)

1import { LOD } from 'three';
2
3const lod = new THREE.LOD();
4
5// High detail model (close distance)
6const highDetailGeometry = new THREE.SphereGeometry(1, 64, 64);
7const highDetailMesh = new THREE.Mesh(highDetailGeometry, material);
8lod.addLevel(highDetailMesh, 0);
9
10// Medium detail model (medium distance)
11const mediumDetailGeometry = new THREE.SphereGeometry(1, 32, 32);
12const mediumDetailMesh = new THREE.Mesh(mediumDetailGeometry, material);
13lod.addLevel(mediumDetailMesh, 10);
14
15// Low detail model (far distance)
16const lowDetailGeometry = new THREE.SphereGeometry(1, 16, 16);
17const lowDetailMesh = new THREE.Mesh(lowDetailGeometry, material);
18lod.addLevel(lowDetailMesh, 50);
19
20scene.add(lod);
21

3. Use Object Pooling

Instead of creating and destroying objects frequently, reuse them:

1// Create a pool of objects
2const particlePool = [];
3for (let i = 0; i < 100; i++) {
4  const particle = createParticle();
5  particle.visible = false;
6  scene.add(particle);
7  particlePool.push(particle);
8}
9
10// Reuse objects from the pool
11function getParticle() {
12  for (const particle of particlePool) {
13    if (!particle.visible) {
14      particle.visible = true;
15      return particle;
16    }
17  }
18  return null; // Pool exhausted
19}
20
21// Return particle to pool when done
22function releaseParticle(particle) {
23  particle.visible = false;
24}
25

Real-World Applications of Three.js

Three.js is used in a wide variety of applications:

  • Product Configurators: Interactive 3D product viewers
  • Data Visualization: Complex data represented in 3D space
  • Educational Tools: Interactive learning experiences
  • Games: Browser-based 3D games
  • Virtual Tours: Immersive exploration of spaces
  • Architectural Visualization: Interactive building models

Conclusion

Three.js opens up a world of possibilities for creating immersive 3D experiences on the web. By mastering its fundamentals and advanced techniques, you can build engaging visualizations that were once only possible in native applications.

Ready to start building? Check out the official Three.js documentation and examples for inspiration and detailed guides.

Remember that the best way to learn Three.js is by experimenting and building projects. Start small, understand the fundamentals, and gradually incorporate more advanced techniques as you become comfortable with the library.