Why should you learn Three.js?

Want to make cool 3d stuff for the web? This is why you should and what you need to know.

The Bridge to the GPU

For decades, high-end 3D graphics were confined to native applications like AAA games or CAD software. The web was flat (and clunky and boring!). When WebGL (Web Graphics Library) arrived, it unlocked the power of those monster GPUs to be used inside the browser, but it came with a steep learning curve.

Just for completeness, this is what that looks like.

Writing raw WebGL is notoriously verbose. To draw a single 2d box in the browser, we need to first create a canvas element:

html
<canvas id='glCanvas' width='640' height='480'></canvas>

    <script id='vs' type='x-shader/x-vertex'>
      attribute vec2 position;
      void main() {
        gl_Position = vec4(position, 0.0, 1.0);
      }
    </script>

    <script id='fs' type='x-shader/x-fragment'>
      void main() {
        gl_FragColor = vec4(1.0, 0.5, 0.0, 1.0); // Orange
      }
    </script>

And then we have to fill it with our 2d box as generated by the GPU by rendering two triangles:

javascript
const canvas = document.querySelector('#glCanvas');
    const gl = canvas.getContext('webgl');

    if (!gl) {
      alert('WebGL not supported');
    }

    // 1. Compile Shaders
    function createShader(gl, type, source) {
      const shader = gl.createShader(type);
      gl.shaderSource(shader, source);
      gl.compileShader(shader);
      return shader;
    }

    const vsSource = document.getElementById('vs').text;
    const fsSource = document.getElementById('fs').text;
    const vertexShader = createShader(gl, gl.VERTEX_SHADER, vsSource);
    const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fsSource);

    // 2. Link Program
    const program = gl.createProgram();
    gl.attachShader(program, vertexShader);
    gl.attachShader(program, fragmentShader);
    gl.linkProgram(program);
    gl.useProgram(program);

    // 3. Define Geometry (Square made of two triangles)
    // Coordinates are Clip Space: -1.0 to +1.0
    const vertices = new Float32Array([
      -0.5,  0.5,   // Top Left
      0.5,  0.5,   // Top Right
      -0.5, -0.5,   // Bottom Left
      0.5, -0.5    // Bottom Right
    ]);

    // 4. Create Buffer and Upload Data
    const buffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
    gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

    // 5. Tell GPU how to read the buffer
    const positionLocation = gl.getAttribLocation(program, 'position');
    gl.enableVertexAttribArray(positionLocation);
    gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);

    // 6. Draw
    gl.clearColor(0, 0, 0, 1); // Black background
    gl.clear(gl.COLOR_BUFFER_BIT);
    gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);

And this is the result — an orange square rendered by the GPU:

What a headache.

Three.js makes all of this much easier by providing a high-level, object-oriented API that allows developers to think in terms of scenes, lights, and materials rather than points, lines, and triangles.

With Three.js, the same effect (an orange box, centered in a canvas) can be achieved in less lines of code and a much more human-understandable code structure.

javascript
import * as THREE from 'three';

    // 1. Setup Scene & Camera
    const scene = new THREE.Scene();
    const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
    camera.position.z = 5;

    // 2. Setup Renderer
    const renderer = new THREE.WebGLRenderer({ antialias: true });
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);

    // 3. Create the Box (Geometry + Material = Mesh)
    const geometry = new THREE.BoxGeometry(2, 2, 2);
    const material = new THREE.MeshBasicMaterial({ color: 0xffa500 }); // Orange
    const cube = new THREE.Mesh(geometry, material);
    scene.add(cube);

    // 4. Animation Loop
    function animate() {
      requestAnimationFrame(animate);
      
      // Let's make it spin! (Something very hard in raw WebGL)
      cube.rotation.x += 0.01;
      cube.rotation.y += 0.01;
      
      renderer.render(scene, camera);
    }

    animate();

I think that is worth learning. I bet that you do, too.

←   HomeA modern dev environment   →