Interactive 3D Graphics for Websites: WebGL Tutorial + Live Demos

3D graphics on the web aren’t a gimmick anymore. They’re practical, performant, and surprisingly accessible.

Five years ago, 3D meant slow loading times, browser compatibility nightmares, and experiences that only worked on high-end devices. Today, even mid-range phones handle impressive 3D scenes smoothly.

You’ve seen 3D on product pages where you rotate items to examine them. Portfolio sites with immersive 3D environments. Landing pages with interactive 3D elements that respond to scrolling. These aren’t Flash animations or embedded players. They’re native web graphics running directly in the browser.

This tutorial teaches you how to build interactive 3D experiences using Three.js, the most popular JavaScript library for 3D graphics. We’ll start simple and build complexity. By the end, you’ll understand how to add 3D to your projects.

No prior 3D experience required. Just JavaScript knowledge and curiosity.

TL;DR: 3D Web Graphics Essentials

  • Three.js simplifies WebGL – Handles complex WebGL API for you
  • Scene, camera, renderer – Three core components for any 3D
  • Geometry + Material = Mesh – Objects are made from shape and appearance
  • Lights are essential – Without lights, you see nothing
  • Animation loop renders frames – RequestAnimationFrame updates scene
  • Performance matters – Optimize poly count, textures, and draw calls
  • GLTF for models – Industry standard for 3D model loading
  • Responsive canvas sizing – Handle window resizes properly
  • Progressive enhancement – Provide fallbacks for unsupported devices

Understanding WebGL and Three.js

Before we code, understand what you’re working with.

What is WebGL?

WebGL (Web Graphics Library) is a JavaScript API that renders 2D and 3D graphics in browsers using the GPU (Graphics Processing Unit).

It’s based on OpenGL ES, the graphics standard for mobile devices. This means WebGL code runs on phones, tablets, and desktops.

Key advantages:

  • Hardware accelerated (uses GPU, not CPU)
  • No plugins required (native browser support)
  • Cross-platform compatibility
  • Access to shader programming for custom effects

The challenge: Raw WebGL is complex. You write shader code, manage buffers, handle matrices manually. It works but requires deep graphics programming knowledge.

Why Three.js?

Three.js wraps WebGL in a friendly JavaScript API. It handles the complex stuff while giving you intuitive controls.

With Three.js, creating a 3D cube takes 10 lines instead of 200. You focus on what you want to create, not how graphics APIs work.

Three.js handles:

  • Scene management
  • Camera systems
  • Material and lighting
  • Geometry creation
  • Model loading
  • Animation
  • Math operations (vectors, matrices, quaternions)

You tell Three.js “create a cube with this material under this light.” It translates that to WebGL commands.

Browser Support

Modern WebGL (WebGL 2.0) works in:

  • Chrome/Edge (version 56+)
  • Firefox (version 51+)
  • Safari (version 15+)
  • Mobile browsers (iOS Safari 15+, Chrome Mobile)

That’s over 95% of global browser usage. WebGL is safe for production.

Exceptions: Some enterprise environments disable WebGL for security. Always provide fallback content or detect support before rendering.

Setting Up Your First 3D Scene

Let’s build something immediately. A rotating cube. The “Hello World” of 3D graphics.

Basic HTML Setup

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>3D Graphics Demo</title>
  <style>
    body {
      margin: 0;
      overflow: hidden;
    }
    
    canvas {
      display: block;
    }
  </style>
</head>
<body>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
  <script src="script.js"></script>
</body>
</html>

We remove body margins and set overflow hidden so the canvas fills the viewport cleanly.

Creating Scene, Camera, Renderer

Every Three.js project needs three core components:

// Scene: Container for all 3D objects
const scene = new THREE.Scene();

// Camera: Defines what we see
const camera = new THREE.PerspectiveCamera(
  75,                                    // Field of view (degrees)
  window.innerWidth / window.innerHeight, // Aspect ratio
  0.1,                                   // Near clipping plane
  1000                                   // Far clipping plane
);

// Renderer: Draws the scene using WebGL
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

Scene holds everything. Objects, lights, cameras all go in the scene.

Camera determines perspective. PerspectiveCamera mimics human vision with depth and perspective. Position it to view your objects.

Renderer draws pixels. It takes scene and camera, renders them to a canvas element.

Adding a 3D Object

Objects in Three.js are meshes made from geometry (shape) and material (appearance):

// Create geometry (shape)
const geometry = new THREE.BoxGeometry(1, 1, 1);

// Create material (appearance)
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });

// Combine into mesh
const cube = new THREE.Mesh(geometry, material);

// Add to scene
scene.add(cube);

// Position camera
camera.position.z = 5;

BoxGeometry creates a cube. Parameters are width, height, depth.

MeshBasicMaterial is the simplest material. It shows solid color, unaffected by lights.

Mesh combines geometry and material into a renderable object.

We position the camera back (z = 5) so we can see the cube at origin (0, 0, 0).

Rendering the Scene

function animate() {
  requestAnimationFrame(animate);
  
  // Rotate cube
  cube.rotation.x += 0.01;
  cube.rotation.y += 0.01;
  
  // Render scene
  renderer.render(scene, camera);
}

animate();

requestAnimationFrame calls our function before next browser repaint. This creates smooth 60fps animation.

We rotate the cube slightly each frame, then render the updated scene.

That’s it. A rotating 3D cube in about 30 lines of JavaScript.

Working with Lights

MeshBasicMaterial doesn’t react to lights. For realistic materials, you need lights and different materials.

Types of Lights

AmbientLight provides uniform lighting from all directions:

const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(ambientLight);

This prevents completely black shadows but doesn’t create depth alone.

DirectionalLight emits parallel rays like sunlight:

const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(5, 5, 5);
scene.add(directionalLight);

Good for outdoor scenes or primary lighting.

PointLight emits light in all directions from a point, like a light bulb:

const pointLight = new THREE.PointLight(0xffffff, 1, 100);
pointLight.position.set(10, 10, 10);
scene.add(pointLight);

The third parameter is distance where light fades to zero.

SpotLight creates a cone of light:

const spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(10, 20, 10);
spotLight.castShadow = true;
scene.add(spotLight);

Useful for dramatic lighting or highlighting specific objects.

Light-Reactive Materials

Switch from MeshBasicMaterial to materials that respond to lights:

// Matte, non-shiny surface
const material = new THREE.MeshLambertMaterial({ color: 0x00ff00 });

// Shiny surface with specular highlights
const material = new THREE.MeshPhongMaterial({ 
  color: 0x00ff00,
  shininess: 100 
});

// Physically accurate material (best looking, more expensive)
const material = new THREE.MeshStandardMaterial({
  color: 0x00ff00,
  metalness: 0.5,
  roughness: 0.5
});

MeshStandardMaterial is the modern choice. It uses physically-based rendering (PBR) for realistic results.

Simple Lighting Setup

A good starting point for most scenes:

// Soft ambient light
const ambient = new THREE.AmbientLight(0xffffff, 0.4);
scene.add(ambient);

// Main directional light
const directional = new THREE.DirectionalLight(0xffffff, 0.8);
directional.position.set(10, 10, 5);
scene.add(directional);

// Fill light (dimmer, opposite side)
const fill = new THREE.DirectionalLight(0xffffff, 0.3);
fill.position.set(-10, 0, -5);
scene.add(fill);

This three-point lighting creates depth without harsh shadows.

Loading 3D Models

Creating complex shapes programmatically is tedious. Usually you load models created in 3D software.

GLTF Format

GLTF (GL Transmission Format) is the industry standard for web 3D models. Think of it like JPEG for images but for 3D.

Why GLTF:

  • Compact file size
  • Fast loading and parsing
  • Supports animations, materials, textures
  • Industry-wide support (Blender, Maya, 3ds Max all export GLTF)

GLTF comes in two variants:

  • .gltf (JSON + separate files)
  • .glb (binary, everything in one file)

Use .glb for web. Single file, easier to manage.

Loading a Model

// Import GLTFLoader (required for GLTF loading)
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';

const loader = new GLTFLoader();

loader.load(
  'models/scene.glb',  // Path to model
  (gltf) => {
    // Success callback
    const model = gltf.scene;
    scene.add(model);
    
    // Adjust scale if needed
    model.scale.set(2, 2, 2);
    
    // Position model
    model.position.set(0, 0, 0);
  },
  (progress) => {
    // Progress callback
    console.log((progress.loaded / progress.total * 100) + '% loaded');
  },
  (error) => {
    // Error callback
    console.error('Error loading model:', error);
  }
);

Important: Models often come in unpredictable scales. You might need to adjust scale drastically. A model could be tiny (0.001) or huge (1000).

Where to Get Models

Free models:

  • Sketchfab (many free models)
  • Poly Haven (high quality, CC0 license)
  • Google Poly (archived but models still available)

Creating your own:

  • Blender (free, powerful)
  • Spline (web-based, beginner friendly)
  • Adobe Dimension

Export as GLTF/GLB from any of these tools.

Model Optimization

Models from 3D artists are often too detailed for web:

Reduce polygon count. Aim for under 50,000 triangles for objects that will be viewed close-up. Background objects can be much lower.

Compress textures. Use smaller image sizes. 1024×1024 instead of 4096×4096. Convert to compressed formats like KTX2.

Remove unused animations. If you’re not using animations, delete them to reduce file size.

Use tools like gltf-pipeline to optimize GLTF files automatically.

Adding Interactivity

Static 3D is nice. Interactive 3D is engaging.

Orbit Controls

Let users rotate, zoom, and pan the camera:

import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';

const controls = new OrbitControls(camera, renderer.domElement);

// Customize controls
controls.enableDamping = true;      // Smooth motion
controls.dampingFactor = 0.05;
controls.maxDistance = 10;          // Max zoom out
controls.minDistance = 2;           // Max zoom in

function animate() {
  requestAnimationFrame(animate);
  controls.update();  // Update controls each frame
  renderer.render(scene, camera);
}

Now users can click-drag to rotate, scroll to zoom, right-click-drag to pan.

Raycasting for Click Detection

Detect which object the user clicks:

const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2();

function onMouseClick(event) {
  // Convert mouse position to normalized device coordinates
  mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
  mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
  
  // Update raycaster
  raycaster.setFromCamera(mouse, camera);
  
  // Check for intersections
  const intersects = raycaster.intersectObjects(scene.children, true);
  
  if (intersects.length > 0) {
    const clicked = intersects[0].object;
    console.log('Clicked:', clicked);
    
    // Change color on click
    clicked.material.color.set(0xff0000);
  }
}

window.addEventListener('click', onMouseClick);

Raycasting shoots a ray from camera through mouse position. Returns objects the ray intersects.

Hover Effects

Similar to clicking, detect hovering:

let hoveredObject = null;

function onMouseMove(event) {
  mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
  mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
  
  raycaster.setFromCamera(mouse, camera);
  const intersects = raycaster.intersectObjects(scene.children, true);
  
  // Reset previous hover
  if (hoveredObject) {
    hoveredObject.material.emissive.setHex(0x000000);
  }
  
  // Apply hover effect
  if (intersects.length > 0) {
    hoveredObject = intersects[0].object;
    hoveredObject.material.emissive.setHex(0x555555);
    document.body.style.cursor = 'pointer';
  } else {
    hoveredObject = null;
    document.body.style.cursor = 'default';
  }
}

window.addEventListener('mousemove', onMouseMove);

This highlights objects on hover and changes cursor.

Scroll-Triggered Animation

Animate 3D objects based on scroll position:

function onScroll() {
  const scrollPercent = window.scrollY / (document.body.offsetHeight - window.innerHeight);
  
  // Rotate object based on scroll
  cube.rotation.y = scrollPercent * Math.PI * 2;
  
  // Move camera
  camera.position.y = scrollPercent * 10;
}

window.addEventListener('scroll', onScroll);

This creates parallax-style effects where 3D objects respond to scrolling.

Performance Optimization

3D graphics are resource-intensive. Optimize for smooth performance.

Polygon Count Management

Keep it low. Each triangle must be processed and rendered. Fewer triangles = better performance.

Level of Detail (LOD). Show detailed models up close, simpler models far away:

const lod = new THREE.LOD();

// High detail (close up)
const highDetail = new THREE.Mesh(
  new THREE.SphereGeometry(1, 32, 32),
  material
);
lod.addLevel(highDetail, 0);

// Medium detail
const mediumDetail = new THREE.Mesh(
  new THREE.SphereGeometry(1, 16, 16),
  material
);
lod.addLevel(mediumDetail, 5);

// Low detail (far away)
const lowDetail = new THREE.Mesh(
  new THREE.SphereGeometry(1, 8, 8),
  material
);
lod.addLevel(lowDetail, 10);

scene.add(lod);

Three.js automatically switches between levels based on camera distance.

Texture Optimization

Use appropriate sizes. Don’t load 4096×4096 textures if object will be small on screen.

Compress textures. Use compressed formats (KTX2, Basis) for smaller file sizes.

Mipmaps are automatic. Three.js generates them by default for better performance at distance.

Reuse materials. If multiple objects use the same material, create one material instance and share it:

const sharedMaterial = new THREE.MeshStandardMaterial({ color: 0x00ff00 });

const cube1 = new THREE.Mesh(geometry, sharedMaterial);
const cube2 = new THREE.Mesh(geometry, sharedMaterial);
const cube3 = new THREE.Mesh(geometry, sharedMaterial);

This reduces draw calls and memory usage.

Frustum Culling

Three.js automatically doesn’t render objects outside camera view. But you can optimize further:

// Mark objects that move rarely as static
mesh.matrixAutoUpdate = false;
mesh.updateMatrix();

This tells Three.js not to recalculate the object’s transformation matrix every frame.

Reduce Draw Calls

Merge geometries when possible:

import { BufferGeometryUtils } from 'three/examples/jsm/utils/BufferGeometryUtils.js';

const geometries = [];
for (let i = 0; i < 100; i++) {
  const geo = new THREE.BoxGeometry(1, 1, 1);
  geo.translate(i * 2, 0, 0);
  geometries.push(geo);
}

const merged = BufferGeometryUtils.mergeGeometries(geometries);
const mesh = new THREE.Mesh(merged, material);
scene.add(mesh);

Instead of 100 draw calls, you have one. Huge performance gain.

Monitor Performance

Use browser dev tools:

Chrome/Edge: Performance tab records frame rate and GPU usage.

Firefox: Performance tool shows rendering times.

Stats.js library shows real-time FPS:

import Stats from 'three/examples/jsm/libs/stats.module.js';

const stats = new Stats();
document.body.appendChild(stats.dom);

function animate() {
  requestAnimationFrame(animate);
  stats.begin();
  
  // Your rendering code
  
  stats.end();
}

Aim for consistent 60fps. Drops below 30fps feel sluggish.

Responsive 3D Scenes

3D must adapt to different screen sizes like responsive web design.

Handle Window Resize

function onWindowResize() {
  // Update camera aspect ratio
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  
  // Update renderer size
  renderer.setSize(window.innerWidth, window.innerHeight);
}

window.addEventListener('resize', onWindowResize);

Without this, 3D scene distorts when window resizes.

Mobile Considerations

Mobile devices have less GPU power. Adjust accordingly:

const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);

const renderer = new THREE.WebGLRenderer({ 
  antialias: !isMobile,  // Disable on mobile
  powerPreference: 'high-performance'
});

// Reduce pixel ratio on mobile
const pixelRatio = isMobile ? 1 : Math.min(window.devicePixelRatio, 2);
renderer.setPixelRatio(pixelRatio);

// Simpler materials on mobile
const material = isMobile 
  ? new THREE.MeshLambertMaterial({ color: 0x00ff00 })
  : new THREE.MeshStandardMaterial({ color: 0x00ff00 });

Canvas Sizing Strategies

Full viewport:

canvas {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

Fixed container:

const container = document.getElementById('canvas-container');
const width = container.clientWidth;
const height = container.clientHeight;

camera.aspect = width / height;
camera.updateProjectionMatrix();
renderer.setSize(width, height);

Accessibility Considerations

3D graphics present accessibility challenges. Address them proactively.

Provide Fallback Content

Not all users can see or interact with 3D:

<div id="webgl-container">
  <canvas></canvas>
  <div class="fallback-content" style="display: none;">
    <img src="fallback-image.jpg" alt="Product view">
    <p>Interactive 3D view not available. Static image shown.</p>
  </div>
</div>
if (!renderer) {
  // WebGL not supported
  document.querySelector('.fallback-content').style.display = 'block';
}

Reduced Motion Preference

Respect prefers-reduced-motion:

const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;

function animate() {
  requestAnimationFrame(animate);
  
  if (!prefersReducedMotion) {
    cube.rotation.y += 0.01;
  }
  
  renderer.render(scene, camera);
}

Keyboard Controls

If you have OrbitControls, they work with keyboard automatically. For custom interactions, add keyboard support:

document.addEventListener('keydown', (event) => {
  switch(event.key) {
    case 'ArrowLeft':
      camera.position.x -= 0.1;
      break;
    case 'ArrowRight':
      camera.position.x += 0.1;
      break;
    // Add more controls
  }
});

Screen Reader Support

Describe what the 3D content shows:

<div role="img" aria-label="3D model of red sports car, rotatable with mouse">
  <canvas id="canvas"></canvas>
</div>

For complex scenes, provide text description of key elements and interactions.

Real-World Use Cases

Let’s look at practical applications of 3D on websites.

Product Viewers

E-commerce sites use 3D to show products from all angles:

// Load product model
loader.load('models/shoe.glb', (gltf) => {
  const shoe = gltf.scene;
  scene.add(shoe);
  
  // Center and scale appropriately
  const box = new THREE.Box3().setFromObject(shoe);
  const center = box.getCenter(new THREE.Vector3());
  shoe.position.sub(center);
  
  // Enable rotation
  const controls = new OrbitControls(camera, renderer.domElement);
  controls.enableZoom = true;
  controls.autoRotate = true;
  controls.autoRotateSpeed = 2;
});

Users can examine products closely, increasing confidence before purchase.

Portfolio Showcases

Creative professionals use 3D environments to present work:

// Create gallery space
const walls = new THREE.Mesh(
  new THREE.BoxGeometry(20, 10, 20),
  new THREE.MeshStandardMaterial({ 
    color: 0xffffff,
    side: THREE.BackSide 
  })
);
scene.add(walls);

// Add artwork as textured planes
const artworks = [
  { texture: 'art1.jpg', position: [0, 5, -9.9] },
  { texture: 'art2.jpg', position: [-9.9, 5, 0] },
  // More artworks
];

artworks.forEach(art => {
  const texture = new THREE.TextureLoader().load(art.texture);
  const plane = new THREE.Mesh(
    new THREE.PlaneGeometry(4, 3),
    new THREE.MeshBasicMaterial({ map: texture })
  );
  plane.position.set(...art.position);
  scene.add(plane);
});

Users navigate a virtual gallery space.

Data Visualization

Represent data in 3D space:

// Create 3D bar chart
const data = [10, 25, 15, 30, 20];

data.forEach((value, index) => {
  const bar = new THREE.Mesh(
    new THREE.BoxGeometry(1, value, 1),
    new THREE.MeshStandardMaterial({ color: 0x0088ff })
  );
  
  bar.position.x = index * 2;
  bar.position.y = value / 2;
  
  scene.add(bar);
});

3D can make complex data more understandable through spatial relationships.

Interactive Configurators

Let users customize products in real-time:

let currentColor = 0xff0000;

// Color picker
document.getElementById('color-picker').addEventListener('change', (e) => {
  currentColor = parseInt(e.target.value.replace('#', '0x'));
  carMaterial.color.setHex(currentColor);
});

// Part selection
const parts = {
  wheels: wheelMesh,
  body: bodyMesh,
  interior: interiorMesh
};

document.querySelectorAll('.part-option').forEach(button => {
  button.addEventListener('click', (e) => {
    const partName = e.target.dataset.part;
    const partMesh = parts[partName];
    partMesh.visible = !partMesh.visible;
  });
});

Users see their customizations immediately in 3D.

Common Pitfalls and Solutions

Avoid these common mistakes when working with 3D.

Mistake: Not Handling Aspect Ratio

Problem: Scene looks stretched or squashed.

Solution: Always update camera aspect ratio on resize and initially:

camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();

Mistake: Missing Lights

Problem: Scene is completely black with standard materials.

Solution: Add at least ambient + directional light. MeshBasicMaterial works without lights but looks flat.

Mistake: Huge File Sizes

Problem: Models take forever to load.

Solution: Optimize models before uploading. Reduce polygons, compress textures, use GLTF/GLB format.

Mistake: Memory Leaks

Problem: Performance degrades over time.

Solution: Dispose of geometries and materials when removing objects:

scene.remove(mesh);
mesh.geometry.dispose();
mesh.material.dispose();

Mistake: Z-Fighting

Problem: Surfaces flicker when they occupy same space.

Solution: Separate overlapping surfaces slightly or adjust camera near/far planes.

Mistake: Ignoring Performance Budget

Problem: Scene runs smoothly on your device but not on target devices.

Solution: Test on low-end devices. Profile regularly. Set performance budgets (max triangles, max draw calls).

Conclusion

3D graphics on the web are powerful tools for creating engaging, interactive experiences. With Three.js, they’re surprisingly accessible even for developers without 3D experience.

Key takeaways:

  • Three.js simplifies WebGL into manageable JavaScript API
  • Scene, camera, and renderer are three essential components
  • Lights are required for realistic materials to be visible
  • GLTF/GLB is the standard format for loading 3D models
  • Interactivity through raycasting, orbit controls, and event listeners
  • Performance optimization is critical for smooth experiences
  • Mobile devices need special consideration for lower power
  • Accessibility requires fallbacks and reduced motion support
  • Real-world applications include product viewers, portfolios, and visualizations

The action you should take today: Build the rotating cube example. Get Three.js running. Once you see your first 3D object rendering, everything else builds on that foundation.

3D graphics aren’t appropriate for every site. When they fit, they create memorable experiences that flat designs can’t match. Start simple, optimize aggressively, and always prioritize usability over visual complexity.

Ready to explore more cutting-edge interactions? Check out our guide on The Power of Micro-Interactions in Web Design (+ 20 Examples), where we cover subtle animations and interactions that enhance user experience.

Quick Reference: Three.js Essentials

Basic Setup:

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, width/height, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();

Creating Objects:

const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshStandardMaterial({ color: 0x00ff00 });
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);

Lighting:

const ambient = new THREE.AmbientLight(0xffffff, 0.5);
const directional = new THREE.DirectionalLight(0xffffff, 1);
scene.add(ambient, directional);

Animation:

function animate() {
  requestAnimationFrame(animate);
  mesh.rotation.y += 0.01;
  renderer.render(scene, camera);
}
animate();

Frequently Asked Questions

Do I need to know math for 3D graphics? Basic math helps but Three.js handles most calculations. Understanding coordinates, angles, and basic geometry is enough to start.

How performant is Three.js compared to native solutions? Three.js adds minimal overhead. Performance depends mainly on scene complexity. Well-optimized Three.js apps run smoothly on most devices.

Can I use 3D graphics on mobile devices? Yes, but optimize more aggressively. Reduce polygon counts, simpler materials, lower resolution. Test on actual mobile devices.

What file format should I use for 3D models? GLTF (specifically GLB, the binary version) is the web standard. It’s compact, loads fast, and widely supported.

How do I create 3D models? Use 3D software like Blender (free), Spline, or Adobe Dimension. Export as GLTF/GLB. Many free models available on Sketchfab and Poly Haven.

Is WebGL supported on all browsers? Over 95% of browsers support WebGL 1.0. Always provide fallback content for the small percentage that don’t.

How much does Three.js add to page size? The minified Three.js library is about 150KB gzipped. Additional modules you import add more, but you only load what you use.

References & Further Reading

  • Three.js Official Documentation
  • Three.js Fundamentals (threejsfundamentals.org)
  • “WebGL Programming Guide” – Matsuda & Lea
  • Bruno Simon’s Three.js Journey (course)
  • Three.js Examples (threejs.org/examples)
  • WebGL Fundamentals (webglfundamentals.org)
  • Khronos WebGL Specification