Aller au contenu principal

2. [Three.js] Fundamentals

· 5 minutes de lecture
Sangmin SHIM
Fullstack Developer

1. Digest

Building a solid foundation in Three.js starts with understanding the core components that make 3D web graphics possible. The fundamentals covered here include setting up the essential rendering pipeline with WebGLRenderer, Scene, and Camera objects, along with creating and manipulating 3D meshes. You'll learn how to handle responsive design by adapting your 3D scenes to browser window resizing, optimizing rendering quality with pixel ratio settings, and managing background colors and transparency.

Animation brings static 3D scenes to life, and you'll explore multiple approaches to achieve smooth, frame-rate-independent animations. From basic rotation and movement using requestAnimationFrame to implementing time-based animations with THREE.Clock, you'll understand how to create consistent motion across different devices. The chapter also introduces advanced animation techniques using GSAP (GreenSock Animation Platform) for complex, eased animations with features like yoyo effects and infinite repeats.

Visual depth and realism are enhanced through lighting and atmospheric effects. You'll work with DirectionalLight to illuminate your 3D objects and implement fog effects to create depth perception. The chapter demonstrates practical patterns like creating multiple objects using functional array methods (Array.from with map), managing collections of meshes, and applying transformations to create dynamic, multi-object scenes.

2. What is the purpose

The purpose of this module is to equip developers with essential Three.js skills needed for building interactive 3D web applications. You'll gain hands-on experience with the fundamental rendering loop, understand camera types (PerspectiveCamera vs OrthographicCamera), and master the relationship between geometry, materials, and meshes.

By the end of this module, you'll be able to create responsive 3D scenes that adapt to different screen sizes and pixel densities, implement smooth animations using various timing techniques, and enhance visual quality with lighting and atmospheric effects. These skills form the foundation for more advanced Three.js development, including interactive controls, complex geometries, and realistic rendering.

The practical applications include creating animated product showcases, interactive 3D visualizations, educational demonstrations, and engaging web experiences that respond dynamically to user interactions and viewport changes.

3. Some code block and its explanation

Example 1: Responsive Rendering with Pixel Ratio Optimization

const canvas = document.querySelector("#three-canvas");
const renderer = new THREE.WebGLRenderer({ canvas, antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio > 1 ? 2 : 1);

function setSize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.render(scene, camera);
}

window.addEventListener("resize", setSize);

This code establishes a responsive 3D rendering setup that adapts to browser window changes. The setPixelRatio method caps the pixel ratio at 2 for high-DPI displays, balancing visual quality with performance—preventing unnecessary rendering overhead on ultra-high-resolution screens. The resize event handler updates the camera's aspect ratio and projection matrix, ensuring the 3D scene maintains correct proportions when the window is resized. This pattern is essential for creating professional Three.js applications that work seamlessly across different devices and screen sizes.

Example 2: Frame-Rate-Independent Animation with THREE.Clock

const clock = new THREE.Clock();

function draw() {
const delta = clock.getDelta();

mesh.rotation.y += delta;
mesh.position.y += delta;

if(mesh.position.y > 2) mesh.position.y = 0;

renderer.render(scene, camera);
window.requestAnimationFrame(draw);
}

draw();

Using THREE.Clock.getDelta() ensures smooth, consistent animations regardless of frame rate variations. The delta value represents the time elapsed since the last frame in seconds, making animation speed independent of the device's refresh rate. This approach is superior to fixed increments because it maintains the same visual speed on both 60Hz and 120Hz displays. The pattern shown here—rotating and translating objects based on delta time—is a fundamental technique for creating professional-quality animations in Three.js.

Example 3: Creating Multiple Objects with Functional Patterns

const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshStandardMaterial({ color: "#ff0000" });

const meshes = Array.from({length: 10}).map(() => {
const mesh = new THREE.Mesh(geometry, material);
mesh.position.x = Math.random() * 5 - 2.5;
mesh.position.y = Math.random() * 5 - 2.5;
scene.add(mesh);
return mesh;
});

meshes.forEach((mesh) => {
mesh.rotation.y += deltaTime * 0.001;
mesh.position.y += deltaTime * 0.001;
if(mesh.position.y > 5) mesh.position.y = -5;
});

This demonstrates a modern JavaScript approach to creating and managing multiple 3D objects. Using Array.from with map creates 10 box meshes with randomized positions in a single, readable expression. Storing references in the meshes array enables efficient batch operations during animation, where forEach applies transformations to all objects simultaneously. This pattern is particularly useful for particle systems, object pools, or any scenario requiring management of multiple similar objects. The random positioning creates visual variety while keeping the code concise and maintainable.

Example 4: Advanced Animation with GSAP Integration

import gsap from "gsap";

const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);

gsap.to(mesh.position, {
duration: 1,
y: 2,
z: 1,
ease: "power3.inOut",
repeat: -1,
yoyo: true
});

function draw() {
renderer.render(scene, camera);
window.requestAnimationFrame(draw);
}
draw();

GSAP (GreenSock Animation Platform) provides powerful, professional-grade animation capabilities that complement Three.js. This code animates the mesh's position smoothly with easing functions (power3.inOut), creating natural-looking motion with acceleration and deceleration. The repeat: -1 creates an infinite loop, while yoyo: true makes the animation reverse direction, creating a ping-pong effect. GSAP handles all the interpolation and timing internally, so the render loop only needs to call renderer.render(). This separation of concerns—GSAP for animation logic, Three.js for rendering—results in cleaner code and more sophisticated animations than manual implementations.