Creating Stunning 3D Visualizations with Three.js: A Beginner’s Guide

ASHABB ReactJS & ThreeJS
12 min readJun 14, 2023

--

Photo by Braden Collum on Unsplash
  1. `<title>three.js — Boilerplate</title>`: This line sets the title of the HTML page to “three.js — Boilerplate”. The title is displayed on the browser tab.

2. `<meta charset=”utf-8">`: This meta tag specifies the character encoding for the HTML document. UTF-8 is a widely used character encoding that supports a wide range of characters.

3. `<meta name=”viewport” content=”width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">`: This meta tag defines the viewport settings for the webpage. It ensures that the width of the viewport matches the device width, disables user scaling, and sets the minimum and maximum scale factors to 1.0.

4. `<script async src=”https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script>`: This line imports the ES Module Shims library from the specified URL. The ES Module Shims library enables the usage of ES modules in older browsers that do not support them natively.

code snippet :

<head>
<title>three.js - Boilerplate</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script>

<style>
body {
background-color: grey
}

html,
body {
margin: 0;
height: 100%;
}

#canvas {
width: 100%;
height: 100%;
display: block;
color: rgb(40, 63, 141);
}
</style>

</head>

5. The following block of CSS styles the appearance of the HTML and body elements:

- The background color of the body is set to grey.

- The margin of the html and body elements is set to 0 to remove any default spacing.

- The height of the html and body elements is set to 100% to take up the full height of the viewport.

- The canvas element with an id of “canvas” is styled to occupy the full width and height of its container, and its text color is set to rgb(40, 63, 141).

6. `<body>`: The start of the HTML body.

7. `<canvas id=”canvas”></canvas>`: This creates a canvas element with an id of “canvas”. The canvas is a container used for rendering the Three.js 3D graphics.

8. The following script tag contains the JavaScript code that initializes and renders the Three.js scene:

- The script starts with a `type=”module”` attribute, indicating that it uses ES modules.

- The script imports various modules using the `import` statement, including Three.js, OrbitControls, DAT.GUI, and Stats.

- The script initializes variables for the canvas, renderer, scene, camera, controls, and stats.

- Inside the `init()` function, the code sets up the canvas, renderer, scene, camera, controls, and adds objects to the scene.

- The `animate()` function is called recursively using `requestAnimationFrame()` to continuously render the scene and update the controls.

- The `init()` function is called to initialize the scene, and then the `animate()` function is called to start the rendering loop.

9. `</body>`: The end of the HTML body.

<canvas id="canvas"></canvas>
<script type="importmap">
{
"imports": {
"three": "../threeJS/build/three.module.js"
}
}
</script>
<script type="module">
import * as THREE from 'three';
import { OrbitControls } from '../threeJS/examples/jsm/controls/OrbitControls.js';
import * as DAT from '../threeJS/newadded/DatGUI.js';
import { Stats } from "../threeJS/newadded/Stats.js";
</script>

1. `<canvas id=”canvas”></canvas>`: This line creates a canvas element with the id “canvas”. It is the container where the Three.js scene will be rendered.

2. `<script type=”importmap”>`: This script tag introduces the import map syntax. Import maps allow you to define mappings between module specifiers and URLs. In this case, the import map is used to define the import of the Three.js library.

3. The content of the `<script type=”importmap”>` tag:

   {
"imports": {
"three": "../threeJS/build/three.module.js"
}
}

This import map specifies that when the code imports the module “three”, it should resolve to the “../threeJS/build/three.module.js” URL. It provides a convenient way to alias module imports to specific file paths.

4. `<script type=”module”>`: This script tag indicates that the enclosed JavaScript code should be treated as a module. Modules are separate JavaScript files that can import and export functionality. The “type” attribute set to “module” enables the use of ES modules.

5. The JavaScript code within the `<script type=”module”>` tag:

- The code imports various modules using the `import` statement:

- `import * as THREE from ‘three’;` imports the entire Three.js library and assigns it to the variable `THREE`.

- `import { OrbitControls } from ‘../threeJS/examples/jsm/controls/OrbitControls.js’;` imports the OrbitControls module from a specific file path.

- `import * as DAT from ‘../threeJS/newadded/DatGUI.js’;` imports the DAT module from a specific file path.

- `import { Stats } from “../threeJS/newadded/Stats.js”;` imports the Stats module from a specific file path.

- These imports bring in additional functionalities and libraries used in the Three.js scene.

In summary, this section of the code sets up the import map to specify the location of the Three.js library and imports various modules needed for the Three.js scene, including Three.js itself, OrbitControls, DAT.GUI, and Stats. These modules provide additional features and controls to enhance the functionality and interactivity of the 3D scene.

//---gui---//
var gui;
gui = new DAT.GUI();
var lightGui = false;
var statsGui = true;
gui.close();

1. `// — -gui — -//`: This comment indicates the start of the section related to the GUI (Graphical User Interface).

2. `var gui;`: This line declares a variable named `gui` without assigning any value to it.

3. `gui = new DAT.GUI();`: This line creates a new instance of the `DAT.GUI` object and assigns it to the `gui` variable. `DAT.GUI` is a library that provides an interface for creating interactive GUI controls.

4. `var lightGui = false;`: This line declares a variable named `lightGui` and assigns it the value `false`. This variable is likely used to control the visibility or behavior of GUI controls related to lights in the scene.

5. `var statsGui = true;`: This line declares a variable named `statsGui` and assigns it the value `true`. This variable is likely used to control the visibility or behavior of GUI controls related to statistics display in the scene.

6. `gui.close();`: This line calls the `close()` method on the `gui` object. This method is used to close or collapse the GUI, making it initially hidden or collapsed.

Moving on to the next part:

var canvas, renderer, scene, camera, controls, stats;

1. `var canvas, renderer, scene, camera, controls, stats;`: This line declares multiple variables using comma separation without assigning any initial values to them. These variables are likely placeholders for the different components and objects related to the Three.js scene, including the canvas element, renderer, scene, camera, controls (such as OrbitControls), and stats (such as performance statistics).

Overall, this section sets up the GUI (DAT.GUI) and declares variables for different Three.js components that will be used later in the code.

canvas = document.getElementById('canvas');

renderer = new THREE.WebGLRenderer({ canvas });
renderer.setSize(window.innerWidth, window.innerHeight);
stats = Stats();
statsGui && document.body.appendChild(stats.dom);

scene = new THREE.Scene();
scene.background = new THREE.Color('black');
scene.fog = new THREE.Fog(0xffffff, 0, 750);

const axesHelper = new THREE.AxesHelper(500);
scene.add(axesHelper);

const ambientLight = new

1. `canvas = document.getElementById(‘canvas’);`: This line retrieves the HTML element with the ID “canvas” using `document.getElementById()` and assigns it to the `canvas` variable. This element represents the canvas where the Three.js scene will be rendered.

2. `renderer = new THREE.WebGLRenderer({ canvas });`: This line creates a new instance of the `THREE.WebGLRenderer` object and assigns it to the `renderer` variable. The renderer is responsible for rendering the Three.js scene using WebGL. The `canvas` option is passed to the constructor, linking the renderer to the specified canvas element.

3. `renderer.setSize(window.innerWidth, window.innerHeight);`: This line sets the size of the renderer to match the width and height of the window. It ensures that the rendered scene occupies the entire window space.

4. `stats = Stats();`: This line creates a new instance of the `Stats` object, which provides performance statistics for the rendered scene, such as frames per second (FPS). The `Stats` object is assigned to the `stats` variable.

5. `statsGui && document.body.appendChild(stats.dom);`: This line conditionally appends the `stats.dom` element (the DOM element associated with the `Stats` object) to the body of the document if `statsGui` evaluates to `true`. This allows displaying the performance statistics on the webpage.

6. `scene = new THREE.Scene();`: This line creates a new instance of the `THREE.Scene` object and assigns it to the `scene` variable. The scene serves as a container for all the objects, lights, and cameras in the Three.js scene.

7. `scene.background = new THREE.Color(‘black’);`: This line sets the background color of the scene to black using a `THREE.Color` object.

8. `scene.fog = new THREE.Fog(0xffffff, 0, 750);`: This line adds fog to the scene using a `THREE.Fog` object. The parameters passed are the fog color (white) specified as a hexadecimal value, the near distance (0), and the far distance (750).

9. `const axesHelper = new THREE.AxesHelper(500);`: This line creates an `AxesHelper` object, which provides visual reference axes in the scene. The parameter passed (500) specifies the size of the axes.

10. `scene.add(axesHelper);`: This line adds the `axesHelper` object to the scene, making it visible.

11. `const ambientLight = new THREE.AmbientLight(0xffffff, 0.7);`: This line creates a new instance of the `THREE.AmbientLight` object, representing ambient light in the scene. The parameters passed are the light color (white) specified as a hexadecimal value and the light intensity (0.7).

12. `scene.add(ambientLight);`: This line adds the `ambientLight` object to the scene, making it affect all objects in the scene uniformly.

In summary, this section of the code sets up the canvas, renderer, scene, performance statistics,

camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.y = 100;
camera.position.z = 250;

controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.6;
controls.screenSpacePanning = false;
controls.maxPolarAngle = Math.PI / 2.02;
controls.minDistance = 10;
controls.maxDistance = 1000;
controls.update();

1. `camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 1000);`: This line creates a new instance of the `THREE.PerspectiveCamera` object and assigns it to the `camera` variable. The `PerspectiveCamera` represents a perspective projection camera, which mimics the human eye’s perspective. The parameters passed are the field of view (75 degrees), aspect ratio (derived from the window’s width and height), near clipping plane (1 unit), and far clipping plane (1000 units).

2. `camera.position.y = 100;`: This line sets the `y` position of the camera to 100. It positions the camera vertically above the scene.

3. `camera.position.z = 250;`: This line sets the `z` position of the camera to 250. It positions the camera along the positive `z` axis, away from the scene.

4. `controls = new OrbitControls(camera, renderer.domElement);`: This line creates a new instance of the `OrbitControls` object and assigns it to the `controls` variable. `OrbitControls` is a control system that allows users to orbit around and pan the scene with the mouse or touch gestures. It takes the `camera` and the renderer’s DOM element as parameters.

5. `controls.enableDamping = true;`: This line enables damping for the controls. Damping adds inertia to the controls’ movement, resulting in smoother interactions.

6. `controls.dampingFactor = 0.6;`: This line sets the damping factor of the controls to 0.6. The damping factor determines the rate at which damping is applied.

7. `controls.screenSpacePanning = false;`: This line disables screen space panning. When disabled, panning is performed in the plane perpendicular to the camera’s view direction.

8. `controls.maxPolarAngle = Math.PI / 2.02;`: This line sets the maximum polar angle of the controls. It limits the vertical rotation of the camera, preventing it from rotating beyond a certain angle.

9. `controls.minDistance = 10;`: This line sets the minimum distance from the camera to the center of the scene. It prevents the camera from getting too close to the scene.

10. `controls.maxDistance = 1000;`: This line sets the maximum distance from the camera to the center of the scene. It prevents the camera from moving too far away from the scene.

11. `controls.update();`: This line updates the controls. It ensures that any changes made to the controls (such as position or rotation) take effect.

In summary, this section sets up the camera for the scene using a perspective projection, creates and configures the OrbitControls for user interaction, and positions the camera and controls in the scene.

const floorGeometry = new THREE.PlaneGeometry(500, 500);
const floorMaterial = new THREE.MeshStandardMaterial({
color: '#777777',
metalness: 0.2,
roughness: 0.4,
envMapIntensity: 0.5,
side: THREE.DoubleSide
});
const floor = new THREE.Mesh(floorGeometry, floorMaterial);
floor.receiveShadow = true;
floor.rotation.x = -Math.PI * 0.5;
floor.position.set(0, 0, 0);
scene.add(floor);

const m1Geometry = new THREE.BoxGeometry(50, 100, 50);
const m1Material = new THREE.MeshBasicMaterial({
color: '#ff0',
});
const m2 = new THREE.Mesh(m1Geometry, m1Material);
m2.position.set(0, 0, 0);
scene.add(m2);

1. `const floorGeometry = new THREE.PlaneGeometry(500, 500);`: This line creates a plane geometry with dimensions of 500 units by 500 units. It will be used to create the floor object.

2. `const floorMaterial = new THREE.MeshStandardMaterial({ … });`: This line creates a mesh standard material for the floor. The material properties are defined, including the color, metalness, roughness, environment map intensity, and side of the material.

3. `const floor = new THREE.Mesh(floorGeometry, floorMaterial);`: This line creates a mesh object called `floor` using the `floorGeometry` and `floorMaterial`. It represents the floor in the scene.

4. `floor.receiveShadow = true;`: This line enables the floor to receive shadows cast by other objects in the scene.

5. `floor.rotation.x = -Math.PI * 0.5;`: This line sets the rotation of the floor around the x-axis to -90 degrees (in radians). It rotates the floor to be aligned horizontally.

6. `floor.position.set(0, 0, 0);`: This line sets the position of the floor at coordinates (0, 0, 0), which is the center of the scene.

7. `scene.add(floor);`: This line adds the `floor` object to the scene.

8. `const m1Geometry = new THREE.BoxGeometry(50, 100, 50);`: This line creates a box geometry with dimensions of 50 units by 100 units by 50 units. It will be used to create the `m2` object.

9. `const m1Material = new THREE.MeshBasicMaterial({ color: ‘#ff0’ });`: This line creates a basic mesh material with a yellow color for the `m2` object.

10. `const m2 = new THREE.Mesh(m1Geometry, m1Material);`: This line creates a mesh object called `m2` using the `m1Geometry` and `m1Material`. It represents a box in the scene.

11. `m2.position.set(0, 0, 0);`: This line sets the position of `m2` at coordinates (0, 0, 0), which is the center of the scene.

12. `scene.add(m2);`: This line adds the `m2` object to the scene.

In summary, this section creates a floor object using a plane geometry and a mesh standard material. It also creates a box object using a box geometry and a basic mesh material. Both objects are positioned and added to the scene. The floor is rotated to be horizontal, and it is set to receive shadows.

window.addEventListener('resize', function () {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});

function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
stats.update();
}

init();
animate();

1. `window.addEventListener(‘resize’, function () { … });`: This line adds an event listener to the window’s resize event. Whenever the window is resized, the function inside the event listener is executed.

- `camera.aspect = window.innerWidth / window.innerHeight;`: This line updates the aspect ratio of the camera to match the new width and height of the window. This ensures that the scene is rendered correctly without distortion.

- `camera.updateProjectionMatrix();`: This line updates the camera’s projection matrix to reflect the changes in aspect ratio. It ensures that the scene is rendered with the correct perspective.

- `renderer.setSize(window.innerWidth, window.innerHeight);`: This line updates the size of the renderer to match the new width and height of the window. It ensures that the rendered scene fills the entire window.

2. `function animate() { … }`: This is the animation loop function. It is called recursively using `requestAnimationFrame()` to render the scene continuously.

- `requestAnimationFrame(animate);`: This line requests the browser to call the `animate()` function before the next repaint. It creates a loop that keeps updating and rendering the scene at the browser’s frame rate.

- `renderer.render(scene, camera);`: This line renders the scene with the specified camera using the renderer. It draws each frame of the scene based on the current camera position and object configurations.

- `stats.update();`: This line updates the stats object, which may be a performance monitor or debug information, to reflect the current frame’s statistics.

3. `init();`: This line calls the `init()` function, which initializes the necessary components, such as the canvas, renderer, scene, camera, controls, and objects.

4. `animate();`: This line calls the `animate()` function to start the animation loop and continuously render the scene.

In summary, this code sets up the event listener for window resizing to ensure the scene adapts correctly to different window sizes. It also defines the animation loop that continuously renders the scene and updates any relevant statistics. The `init()` function is called to initialize the necessary components, and then the animation loop is started with the `animate()` function.

Full code

<html lang="en">
<head>
<title>three.js - Boilerplate</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script>

<style>
body {
background-color: grey
}

html,
body {
margin: 0;
height: 100%;
}

#canvas {
width: 100%;
height: 100%;
display: block;
color: rgb(40, 63, 141);
}
</style>

</head>

<body>
<canvas id="canvas"></canvas>
<script type="importmap">
{
"imports": {
"three": "../threeJS/build/three.module.js"
}
}
</script>
<script type="module">
import * as THREE from 'three';
import { OrbitControls } from '../threeJS/examples/jsm/controls/OrbitControls.js';
import * as DAT from '../threeJS/newadded/DatGUI.js';
import { Stats } from "../threeJS/newadded/Stats.js";

//---gui---//
var gui;
gui = new DAT.GUI();
var lightGui = false;
var statsGui = true;
gui.close();

// three var
var canvas, renderer, scene, camera, controls, stats;





function init() {
canvas = document.getElementById('canvas');

renderer = new THREE.WebGLRenderer({ canvas });
renderer.setSize(window.innerWidth, window.innerHeight);
stats = Stats();
statsGui && document.body.appendChild(stats.dom);

scene = new THREE.Scene();
scene.background = new THREE.Color('black');
scene.fog = new THREE.Fog(0xffffff, 0, 750);

const axesHelper = new THREE.AxesHelper(500);
scene.add(axesHelper);

const ambientLight = new THREE.AmbientLight(0xffffff, 0.7)
scene.add(ambientLight)

camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.y = 100;
camera.position.z = 250;


controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.6;
controls.screenSpacePanning = false;
controls.maxPolarAngle = Math.PI / 2.02;
controls.minDistance = 10;
controls.maxDistance = 1000;
controls.update();

const floorGeometry = new THREE.PlaneGeometry(500, 500);
const floorMaterial = new THREE.MeshStandardMaterial({
color: '#777777',
metalness: 0.2,
roughness: 0.4,
envMapIntensity: 0.5,
side: THREE.DoubleSide

});
const floor = new THREE.Mesh(floorGeometry, floorMaterial)
floor.receiveShadow = true
floor.rotation.x = - Math.PI * 0.5
floor.position.set(0, 0, 0)
scene.add(floor)

const m1Geometry = new THREE.BoxGeometry(50, 100, 50);
const m1Material = new THREE.MeshBasicMaterial({
color: '#ff0',
});
const m2 = new THREE.Mesh(m1Geometry, m1Material);
m2.position.set(0, 0, 0)
scene.add(m2)


window.addEventListener('resize', function () {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
}


function animate() {
requestAnimationFrame(animate)
renderer.render(scene, camera);
stats.update();
}
init()
animate();
</script>
</body>

</html

Output :

outut of above code

--

--