Three.js: Interactive 3D Experiences
What is Three.js?
Three.js is a cross-browser JavaScript library and API used to create and display animated 3D computer graphics in a web browser.
It leverages WebGL to render scenes directly within the browser, providing an easy-to-use interface for building complex 3D experiences.
WebGL (Web Graphics Library) is a JavaScript API used for rendering high-performance interactive 3D and 2D graphics within any compatible web browser without the use of plugins.
- Integration with HTML: works with the HTML5 <canvas> element to draw graphics.
- Cross-Platform: runs on any device with a compatible web browser.
- Hardware-Accelerated: utilizes the GPU for high-performance graphics rendering.
- Foundation for Three.js: simplifies the use of WebGL for developers.
Key Features of Three.js
Geometry and Materials
Three.js provides a rich set of geometry primitives and the ability to create custom geometries. It also offers a variety of materials that define how the surfaces of these geometries interact with light. Advanced materials can simulate realistic physical properties like metalness and roughness, enabling the creation of visually complex and interactive 3D objects.
Lights and Shadows
Supports multiple types of lights for the creation of intricate lighting setups. These lights can cast realistic shadows, adding depth and immersion to the scene. The shadow system in Three.js includes various parameters enabling fine-tuning of shadow quality and performance to suit the needs of any 3D application.
Animation
Includes robust animation capabilities that allow developers to create smooth and intricate animations. This can range from simple transformations to complex skeletal animations for character models.
Camera Controls
Offers various camera types each serving different visualization needs. It is also possible to insert camera controls able to provide intuitive ways for users to interact with the scene. These controls enable users to pan, zoom, and rotate the camera around the scene, creating an interactive and immersive experience.
Textures
Textures are essential for adding detail and realism to 3D models. These can be applied to materials to simulate surface details like color, bumpiness, and reflectivity. Three.js also supports advanced texture mapping techniques enhancing the visual complexity of objects.
Loaders
Three.js includes a range of loaders that make it easy to import 3D models and assets from various formats. These loaders handle the intricacies of parsing and interpreting different file types, allowing developers to integrate pre-made models and assets into their scenes seamlessly.
How to build a Three.js scene in Vue 3 — Typescript application
Let's look at the main elements useful for building a Vue 3 and Typescript application that uses the Three.js library to display a 3D scene.
Base scene setup
The first step to create a 3D scene is to initialize the basic elements that will compose it:
- Scene: The scene is the container that holds all the 3D objects, lights, and cameras. It serves as the stage where everything happens.
- Camera: The camera determines what portion of the scene is visible on the screen. The
PerspectiveCamera
is commonly used because it simulates the way the human eye perceives the world, with objects appearing smaller as they get further away. - Renderer: The renderer takes the scene and camera and produces the final image. The
WebGLRenderer
is used for rendering 3D graphics using WebGL.
For our small application example we create a container to which we will append the constructed scene, as follows:
<template>
<div ref="modelContainer" class="model-container"></div>
</template>
import * as THREE from 'three';
// Create the scene
const scene = new THREE.Scene();
// Create the camera
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 5;
// Create the renderer
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
modelContainer.value.appendChild(renderer.domElement);
Add or create models/geometries
After setting up the scene, the next step is to add 3D objects. Three.js provides multiple possibilities for adding 3D elements within the scene, from the ability to add geometric objects to the use of loaders for loading pre-existing 3D models.
Let’s look at an example on how to load a 3D model using the GLTFLoader:
// Load an external model (GLTF)
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
const loader = new GLTFLoader();
loader.load('path/to/model.gltf', (gltf) => {
scene.add(gltf.scene);
});
Set lights and shadows
Lighting is crucial for creating realistic and visually appealing 3D scenes. Three.js offers various types of lights, each serving different purposes:
- Ambient Light: provides a constant light across the entire scene, without casting shadows. It is used to simulate a basic level of light.
- Directional Light: mimics sunlight, providing parallel rays of light and casting shadows. It is ideal for outdoor scenes.
- Point Light: emits light in all directions from a single point, similar to a light bulb.
- Spotlight: emits light in a cone shape and can cast shadows. It is useful for highlighting specific areas.
Here are a couple of examples on how to add lights within an existing scene:
// Add ambient light
const ambientLight = new THREE.AmbientLight(0x404040); // soft white light
scene.add(ambientLight);
// Add a directional light with shadows
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(5, 10, 5);
scene.add(directionalLight);
// it is possible to add and tune shadows adusting some light properites as follow
directionalLight.castShadow = true;
// set the shadow min and max distance
directionalLight.shadow.camera.near = 0.5;
directionalLight.shadow.camera.far = 5000;
//set the shadow resolution/quality
directionalLight.shadow.mapSize.width = 4096;
directionalLight.shadow.mapSize.height = 4096;
It is important to remember that to allow the inserted lights to generate shadows within the scene there are properties to be set in the renderer and on the inserted 3D models:
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
model.traverse((node: unknown) => {
node.castShadow = true; // grant the model the possibility to generate shadows
node.receiveShadow = true; // grant the model the possibility to receive shadows
});
Camera controls
Interactive camera controls enhance the user experience by allowing them to explore the 3D scene. Three.js provides several control classes that can be added to the camera to achieve this:
- OrbitControls: Allows the user to rotate around, zoom, and pan the scene by dragging the mouse or using touch gestures.
- TrackballControls: Provides similar functionality to OrbitControls but with more flexibility in rotation.
- FirstPersonControls: Simulates a first-person perspective, where the camera moves as if it were the user’s eyes.
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
// Create OrbitControls
const controls = new OrbitControls(camera, renderer.domElement);
// Set some controls properties
controls.maxPolarAngle = Math.PI / 2;
// set max and min zoom distance
controls.minDistance = 0.8;
controls.maxDistance = 4;
// set zoom speed
controls.zoomSpeed = 4;
Animations
Animations bring life to your 3D scene. With Three.js, you can animate any property of your objects. The simplest way to create animations is to use the requestAnimationFrame
function to create a loop that updates the scene at regular intervals.
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();
PoC Three.Js
Putting together all the information described, we provide a small example of a scene, available at the following link.
In the example scene we inserted a geometric plane to which we applied a wooden texture to create a floor. Above it we have loaded, thanks to GLTFLoader, two 3D models: a coffee table and a cup of coffee placed on it. A camera rotates around the models thanks to the OrbitControls library.
Finally, we added an ambient light and a spotlight to highlight the table in the center of the scene, while also generating shadows.
Resources
- Github: https://github.com/FrancescoMarz10/PoC-threejs
- CodeSandbox: https://codesandbox.io/p/github/FrancescoMarz10/PoC-threejs
- Texture website: https://polyhaven.com/hdris
- 3D models website: https://sketchfab.com
- Three.js documentation: https://threejs.org/
Conclusion
Three.js is a powerful and versatile library for creating 3D graphics on the web, leveraging WebGL for high-performance rendering. It offers a rich feature set making it an incredibly comprehensive tool for 3D development. Additionally, Three.js benefits from a large community and extensive resources, including detailed documentation which make it easier for developers to learn and get support. These qualities collectively make Three.js an excellent choice for creating immersive and visually appealing 3D applications on the web.