Three.js Realistic Shadows: A Practical Guide

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




3d websites

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

Popular posts from this blog

#30 Sets in Python - Part 1 (Python Tutorials)

Best Unity Game Ideas for the Game Developers

How to Start a Blockchain Services Business?