PREREQUISITES

PREREQUISITES


Before you jump into Three.js, you need a strong base.

πŸ‘‰ Three.js is just a tool without JavaScript and web basics, you won’t be able to control it.


1. HTML (Structure of your 3D app)


HTML is the skeleton of your webpage.

In Three.js, HTML is mainly used to:

  • Create a container (like <div> or <canvas>)
  • Load your JavaScript file
  • Add UI elements (buttons, text, etc.)

Example:

<body>
  <canvas id="webgl"></canvas>
</body>

πŸ‘‰ Three.js renders everything inside this <canvas>.


2. CSS (Styling your 3D scene container)


CSS controls how your page looks and behaves.

In Three.js projects, CSS helps you:

  • Make canvas fullscreen
  • Position UI elements over 3D (like buttons, menus)
  • Handle responsiveness

Example:

body {
  margin: 0;
  overflow: hidden;
}
canvas {
  display: block;
}

πŸ‘‰ Without CSS, your 3D scene may look broken or misaligned.


3. JavaScript (CORE β€” Most Important)


πŸ‘‰ This is the heart of Three.js.

Since Three.js is a JavaScript library, you MUST understand JS basics.

Key Concepts You Need:

βœ… Variables

Store data

let speed = 5;

const

Cannot reassign.

const age = 20;



βœ… Arrays

Store multiple values

let colors = ["red", "blue", "green"];

βœ… Objects

Store structured data (VERY important for 3D)

let cube = {
  width: 1,
  height: 1,
  depth: 1
};

βœ… Functions

Reusable logic

function rotate() {
  console.log("rotating...");
}

βœ… Events

React to user actions

window.addEventListener("click", () => {
  console.log("Clicked!");
});

βœ… DOM (Document Object Model)

Interact with HTML

const canvas = document.getElementById("webgl");

πŸ‘‰ Three.js uses ALL of these heavily.


 4. Basic Math


Unit-5: 3 D Co-ordinate Geometry – B.C.A study


Coordinates (Positioning in 3D)

  • X β†’ left/right
  • Y β†’ up/down
  • Z β†’ forward/back

πŸ‘‰ Example:

mesh.position.set(1, 2, 3);

πŸ“ Vectors

Used to represent:

  • Position
  • Direction
  • Movement

πŸ‘‰ Example:

let direction = { x: 1, y: 0, z: 0 };

πŸ”„ Angles & Rotation

Used to rotate objects

πŸ‘‰ Example:

mesh.rotation.y = Math.PI; // 180Β°



SETUP & INSTALLATION

Every three.js project needs at least one HTML file to define the webpage, and a JavaScript file to run your three.js code.


Before coding, need to add Three.js to project.

There are two main ways:


  • CDN (quick & beginner-friendly)
  • NPM (professional & scalable)


Install with CDN

CDN METHOD

πŸ‘‰ Best for:

  • Beginners
  • Quick demos
  • Learning concepts
  • No setup needed


What is CDN?

A CDN (Content Delivery Network) is just a hosted file online.

You directly link Three.js into your HTML.

πŸ‘‰ No installation. No terminal. Just plug and play.


 Setup Steps


Step 1: Create basic project

project/
 β”œβ”€β”€ index.html
 └── script.js


Step 2: Add Three.js CDN

<!DOCTYPE html>
<html lang="en">
<head>
  <title>Three.js CDN</title>
  <style>
    body { margin: 0; }
  </style>
</head>
<body>

<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r152/three.min.js"></script>
<script src="script.js"></script>

</body>
</html>


Pros of CDN

  • No setup required
  • Works instantly
  • Great for testing ideas
  • Beginner-friendly


Cons of CDN

  • Not scalable for big projects
  • Hard to manage dependencies
  • No modular imports
  • Not ideal for production



Install with NPM

NPM METHOD


Best for:

  • Real projects
  • React / Next.js
  • Large applications
  • Clean & modular code


 What is NPM?

NPM = Node Package Manager

It installs libraries locally in your project.


 Setup Steps


Step 1: Install Node.js

Download from: https://nodejs.org

Check installation:

node -v
npm -v


Step 2: Create project

mkdir three-project
cd three-project
npm init -y


Step 3: Install Three.js

npm install three

 

Step 4: Install a bundler (VERY IMPORTANT)

Three.js (NPM) needs a bundler like:

  • Vite

πŸ‘‰ Use Vite (simple and fast)

npm create vite@latest

Then:

cd your-project
npm install
npm run dev


Step 5: Import Three.js

import * as THREE from 'three';


Pros of NPM

  • Clean modular code
  • Easy to scale
  • Works with React / Next.js
  • Better performance control
  • Industry standard


Cons of NPM

  • Setup required
  • Needs Node.js knowledge
  • Slightly complex for beginners


CORE FOUNDATION

 Every Three.js app is built on three core components:

  • Scene β†’ where everything exists
  • Camera β†’ how you view the scene
  • Renderer β†’ how it gets displayed on screen


import * as THREE from 'three';

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );

const renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );


1️⃣ Import Three.js

import * as THREE from 'three';

πŸ‘‰ You are importing the Three.js library so you can use it.


2️⃣ Create Scene

const scene = new THREE.Scene();

πŸ‘‰ Think of scene = empty stage

  • This is where you will add:
  • objects (cube, sphere)
  • lights
  • models

3️⃣ Create Camera

const camera = new THREE.PerspectiveCamera(
  75,
  window.innerWidth / window.innerHeight,
  0.1,
  1000
);

πŸ‘‰ Think of camera = your eyes

This camera decides what part of the scene you see

Parameters:

  • 75 β†’ Field of View (how wide you see)
  • window.innerWidth / window.innerHeight β†’ screen ratio
  • 0.1 β†’ near (closest visible distance)
  • 1000 β†’ far (farthest visible distance)

πŸ’‘ Simple meaning:

"Show everything between 0.1 and 1000 units from camera"


4️⃣ Create Renderer

const renderer = new THREE.WebGLRenderer();

πŸ‘‰ Think of renderer = painter

  • It takes your scene + camera
  • Draws it using WebGL (GPU)


5️⃣ Set Size

renderer.setSize(window.innerWidth, window.innerHeight);

πŸ‘‰ This makes the canvas fill the screen


6️⃣ Add to HTML

document.body.appendChild(renderer.domElement);

πŸ‘‰ This adds the 3D canvas into your webpage

  • renderer.domElement = actual <canvas> element


Add this at the end:

renderer.render(scene, camera);



GLB

What is GLB?

  • .gltf β†’ JSON + separate textures/files
  • .glb β†’ Everything packed into one file

Most websites use GLB because it's easier and loads faster.


 Load GLB Model

Import Loader

import { GLTFLoader } from
'three/examples/jsm/loaders/GLTFLoader.js';


Load Model

const loader = new GLTFLoader();

loader.load(
  '/models/shoe.glb',

  function(gltf) {

    const model = gltf.scene;

    model.scale.set(1,1,1);

    model.position.set(0,0,0);

    scene.add(model);

  },

  function(xhr) {

    console.log(
      (xhr.loaded / xhr.total * 100)
      + '% loaded'
    );

  },

  function(error) {

    console.log(error);

  }
);


 DRACO Loader

Without Draco:

shoe.glb = 20 MB

With Draco:

shoe.glb = 2-5 MB

Huge performance improvement.


Import

import { DRACOLoader }
from 'three/examples/jsm/loaders/DRACOLoader.js';


KTX2 Texture Compression

Professional websites use:

GLB + Draco + KTX2

Benefits:

  • Faster loading
  • Less GPU memory
  • Mobile optimization

Import:

import { KTX2Loader }
from 'three/examples/jsm/loaders/KTX2Loader.js';

Used for compressed textures.


Step 1: Create the Sandal in Blender

You make 3 separate objects:

Sandal
β”œβ”€β”€ Sole
β”œβ”€β”€ Top
β”œβ”€β”€ Buckle

In Blender Outliner:

Collection
 β”œβ”€β”€ Sole
 β”œβ”€β”€ Top
 β”œβ”€β”€ Buckle

⚠️ Don't join them (Ctrl + J).

Keep them as separate meshes.


Step 2: Export as GLB

File
β†’ Export
β†’ glTF 2.0
β†’ Format: GLB

Export:

sandal.glb

Inside that single GLB:

Sole Mesh
Top Mesh
Buckle Mesh

are all stored separately.


Step 3: Load in Three.js

const loader = new GLTFLoader();

loader.load('/models/sandal.glb', (gltf) => {

    const sandal = gltf.scene;

    scene.add(sandal);

});

At this point:

Sole
Top
Buckle

appear together as one sandal.


Step 4: Access Individual Parts

Because they are separate objects in Blender:

loader.load('/models/sandal.glb', (gltf) => {

    const sandal = gltf.scene;

    const sole =
    sandal.getObjectByName("Sole");

    const top =
    sandal.getObjectByName("Top");

    const buckle =
    sandal.getObjectByName("Buckle");

    scene.add(sandal);

});

Now Three.js can control each part independently.


let sole;
let top;
let buckle;

loader.load('/models/sandal.glb', (gltf) => {

  const sandal = gltf.scene;

  sole = sandal.getObjectByName("Sole");
  top = sandal.getObjectByName("Top");
  buckle = sandal.getObjectByName("Buckle");

  scene.add(sandal);

});

Animate in the Render Loop

Rotate Only the Buckle

function animate() {

    requestAnimationFrame(animate);

    if(buckle){
        buckle.rotation.y += 0.02;
    }

    renderer.render(scene, camera);

}

animate();

Only the buckle rotates.


Using GSAP

Most product websites use GSAP.

<script src="https://cdn.jsdelivr.net/npm/gsap@3"></script>

Animate Buckle

gsap.to(buckle.rotation,{
    y:Math.PI * 2,
    duration:2,
    repeat:-1,
    ease:"none"
});


Environment & Realism

 make 3D scenes look realistic using:

  • HDRI
  • Environment Maps
  • HDR Lighting
  • Sky & Skybox
  • Cube Maps
  • Reflections
  • Reflection Mapping
  • Realistic Materials
  • PBR Workflow

Without these, models look like plastic toys.

With these, models look like real products.

HDRI (High Dynamic Range Image)

Definition

An HDRI is a 360Β° image containing lighting and color information from a real-world environment.

Unlike JPG or PNG images, HDRI stores:

  • Bright sunlight
  • Dark shadows
  • Light intensity
  • Reflection information


Why Use HDRI?

HDRI helps objects understand:

  • Where light comes from
  • How bright the scene is
  • What should be reflected


Real-Life Example

Imagine holding a shiny spoon.

The spoon reflects:

  • Ceiling
  • Fan
  • Windows
  • Lights

A 3D object needs the same environmental information.

HDRI provides it.


Benefits

  • Realistic lighting
  • Better reflections
  • Professional product renders
  • Natural shadows


Import:

import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader.js';


Example

const loader = new RGBELoader();

loader.load('studio.hdr', (texture) => {

    texture.mapping =
    THREE.EquirectangularReflectionMapping;

    scene.environment = texture;
});



Environment Maps

Definition

An Environment Map tells objects what exists around them.

It acts as the surrounding world for:

  • Reflections
  • Lighting
  • Realism

Example

scene.environment = hdrTexture;

What Happens?

Before:

Object floating in empty space

After:

Object surrounded by a real environment

Real-Life Example

Sunglasses reflect:

  • Buildings
  • Cars
  • Trees

Environment maps allow 3D objects to do the same.



HDR Lighting


Definition

Using HDRI as a light source instead of relying only on traditional lights.


Traditional Lighting

const light =
new THREE.DirectionalLight();

Only one light source.


HDR Lighting

scene.environment = hdrTexture;

Thousands of lighting values are used from the HDR image.

Sky & Environment

Definition

The sky creates a believable outdoor environment.

Without a sky:

Black empty background

With a sky:

Realistic outdoor scene

Three.js Sky

import { Sky } from
'three/examples/jsm/objects/Sky.js';

const sky = new Sky();

scene.add(sky);

Important Properties

Turbidity

Controls atmospheric haze.

sky.material.uniforms.turbidity.value = 10;

Higher Value:

More foggy

Lower Value:

Clear sky

Rayleigh

Controls sky brightness.

sky.material.uniforms.rayleigh.value = 3;

Mie Coefficient

Controls sun glow.

sky.material.uniforms.mieCoefficient.value = 0.005;

Use Cases

  • Day scenes
  • Sunset scenes
  • Open-world environments 

Reflection Mapping

Reflection Mapping

Definition

Reflection Mapping is the process of using environment data to generate reflections.

Workflow

Environment
      ↓
Reflection Map
      ↓
Material
      ↓
Reflection

Example

scene.environment =
hdrTexture;

const material =
new THREE.MeshPhysicalMaterial({

    metalness: 1,

    roughness: 0
});

Result

The object reflects the HDR environment.

Performance Optimization

Performance Optimization is the process of making your Three.js application run smoothly while using fewer resources.

Objectives

  • Maintain 60 FPS (Frames Per Second)
  • Reduce CPU Usage
  • Reduce GPU Usage
  • Faster Loading Time
  • Better Mobile Performance
  • Lower Memory Consumption

Why It Matters

A scene may look amazing on your computer, but if it lags on users' devices, it is a poor user experience.


Common Areas of Optimization

  • Geometry Optimization
  • Texture Optimization
  • Model Optimization
  • Rendering Optimization
  • Draw Call Reduction
  • Memory Optimization


Geometry Optimization

What is Geometry?

Geometry defines the shape of a 3D object.

It consists of:

  • Vertices (Points)
  • Edges (Lines)
  • Faces/Triangles


The GPU must process every vertex.

More vertices = More calculations = Lower FPS


Best Practices

βœ“ Reduce unnecessary vertices

βœ“ Reuse geometries


Real Example

const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshStandardMaterial({
    color: "orange"
});

for(let i = 0; i < 100; i++){

    const cube = new THREE.Mesh(
        geometry,
        material
    );

    cube.position.x = i * 2;

    scene.add(cube);
}

Result:

  • 100 visible cubes
  • 1 geometry
  • 1 material
  • Much faster


Texture Optimization

Textures are often the biggest performance killer.


Compress Textures

Use:

KTX2
Basis
WebP
AVIF

instead of giant PNGs.

Huge performance gain.

Model Optimization

Optimization Methods


Decimation

Reduce polygon count using Blender.


Draco Compression

Compress geometry data.


glTF Optimization

Export models as:

.glb


Why .glb?

Contains:

  • Geometry
  • Materials
  • Textures
  • Animations

All in one optimized file.


Best Practices

βœ“ Use .glb

βœ“ Compress with Draco

βœ“ Reduce polygon count

βœ“ Remove hidden geometry

Rendering Optimization

Rendering is the process of drawing the scene every frame.

Expensive Rendering Features

Shadows

Very expensive.

Bad:

10 shadow lights

Good:

1 shadow light

Shadow Map Resolution

Bad:

light.shadow.mapSize.set(
    4096,
    4096
);

Good:

light.shadow.mapSize.set(
    1024,
    1024
);

Pixel Ratio Optimization

Bad:

renderer.setPixelRatio(
    window.devicePixelRatio
);

Some phones:

devicePixelRatio = 4

Heavy GPU load.

Good:

renderer.setPixelRatio(
    Math.min(
        window.devicePixelRatio,
        2
    )
);

Professional approach.


Best Practices

βœ“ Reduce shadows

βœ“ Lower shadow resolution

βœ“ Limit pixel ratio

βœ“ Disable unused effects

Frustum Culling

What is Frustum Culling?

Three.js automatically skips rendering objects outside the camera view.

Example

Scene contains:

1000 Trees

Camera sees:

100 Trees

Only 100 trees are rendered.

The other 900 are ignored.

Why It Helps

Reduces:

  • Draw Calls
  • GPU Work
  • CPU Work

Disable Only When Necessary

mesh.frustumCulled = false;

Usually keep it enabled.

InstancedMesh

What Problem Does It Solve?

Suppose you create:

1000 Trees

Normally:

1000 Meshes
1000 Draw Calls

Very expensive.


What is a Draw Call?

A command sent to the GPU:

"Draw this object."

More draw calls = lower performance.


InstancedMesh

Allows rendering thousands of identical objects using a single draw call.

Example

const trees =
new THREE.InstancedMesh(
    geometry,
    material,
    1000
);

Result:

1000 Trees
1 Draw Call

Massive performance improvement.


Common Uses

Grass

5000 Blades

Trees

10000 Trees

Rocks

3000 Rocks

Buildings

1000 Buildings


Best Practices

βœ“ Use when geometry and material are identical

βœ“ Perfect for repeated objects

βœ“ Essential for large environments

TOOLS

1. Chrome DevTools

What is it?

A built-in browser tool used to analyze and debug performance issues in your Three.js application.

Why use it?

  • Check FPS drops
  • Detect memory leaks
  • Analyze CPU/GPU usage
  • Measure loading times

Open DevTools

F12

or

Right Click β†’ Inspect

Implementation

// Open DevTools
F12

// Go to:
Performance Tab

// Click:
Record

// Interact with scene

// Stop Recording

Chrome will show:

Rendering Time
JavaScript Time
Memory Usage
FPS



2. Stats.js

What is it?

A lightweight FPS monitor that displays real-time performance information.

Why use it?

  • Monitor FPS
  • Monitor frame time
  • Monitor memory usage

Installation

<script src="https://cdnjs.cloudflare.com/ajax/libs/stats.js/r17/Stats.min.js"></script>

Implementation

const stats = new Stats();

document.body.appendChild(stats.dom);

function animate() {

    stats.begin();

    renderer.render(scene, camera);

    stats.end();

    requestAnimationFrame(animate);
}

animate();

Output

FPS : 60
MS  : 16
MB  : 80


Particles

Imagine you want to create a sky full of stars.


Wrong Way

Create 10,000 small spheres.

const star = new THREE.Mesh(
    new THREE.SphereGeometry(),
    material
);

Problem:

  • 10,000 Meshes
  • Very heavy
  • Slow website


Right Way

Create 10,000 dots (particles).

const particles = new THREE.Points(
    geometry,
    material
);

Three.js treats them as one object.

Result:

  • Fast
  • Less memory
  • Can create thousands of particles easily

How Does Three.js Know Where To Place Particles?

Every particle needs:

X position
Y position
Z position

Example:

Particle 1 = (1,2,3)
Particle 2 = (4,1,0)
Particle 3 = (-2,5,1)

These positions are stored inside a BufferGeometry.


BufferGeometry

Think of BufferGeometry as a big container that stores all particle positions.

const geometry =
new THREE.BufferGeometry();

Float32Array

Stores coordinates.

const positions =
new Float32Array(count * 3);

Why * 3?

Because every particle needs:

x
y
z

Example:

[
 1,2,3,
 4,5,6,
 7,8,9
]

Means:

Particle 1 β†’ x=1 y=2 z=3
Particle 2 β†’ x=4 y=5 z=6
Particle 3 β†’ x=7 y=8 z=9

Creating Random Particles

for(let i=0;i<count*3;i++){
    positions[i] =
    (Math.random()-0.5)*10;
}

This gives random positions.


PointsMaterial

Particles need a material just like meshes.

const material =
new THREE.PointsMaterial();

Particle Size

size:0.1


const material =
new THREE.PointsMaterial({
    size:0.1
});

Makes particles bigger.


Particle Color

color:"white"


const material =
new THREE.PointsMaterial({
    color:"yellow"
});

All particles become yellow.

Creating The Particle System

const particles =
new THREE.Points(
    geometry,
    material
);

scene.add(particles);

Now particles appear in the scene.