šŸš€ LEVEL UP TO SENIOR:Unlock 500+ Advanced Practical Challenges & Exercises.
šŸŽ“ COURSERA PARTNER:Earn professional Google, Meta, and IBM certificates to supercharge your resume.
HTML MASTER CLASS /// LEARN TAGS /// BUILD STRUCTURE /// SEMANTIC WEB /// HTML MASTER CLASS /// LEARN TAGS ///

Introduction to WebGL & Three.js

Learn the history of WebGL, what Three.js is, and how React Three Fiber revolutionizes 3D development.

⚔ Total XP: 0|šŸ’» threejs XP: 0

Skill Matrix

UNLOCK NODES BY LEARNING NEW TAGS.

System Hub

Core 3D concepts.

Quick Quiz //

What is the primary risk of skipping proper Scene/Camera/Renderer setup in Three.js?


šŸš€ LEVEL UP TO SENIOR:Unlock 500+ Advanced Practical Challenges & Exercises.
šŸŽ“ COURSERA PARTNER:Earn professional Google, Meta, and IBM certificates to supercharge your resume.

Listen up. If you're building modern applications, understanding Introduction to WebGL & Three.js is non-negotiable. This is where simple logic turns into intelligent behavior.

1Why Three.js Replaced Raw WebGL

Welcome to the world of 3D on the Web! Before Three.js, building 3D scenes meant writing hundreds of lines of complex WebGL code — manually compiling GLSL shaders, managing vertex buffers, and hand-rolling matrix math just to draw a single triangle.

Three.js wraps that low-level WebGL API in a JavaScript-friendly object model: instead of shader boilerplate, you work with THREE.Mesh, THREE.Geometry, and THREE.Material objects that read like plain JavaScript. This doesn't remove WebGL — it's still running underneath — but it turns weeks of graphics-programming setup into a few readable lines of code you can iterate on quickly.

āœ•
—
+
// Vanilla WebGL requires insane amounts of math
// Three.js makes it as easy as building with Lego bricks!
localhost:3000
Browser Preview
WebGL Output
3D Scene rendered. Objects: 4, Draw Calls: Optimized.

2The Holy Trinity: Scene, Camera, Renderer

At its core, a 3D application needs 3 things: A Scene (the universe), a Camera (your eyes), and a Renderer (the projector). We call this the Holy Trinity.

The Scene is a container that holds every object, light, and group you add to it — think of it as the 3D equivalent of the DOM tree. The Camera defines the viewpoint and field of view used to project that 3D world onto a 2D screen. The Renderer takes the Scene and Camera together and actually draws the pixels, frame after frame, using the GPU via WebGL. None of the three is optional — remove any one of them and there's nothing to render.

āœ•
—
+
import * as THREE from 'three';

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera();
const renderer = new THREE.WebGLRenderer();
localhost:3000
Browser Preview
WebGL Output
3D Scene rendered. Objects: 4, Draw Calls: Optimized.

3How the Trinity Works Together at Render Time

Every animation frame, the renderer asks: given this camera's position and this scene's contents, what should appear on screen? It calculates which objects are visible, applies lighting and materials, and rasterizes the result into the canvas element.

This loop typically runs inside requestAnimationFrame, redrawing up to 60 times per second. Understanding this cycle matters because anything you change on the scene or camera before the next frame — a rotation, a new mesh, a moved light — will be reflected in the very next render, which is what makes real-time 3D interactivity possible.

āœ•
—
+
scene, camera, and ???
localhost:3000
Browser Preview
WebGL Output
3D Scene rendered. Objects: 4, Draw Calls: Optimized.

4Enter React Three Fiber (R3F)

In modern React apps, we use a wrapper called 'React Three Fiber' (R3F). It takes care of the Holy Trinity for us by just using a Canvas component — no manual new THREE.Scene() or renderer setup required.

R3F isn't a reimplementation of Three.js; it's a React reconciler that lets you describe a Three.js scene declaratively, the same way you'd describe a DOM tree with JSX. Under the hood it still creates real Three.js objects and drives the same render loop — it just manages their lifecycle (creation, updates, disposal) for you as your component tree changes.

āœ•
—
+
import { Canvas } from '@react-three/fiber';

function App() {
  return (
    <Canvas>
      {/* 3D Objects go here */}
    </Canvas>
  );
}
localhost:3000
Browser Preview
WebGL Output
3D Scene rendered. Objects: 4, Draw Calls: Optimized.

5Rendering Your First Mesh

Let's actually render something! Let's put a rotating cube inside our Canvas and watch the 3D preview update in real time.

A mesh in R3F pairs a geometry (the shape, here boxGeometry) with a material (the surface appearance, here meshStandardMaterial), exactly like Three.js's new THREE.Mesh(geometry, material). The useFrame hook runs on every animation frame, letting you mutate the mesh's rotation values directly — this is how you animate objects without manually managing a render loop yourself.

āœ•
—
+
const Cube = () => {
  const meshRef = React.useRef();
  useFrame((state, delta) => {
    meshRef.current.rotation.x += delta;
    meshRef.current.rotation.y += delta;
  });
  return (
    <mesh ref={meshRef}>
      <boxGeometry />
      <meshStandardMaterial color="hotpink" />
    </mesh>
  );
};

render(
  <Canvas>
    <ambientLight intensity={0.5} />
    <directionalLight position={[2, 5, 2]} />
    <Cube />
  </Canvas>
);
localhost:3000
Browser Preview
WebGL Output
3D Scene rendered. Objects: 4, Draw Calls: Optimized.

6The Canvas Component

In React Three Fiber, the Canvas component automatically creates the Scene, Camera, and Renderer for you and mounts a real canvas DOM element in its place.

Everything you nest inside Canvas — lights, meshes, groups — becomes part of that scene graph automatically. This is why R3F code looks so much shorter than vanilla Three.js: the imperative setup (new THREE.Scene(), new THREE.WebGLRenderer(), appending the canvas to the DOM) all happens implicitly the moment you render a Canvas component.

āœ•
—
+
<??? />
localhost:3000
Browser Preview
WebGL Output
3D Scene rendered. Objects: 4, Draw Calls: Optimized.

7Lowercase Tags Map to Three.js Classes

Notice how we used mesh, boxGeometry, and meshStandardMaterial? In R3F, all Three.js classes are available as lowercase HTML-like tags, generated automatically from the THREE namespace.

The naming convention is mechanical: THREE.BoxGeometry becomes boxGeometry, THREE.MeshStandardMaterial becomes meshStandardMaterial, and so on for every class Three.js exports. This means you rarely need to look up R3F-specific documentation for basic primitives — if you know the Three.js class name, you already know its JSX tag.

āœ•
—
+
// THREE.BoxGeometry -> <boxGeometry />
// THREE.MeshStandardMaterial -> <meshStandardMaterial />
localhost:3000
Browser Preview
WebGL Output
3D Scene rendered. Objects: 4, Draw Calls: Optimized.

8Passing Props Like Constructor Arguments

You can pass properties to these tags just like React props. To set the color, we use the color prop, exactly as you would pass a parameter to new THREE.MeshStandardMaterial({ color: '#00FF00' }) in vanilla Three.js.

Most Three.js constructor options map directly to JSX props this way. For properties that take multiple arguments (like a geometry's width, height, and depth), R3F uses an args array prop instead — boxGeometry args={[1, 1, 1]} — since JSX props can only pass one value each.

āœ•
—
+
<meshStandardMaterial color="#00FF00" />
localhost:3000
Browser Preview
WebGL Output
3D Scene rendered. Objects: 4, Draw Calls: Optimized.

9Building Other Primitive Geometries

The same tag-mapping rule applies to every geometry Three.js ships with, including THREE.SphereGeometry, which becomes sphereGeometry in React Three Fiber.

Each primitive geometry accepts its own args — a sphere takes radius and segment counts, a box takes width/height/depth, a cylinder takes top/bottom radius and height. Checking the Three.js documentation for a class's constructor signature tells you exactly what to pass in the args array.

āœ•
—
+
<??? />
localhost:3000
Browser Preview
WebGL Output
3D Scene rendered. Objects: 4, Draw Calls: Optimized.

10Swapping in a Rotating Sphere

Let's change our cube into a rotating green sphere! Swapping the shape is as simple as swapping the geometry tag — the mesh, material, and animation logic barely need to change.

The args={[1.5, 32, 32]} here set the sphere's radius to 1.5 and its width/height segment counts to 32 each, controlling how smooth the sphere looks. Higher segment counts produce a rounder sphere at the cost of more triangles to render — a tradeoff worth remembering once you start optimizing scenes with many objects.

āœ•
—
+
const Sphere = () => {
  const meshRef = React.useRef();
  useFrame((state, delta) => {
    meshRef.current.rotation.y -= delta;
  });
  return (
    <mesh ref={meshRef}>
      <sphereGeometry args={[1.5, 32, 32]} />
      <meshStandardMaterial color="#CCFF00" wireframe />
    </mesh>
  );
};

render(
  <Canvas>
    <ambientLight intensity={1} />
    <Sphere />
  </Canvas>
);
localhost:3000
Browser Preview
WebGL Output
3D Scene rendered. Objects: 4, Draw Calls: Optimized.

11What You've Built and What's Next

Awesome! You've just built your first interactive 3D scenes. In the next lessons, we'll dive deeper into the Scene graph and Camera types (perspective vs. orthographic).

The pattern you just learned — geometry and material combined inside a mesh, animated via a frame hook — is the foundation for almost everything else in Three.js and R3F, from complex character models to particle systems. Every advanced technique you'll see later is built on this same core loop.

āœ•
—
+
// šŸš€ Level 1 Complete!
localhost:3000
Browser Preview
WebGL Output
3D Scene rendered. Objects: 4, Draw Calls: Optimized.

12Step-by-Step Breakdown

Welcome to the world of 3D on the Web! Before Three.js, building 3D scenes meant writing hundreds of lines of complex WebGL code. Three.js changed everything.

At its core, a 3D application needs 3 things: A Scene (the universe), a Camera (your eyes), and a Renderer (the projector). We call this the Holy Trinity.

What are the three fundamental components required to render anything in Three.js?

  • →geometry
  • →renderer
  • →mesh

In modern React apps, we use a wrapper called 'React Three Fiber' (R3F). It takes care of the Holy Trinity for us by just using a <Canvas> component!

Let's actually render something! Let's put a rotating cube inside our Canvas. Look at the 3D preview!

In React Three Fiber, what component automatically creates the Scene, Camera, and Renderer?

  • →Scene
  • →Canvas
  • →WebGL

Notice how we used <mesh>, <boxGeometry>, and <meshStandardMaterial>? In R3F, all Three.js classes are available as lowercase HTML-like tags.

You can pass properties to these tags just like React props. To set the color, we use the color prop.

How would you write a THREE.SphereGeometry in React Three Fiber?

  • →SphereGeometry
  • →sphere
  • →sphereGeometry

Let's change our cube into a rotating green sphere!

Awesome! You've just built your first interactive 3D scenes. In the next lessons, we'll dive deeper into the Scene and Cameras.

Level Up šŸš€

Advanced cheat sheets, SEO tricks, and interview prep for this topic.

Browser Support

ChromeSupported

Fully supported.

FirefoxSupported

Fully supported.

SafariSupported

Fully supported.

EdgeSupported

Fully supported.

Accessibility (A11y)

1Provide a Text Alternative for Canvas-Rendered 3D Content

A WebGL canvas is a single opaque bitmap to assistive technology — screen readers cannot inspect meshes, lights, or geometry inside it. Always wrap the Canvas with an aria-label or adjacent visually-hidden text describing what the scene shows, so the experience isn't entirely invisible to non-sighted users.

<div role="img" aria-label="3D rotating cube demo"><Canvas>...</Canvas></div>

SEO Implications

  • 1

    3D Canvas Content Is Invisible to Search Crawlers

    Everything rendered inside a WebGL canvas is pixels, not indexable text or DOM structure — a page's SEO value for Three.js content comes entirely from the surrounding text, headings, and code samples on the page, not from anything happening inside the canvas element itself.

Best Practices

Always Dispose of Geometries, Materials, and Textures When Removing Objects

Three.js resources allocate GPU memory that JavaScript's garbage collector cannot reclaim on its own. Call .dispose() on any geometry, material, or texture before removing its mesh from the scene, especially in single-page apps where components mount and unmount repeatedly.

Reuse Geometries and Materials Across Multiple Meshes Where Possible

If you're rendering many similar objects (like a field of trees), share one geometry and material instance across all of them via instancing or simple reuse, rather than constructing a new one per mesh — this dramatically reduces memory use and draw calls.

Frequent Bugs

THE BUG

Adding lights and geometry to a scene but seeing nothing render because the camera is positioned at the same coordinates as the object (0,0,0) or facing the wrong direction.

THE FIX

Always explicitly set the camera's position away from the origin (e.g., camera.position.set(0, 0, 5)) and confirm it's pointed at your objects — R3F's default camera position is not guaranteed to frame arbitrary scene content correctly.

Real-World Examples

Product Configurators for E-Commerce

Furniture and sneaker brands use Three.js/R3F to let shoppers rotate, zoom, and recolor a 3D product model directly in the browser — built on exactly the Scene/Camera/Renderer trinity and mesh/geometry/material pattern covered in this lesson, just with more detailed imported models instead of a basic cube.

<Canvas camera={{ position: [0, 0, 5] }}>
  <ProductModel color={selectedColor} />
  <OrbitControls />
</Canvas>

Interview Prep

?Frequently Asked Questions

Pascual Vila

Pascual Vila

Frontend Instructor // Code Syllabus

Common Pitfalls & Errors

The Error //

Not reading error messages carefully

Uncaught TypeError: Cannot read properties of undefined (reading 'length') // Solution: Ensure the variable you are calling .length on is initialized as a string or an array, not undefined.

The Solution //

Most of the time, the compiler or interpreter tells you exactly what line caused the crash and why. Read stack traces from the top down to identify the root cause.

The Error //

Hardcoding sensitive credentials

// Wrong const API_KEY = 'sk-123456789'; // Correct const API_KEY = process.env.API_KEY;

The Solution //

Never hardcode API keys, passwords, or secrets in your source code. Use environment variables (.env files) to keep them secure and out of version control.

Continue Learning