Shadows are not being cast by ThreeJS

I'm in the process of creating a simple Three JS application. As I familiarize myself with Three JS, I've been experimenting with different features. Currently, I am working on constructing a scene that includes a floor, an object, and a light source. My goal is to be able to see the shadow of the object being cast onto the floor by the light. Below is the code snippet I have been working on:

import * as THREE from 'three';
const scene = new THREE.Scene();
const aspect_ratio = window.innerWidth / window.innerHeight;
const camera = new THREE.PerspectiveCamera(75, aspect_ratio, 1, 10000);
camera.position.z = 500;
scene.add(camera);

const renderer = new THREE.WebGLRenderer();
renderer.shadowMapEnabled = true;
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.append(renderer.domElement);

var shape = new THREE.TorusGeometry(100, 50, 8, 20);
var cover = new THREE.MeshPhongMaterial();
cover.emissive.setRGB(0.8, 0.1, 0.1);
cover.specular.setRGB(0.9, 0.9, 0.9);
var donut = new THREE.Mesh(shape, cover); scene.add(donut);
donut.castShadow = true;

var sunlight = new THREE.DirectionalLight();
sunlight.intensity = 0.5;
sunlight.position.set(100, 100, 100);
scene.add(sunlight);
sunlight.castShadow = true;

var shape = new THREE.PlaneGeometry(1500, 1500);
var cover = new THREE.MeshBasicMaterial();
var ground = new THREE.Mesh(shape, cover);
scene.add(ground);
ground.position.set(0, -180, 0);
ground.rotation.set(-Math.PI/2, 0, 0);
ground.receiveShadow = true;

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

The issue I'm facing is that despite setting up the scene for the shadows, the donut does not seem to cast any shadow on the floor as intended. Instead, it appears without the shadow effect.

https://i.sstatic.net/KG8AQ.png

I would greatly appreciate any guidance or assistance in identifying what might be incorrect in my code and how I can rectify it to achieve the desired shadow effect?

Answer №1

Your code has several issues that need to be addressed. The main problem lies in the incorrect configuration of your shadow frustum. Additionally, it is important to note that MeshBasicMaterial does not interact with light and therefore cannot receive shadows. To resolve these issues, consider implementing the following adjustments:

const scene = new THREE.Scene();
const aspect_ratio = window.innerWidth / window.innerHeight;
const camera = new THREE.PerspectiveCamera(75, aspect_ratio, 1, 10000);
camera.position.z = 500;
scene.add(camera);

const renderer = new THREE.WebGLRenderer();
renderer.shadowMap.enabled = true;
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.append(renderer.domElement);

const donutGeometry = new THREE.TorusGeometry(100, 50, 8, 20);
const donutMaterial = new THREE.MeshPhongMaterial();
donutMaterial.emissive.setRGB(0.8, 0.1, 0.1);
donutMaterial.specular.setRGB(0.9, 0.9, 0.9);
const donut = new THREE.Mesh(donutGeometry, donutMaterial); 
scene.add(donut);
donut.castShadow = true;

var sunlight = new THREE.DirectionalLight();
sunlight.intensity = 0.5;
sunlight.position.set(100, 100, 100);
scene.add(sunlight);
sunlight.castShadow = true;
sunlight.shadow.camera.top = 200;
sunlight.shadow.camera.bottom = - 200;
sunlight.shadow.camera.left = - 200;
sunlight.shadow.camera.right = 200;
sunlight.shadow.camera.near = 1;
sunlight.shadow.camera.far = 1000;

//scene.add( new THREE.CameraHelper( sunlight.shadow.camera ) );

const groundGeometry = new THREE.PlaneGeometry(1500, 1500);
const groundMaterial = new THREE.MeshPhongMaterial();
const ground = new THREE.Mesh(groundGeometry, groundMaterial);
scene.add(ground);
ground.position.set(0, -180, 0);
ground.rotation.set(-Math.PI/2, 0, 0);
ground.receiveShadow = true;

function animate() {
    requestAnimationFrame(animate);
    renderer.render(scene, camera);
}
animate();
body {
      margin: 0;
}
<script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="e4908c968181a4d4cad5d0d0">[email protected]</a>/build/three.min.js"></script>

Answer №2

In order to create a shadow on the ground, you must prepare the surface first

follow these steps:

surface.createShadow = true;

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Ways to substitute a single parameter within Vue.js router

We are working on a complex multi-level multi-tenant application, where the hostname is used to identify the 'supplier' account and the customer account is included in the URL structure. For example, our routes are structured like this: /:local ...

including a content tag into an input field within a template

I'm experimenting with the new html5 template tag to create a versatile form that can be used in various situations without relying heavily on javascript. Check out this fiddle to see what I have so far http://jsfiddle.net/684uH/ My objective is to ...

Switch effortlessly between one animation and another with Angular.js

I have two animations named "prev" and "next". Upon clicking the prev button, the "prev" animation should play. Similarly, when you click on the "next" button, the "next" animation should be triggered. I am using ng-class to achieve this behavior. How can ...

Encountered error message: "Cannot assign argument of type '() => () => boolean' to parameter of type 'EffectCallback'"

I recently started working with TypeScript. I encountered an issue when attempting to utilize useEffect in TypeScript within a React context, Error: Argument of type '() => () => boolean' is not assignable to parameter of type 'Effec ...

The ClearInterval() function does not take effect instantly

I've implemented a Carousel with an auto-toggle feature using the setInterval() function to switch between tabs every 4 seconds. However, I now need to stop this automatic toggling when a specific tab is clicked. You can find the HTML and jQuery for ...

Traversing an array of objects in TypeScript and appending to a separate array if not already present

I have been given an array containing objects in the following format: export interface Part { workOrder?: string; task?: string; partNumber?: string; qty?: number; image?: string; name?: string; } My goal is to loop through each object in th ...

Creating a tree structure from a one-dimensional array with the help of dual data tables in JavaScript

I'm struggling to create a tree structure from a flat array using two Mock data tables in JSON. The table should match the unique IDs to determine the hierarchy between them. JSON with Groups DB array example: { "group": [ { "groupName" ...

Node.js/Express/Jade scripts failing to load in the expected order

Imagine having this code snippet in a .jade file: doctype 5 html head title= title link(rel='stylesheet', href='/stylesheets/style.css') script(src='/javascripts/ocanvas-2.2.2.min.js', type='text/javascript') ...

Vue.js - Maintaining input value when model declines updates

I am working on a text input that allows users to enter numbers with a maximum of three digits after the decimal point: <v-text-field type="text" :value="num" @change="changeNum($event)" /> <p>{{ num }}</p> ... export default { data: ...

Error encountered: jQuery AJAX JSON request failed to be caught

While my WordPress AJAX process is successful, a peculiar error keeps popping up in Chrome Devtools: Uncaught TypeError: Cannot read property 'vehicle' of undefined. It's puzzling, as the parsed JSON data seems to be in the correct object fo ...

What steps do I need to take in order to implement a functional pagination menu in Vue?

I downloaded and installed laravel-vue-pagination with the following command: npm install laravel-vue-pagination After that, I globally registered it in my app.js file: Vue.component('pagination', require('laravel-vue-pagination')); F ...

Switching perspective in express with Pug

Hello everyone, I'm still getting the hang of using Node.js with Express and Jade. I've successfully set up a basic 1 page app where a login page is displayed by default. Once the user logs in and is authenticated against a database, the function ...

When using vue.js(2), the function window.scrollY consistently returns a value of 0

Here are some issues I'm experiencing with vuejs and router: The window.addEventListener('scroll', ...) is not being detected in my component. When I enter 'window.scrollY' in console.log, it always returns 0 to me. Scroll(Y) is w ...

jQuery is experiencing compatibility issues with node-webkit

Currently, I am experimenting with node-webkit as a beginner in nodejs. The main content of my webpage consists of a simple html page which includes a script called main.js. To install jquery, I used the command npm install jquery index.html <!-- i ...

The function "Jest spyOn" does not exist

I’m currently facing an unfamiliar error while testing my React component using Jest. Here’s the code snippet for my <Row/> component: In my Row component, there are various methods like showDetailsPanel(), handleStatusChange(), handleModalCanc ...

The issue arises when using an Angular directive with an input type set as "number"

When the input type is text, the code below works perfectly fine. However, it fails to function when the input type is changed to number. <div ng-app="myApp" ng-controller="myCtrl as model"> <input type="text" ng-model="cero" ng-decimal > ...

Various filters have been utilized on an array of objects

Within one of my Vue components, the code structure is as follows: <li class="comment" v-for="comment in comments"> ... </li> Accompanied by a computed method: computed: { comments() { // Here lies the logic for filtering comment ...

JQuery - Issue: Invalid syntax detected in the expression: #

I'm facing an issue with some tabs inside an accordion that don't seem to be functioning properly. The console is showing the following error: Error: Syntax error, unrecognized expression: # Despite searching for a solution online, I can&apos ...

Implementing CodeIgniter's HMVC structure to dynamically update data using AJAX functionality

Recently, I came across an AJAX function in an open-source code that caught my attention. function edit_person(id) { save_method = 'update'; $('#form')[0].reset(); // reset form on modals //Ajax Load data from ajax $.ajax({ ...

The method for transferring text box values to the next page using a hyperlink in JSP is as follows:

Is there a way to pass the values of a text box in a JSP through a hyperlink on the same page? I want to achieve this but am not sure how. ...