Three.js Realistic Shadows: A Practical Guide
In this tutorial, we want to create more realistic scenes by making the shadow effect. There are
many parameters in creating a shadow of an object. One of them is the material. For instance, if
you use the Mesh-basic material, you will see no shadow effects. The next important parameter is
the light source. Different light sources create various types of shadows. Some of them do not
generate any shadow effect on the object. Our blog has covered a complete article about the light
sources in Three.js. Another element that can provide the shadow effect is the background scene.
There is also another article about background scenes on our blog. Once you use the background
for your scene, depending on the quality of the HDR image, the light source (for instance, the
sun) will act as a light source like the point light or the rect-area light. Furthermore, we can use
the shadow properties of the point light. This tutorial will test these properties and see their effects
on a sphere object.
Getting started with the basics:
We will get started with the main elements of a Three js scene, including the camera,
the renderer, the scene, and the object. Before doing that, we use the Vite plugin to
easily create all the folders and files you need to run the Three.js code. First off,
create a folder in the directory of your projects by using the following commands:
Coppied to clipboard.
mkdir Shadows
cd Shadows
Then, inside of the your project folder, create the necessary files and folders by
simply running the Vite plugin command:
Coppied to clipboard.
npm create vite@latest
Then enter the name of the project. You can write the name of your project as the
name. And also the package (the name is arbitrary, and you can choose anything
you want). Then select vanilla as the framework and variant. After that, enter the
following commands in the terminal. Notice that here Shadows is the project folder's
name, and thus, we have changed the directory to Shadows. The name depends on
the name you enter in the Vite plugin :
Coppied to clipboard.
cd Shadows
npm install
Afterward, you can enter the JavaScript code you want to write in the main.js file. So,
we will enter the base or template code for running every project with an animating
object, such as a sphere. Also, do not forget to install the Three.js package library
every time you create a project:
Coppied to clipboard.
npm install three
The code:
Now, enter the following script in the main.js file:
import * as THREE from 'three';
import { OrbitControls } from '/node_modules/three/examples/jsm/controls/OrbitControls.js';
import Stats from '/node_modules/three/examples/jsm/libs/stats.module.js';
const scene = new THREE.Scene();
const light = new THREE.DirectionalLight();
light.castShadow = true;
light.shadow.mapSize.width = 512;
light.shadow.mapSize.height = 512;
light.shadow.camera.near = 0.05;
light.shadow.camera.far = 200;
scene.add(light);
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
)
camera.position.z = 7;
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
document.body.appendChild(renderer.domElement);
new OrbitControls(camera, renderer.domElement);
//creating the plane
const planeGeometry = new THREE.PlaneGeometry(20, 20);
const planeMaterial = new THREE.MeshPhongMaterial({
map : new THREE.TextureLoader().load('./img/aerial_rocks_02_diff_4k.jpg')
});
planeMaterial.displacementMap = new THREE.TextureLoader().load('./img/aerial_rocks_02_disp_1k.jpg');
planeMaterial.normalMap = new THREE.TextureLoader().load('./img/aerial_rocks_02_nor_dx_1k.jpg');
const plane = new THREE.Mesh(planeGeometry, planeMaterial );
plane.rotateX(-Math.PI / 2);
plane.position.y = -1.75;
plane.position.z = -2;
plane.receiveShadow = true;
scene.add(plane);
//creating the torus
const torusGeometry = new THREE.TorusGeometry(1, 0.3, 16, 100);
const material = new THREE.MeshStandardMaterial();
const torus = new THREE.Mesh( torusGeometry, material);
torus.position.x = 0;
torus.position.y = 0;
torus.castShadow = true;
torus.receiveShadow = true;
scene.add(torus);
window.addEventListener('resize', onWindowResize, false);
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
Render();
}
const stats = Stats();
document.body.appendChild(stats.dom);
function animate() {
requestAnimationFrame(animate);
torus.rotation.x += 0.02;
render();
stats.update();
}
function render() {
renderer.render(scene, camera);
}
animate();
Now if we save the code, and enter the following command in the terminal:
Coppied to clipboard.
npm run dev
We should see the following result:
Which is a rotating torus with its shadow on the texture of the plane. You can rotate
around the scene and see from other angles.
You can create a new folder called img and add any texture that you want in it.
Notice that in the folder, you should have the normal map, the displacement map,
and the texture photo, and also edit the names in the script according to the names
of the texture images. If you do not want to have the texture, you can remove the
map, displacement map, and normal map from the script. We have downloaded the
texture of the above scene from polyhaven.com.
Explaining the code:
The first thing we did at the beginning was to import the necessary libraries. Then,
we defined the scene, the point light, the camera, and the renderer. In the point light
section of the code, we set the castShadow property to true. Afterward, we set the
size and the distance of the shadow. Next, we enabled the shadowMap property for
the renderer and specified its type to PCFSoftShadowMap.After that, we created a
plane and set its position. We also set the receiveShadow property to true, So that
we can see the shadows of the objects on it. We also created a torus and did the
same as we did for the plane on it, in addition to setting the castShadow and
receiveShadow properties to true so that it can cast the shadow and receive the
shadow of itself. In the end, we wrote the animation code for the torus.
Conclusion
In this tutorial, we worked on different shadow properties of the point light,
materials, the renderer, and the camera to be able to create the shadow effect.
There are two types of shadow properties for the objects. One of them is the cast
shadow property which will cast the shadow of the object on the ground, other
objects, or itself (not all shapes cast shadows on themselves). And the other one
is the receive shadow property that lets the object receive the shadows of other
objects.
Moreover, the renderer has different types of shadow mapping. In this
tutorial, we only used the PCFSoftShadowMap . But, there are other types which
you can find the complete list from the official website of Three.js.
Download this Article in PDF format
Arashtad Custom Services
In Arashtad, we have gathered a professional team of developers who are working in fields such as 3D websites, 3D games, metaverses, and other types of WebGL and 3D applications as well as blockchain developemnet.
Visit Our Services
Arashtad Serivces
Drop us a message and tell us about your ideas.
Fill in the Form
Blockchain Development
https://blog.arashtad.com/3d/webgl/threejs/three-js-realistic-shadows-a-practical-guide/
Comments
Post a Comment