In Three.js DirectionalLight not cast shadow to plane - three.js

I can't cast shadow to a plane with directional light in three.js r79.
I have tried every thing, but never worked.
I added a CameraHelper to scene, and all things were inside the area by yellow lines around.But it just doesn't work...
Here's the screen shot:
code:
function init(canvas) {
const renderer = new THREE.WebGLRenderer({
antialias: true,
canvas: canvas,
//alpha: true
});
//renderer.setClearColor(0x777777);
renderer.shadowMap.enabled = true;
renderer.shadowMap.soft = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
renderer.shadowMap.needsUpdate = true;
renderer.setSize(innerWidth, innerHeight);
renderer.autoClear = true;
renderer.gammaInput = true;
renderer.gammaOutput = true;
const scene = new THREE.Scene();
const pCamera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 2000);
pCamera.position.x = 300;
pCamera.position.y = -200;
pCamera.position.z = 50;
pCamera.lookAt({x: 0, y: 0, z: -200});
scene.add(pCamera);
//const controls = new THREE.OrbitControls(pCamera, canvas);
//controls.maxPolarAngle = Math.PI * 0.5;
//controls.minDistance = 1000;
//controls.maxDistance = 7500;
const directLight = new THREE.DirectionalLight(0xffffff, 1);
directLight.position.x = 400;
directLight.position.y = 2000;
directLight.position.z = 500;
directLight.castShadow = true;
directLight.shadow.camera.far = 300;
directLight.shadow.camera.near = 100;
directLight.shadow.mapSize.width = 1024;
directLight.shadow.mapSize.height = 1024;
directLight.shadow.bias = 0.0039;
const d = 100;
directLight.shadow.camera.left = -d;
directLight.shadow.camera.right = d;
directLight.shadow.camera.top = -d;
directLight.shadow.camera.bottom = d;
scene.add(directLight);
const cameraHelper = new THREE.CameraHelper(directLight.shadow.camera);
scene.add(cameraHelper);
const cube = new THREE.Mesh(new THREE.BoxGeometry(50, 50, 50), new THREE.MeshLambertMaterial({color: 0xcc0000}));
cube.position.z = -200;
cube.castShadow = true;
scene.add(cube);
const plane = new THREE.Mesh(new THREE.PlaneGeometry(200, 200), new THREE.MeshLambertMaterial({color: 0x22ff11}));
plane.receiveShadow = true;
plane.position.z = -215;
scene.add(plane);
scene.add(new THREE.AmbientLight(0x212223, 0.1));
return function () {
renderer.render(scene, pCamera);
};
}

Related

Selfshadow plane affected by a displacement map not working

Working on some kind of fictional treasure map. I'm cutting a large displacement map intosmaller tiles as I don't yet how wide the final terrain is going to be -- right now it's 5*5, but it could be wider in the future
For some reasons, I am having issues projecting shadows on the displaced planes.
I don't know where the problem is coming from. Maybe it's the way I push meshes into an array through a function, i'm afraid i'm not doing this the right way.
I'd like to achieve the result using a directional light
Here is a c4d draft of what i'm trying to achieve
and here is what i'm able to do in the browser (didnt manage to tile them properly yet :^)
var renderer = new THREE.WebGLRenderer();
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
var material = [];
var texture = [];
var tile = [];
var planeRes = 128;
var planesize = 1;
var dim = 5;
var size = dim * dim;
var DispScale = 2;
var geometry = new THREE.PlaneBufferGeometry(planesize,planesize,planeRes, planeRes);
function tileGenerator(inc) {
if (inc < 10) {
texture[inc] = new THREE.TextureLoader().load('cut25lowres/image_part_00' + inc + '.jpg');
} else {
texture[inc] = new THREE.TextureLoader().load('cut25lowres/image_part_0' + inc + '.jpg');
}
material[inc] = new THREE.MeshPhongMaterial({
color: 0xffffff,
displacementMap: texture[inc],
side: THREE.DoubleSide,
receiveShadow : true,
castShadow : true
});
tile[inc] = new THREE.Mesh(geometry, material[inc]);
}
for (var i = 1; i < size + 1; i++) {
tileGenerator(i);
}
for (var i = 1; i < size + 1; i++) {
tile[i].position.set(-planesize * (i % dim)+1, 0, -planesize * Math.ceil(i / dim)+1 );
tile[i].rotation.x = Math.PI / 2 + Math.PI;
tile[i].rotation.z = Math.PI / 2;
scene.add(tile[i]);
}
var dirLight = new THREE.DirectionalLight( 0xffffff, 1 );
dirLight.castShadow = true;
dirLight.shadow.camera.near = 0.1;
dirLight.shadow.camera.far = 6;
dirLight.shadow.mapSize.set( 1024, 1024 );
var targetObject = new THREE.Object3D();
targetObject.position.x = -10;
targetObject.position.z = -10;
dirLight.position.y = 3;
scene.add(targetObject);
dirLight.target = targetObject;
scene.add( dirLight );
Edit : Here is a cleaner version without the array as it's not part of the problem
jsfiddle.net/clemtre/3y9tqc6j/34
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
var renderer = new THREE.WebGLRenderer();
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var controls = new THREE.OrbitControls(camera, renderer.domElement);
var scene = new THREE.Scene();
var heightmap = new THREE.TextureLoader().load('https://i.imgur.com/MVYhfd7.jpeg');
var geometry = new THREE.PlaneGeometry(20, 20, 100, 100);
var material = new THREE.MeshPhongMaterial({
color: 0xffffff,
displacementMap: heightmap,
displacementScale: 10
});
var light = new THREE.DirectionalLight(0xffffff);
light.position.set(0, 1, 1).normalize();
light.castShadow = true;
scene.add(light);
var plane = new THREE.Mesh(geometry, material);
plane.rotation.x = -Math.PI/2;
scene.add(plane);
camera.position.z = -20;
camera.position.y = 5;
controls.update();
var animate = function() {
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
};
animate();
Many thanks!

Issues casting shadow

I want my tableBoard (Surface of the table) and tableLegs to cast their shadows upon the floor
Light
import * as THREE from "three";
export default ({ scene }) => {
const lights = [];
lights[0] = new THREE.PointLight(0xffffff, 1, 0);
lights[0].position.set(0, 200, 0);
lights[0].castShadow = true;
scene.add(lights[0]);
}
Objects(Mesh)
tableLeg1.castShadow = true;
tableBoard.castShadow = true;
floor.receiveShadow = true;
tableLeg1.add(floor);
tableBoard.add(tableLeg1);
scene.add(tableBoard);
renderer
sceneSetup = () => {
const width = this.el.clientWidth;
const height = this.el.clientHeight;
this.scene = new THREE.Scene();
this.camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 1000);
this.camera.position.z = 5;
this.controls = new OrbitControls(this.camera, this.el);
this.renderer = new THREE.WebGLRenderer({antialias: true});
this.renderer.shadowMap.enabled = true;
this.renderer.setSize(width, height);
this.el.appendChild(this.renderer.domElement);
};

Two objects don't cast a shadow while other one does

I have exactly the same three cube objects except their x position.
I want them to cast a shadow, but somehow two of them don't cast a shadow while the other one does.
Here is the pic of what's happening.
https://ibb.co/z6Vwxmf
I'm sure that castShadow is set to true on all the objects.
And I don't think I missed any shadow setting property either (because the middle object casts a shadow properly.)
These objects are created under //left cube //right cube comments in the below code.
< script >
window.addEventListener('load', init, false);
function init(event) {
createScene();
createLights();
createTile01();
createTile02();
createTile03();
createBase();
loop();
}
var scene, camera, Width, Height, renderer, container;
function createScene() {
Width = window.innerWidth;
Height = window.innerHeight;
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.x = 0;
camera.position.y = 10;
camera.position.z = 50;
camera.lookAt(scene.position);
renderer = new THREE.WebGLRenderer();
renderer.setClearColor(new THREE.Color(0x000000));
renderer.setSize(Width, Height);
renderer.shadowMap.enabled = true;
container = document.getElementById('scene');
container.appendChild(renderer.domElement);
window.addEventListener('resize', handleWindowResize, false);
}
function handleWindowResize() {
Height = window.InnerHeight;
Width = window.InnerWidth;
renderer.setSize(Width, Height);
camera.aspect = Width / Height;
camera.updateProjectionMatrix();
}
var ambiLight, spotLight;
function createLights() {
ambiLight = new THREE.AmbientLight(0xffffff);
scene.add(ambiLight);
spotLight = new THREE.DirectionalLight(0xffffff);
spotLight.position.set(0, 30, -0);
spotLight.intensity = 1;
spotLight.castShadow = true;
scene.add(spotLight);
}
Tile01 = function() {
var geom = new THREE.BoxGeometry(10, 10, 2);
var mat = new THREE.MeshPhongMaterial({
color: 0x53b0df
});
this.mesh = new THREE.Mesh(geom, mat);
this.mesh.receiveShadow = true;
this.mesh.castShadow = true;
}
var tile01;
function createTile01() {
tile01 = new Tile01();
tile01.mesh.position.set(0, 0, 0);
scene.add(tile01.mesh);
}
//right cube
Tile02 = function() {
var geom = new THREE.BoxGeometry(10, 10, 2);
var mat = new THREE.MeshPhongMaterial({
color: 0x25b0cf
});
this.mesh = new THREE.Mesh(geom, mat);
this.mesh.receiveShadow = true;
this.mesh.castShadow = true;
}
var tile02;
function createTile02() {
tile02 = new Tile02();
tile02.mesh.position.set(20, 0, 0);
scene.add(tile02.mesh);
}
//left cube
Tile03 = function() {
var geom = new THREE.BoxGeometry(10, 10, 2);
var mat = new THREE.MeshPhongMaterial({
color: 0x00b0df
});
this.mesh = new THREE.Mesh(geom, mat);
this.mesh.receiveShadow = true;
this.mesh.castShadow = true;
}
var tile03;
function createTile03() {
tile03 = new Tile03();
tile03.mesh.position.set(-20, 0, 0);
scene.add(tile03.mesh);
}
Base = function() {
var geom = new THREE.CylinderGeometry(100, 30, 5, 60);
var mat = new THREE.MeshPhongMaterial({
color: 0xcf34ec
});
this.mesh = new THREE.Mesh(geom, mat);
this.mesh.castShadow = true;
this.mesh.receiveShadow = true;
}
var base;
function createBase() {
base = new Base();
base.mesh.position.set(0, -10, -20);
scene.add(base.mesh);
}
function loop() {
renderer.render(scene, camera);
requestAnimationFrame(loop);
}
< /script>
Could you help me figure out what's wrong with the setting?
I was able to resolve the issue myself.
Referring to some solutions I found at other Q/As about a shadow issue, I added a shadow.camera.left/right/top/bottom properties to the light and it worked.
The below is the code I corrected.
Now I can see the shadows of all the three objects.
var ambiLight, spotLight;
function createLights() {
ambiLight = new THREE.AmbientLight(0xffffff);
scene.add(ambiLight);
spotLight = new THREE.DirectionalLight(0xffffff);
spotLight.position.set(0, 30, -0);
spotLight.intensity = 1;
spotLight.castShadow = true;
spotLight.shadow.camera.left = -400;
spotLight.shadow.camera.right = 400;
spotLight.shadow.camera.top = 400;
spotLight.shadow.camera.bottom = -400;
spotLight.shadow.camera.near = 1;
spotLight.shadow.camera.far = 1000;
spotLight.shadow.mapSize.width = 2048;
spotLight.shadow.mapSize.height = 2048;
scene.add(spotLight);
}

Three.js LatheGeometry won't cast shadows

Lathe Geometry won't cast shadows but spheres and cubes do. Why is that ?
Image
My renderer:
var webGLRenderer = new THREE.WebGLRenderer();
webGLRenderer.setClearColor(0xAAAAAA, 1.0);
webGLRenderer.setSize(window.innerWidth, window.innerHeight);
webGLRenderer.shadowMapEnabled = true;
Lathe:
var latheGeometry = new THREE.LatheGeometry(array, Math.ceil(segments), 0, 2 * Math.PI);
//var meshMaterial = new THREE.MeshBasicMaterial({color:0x00ff00, transparent:true, opacity:0.6});
var meshMaterial = new THREE.MeshLambertMaterial({color: 0xFFFFFF});
meshMaterial.side = THREE.DoubleSide;
var wireFrameMat = new THREE.MeshBasicMaterial();
wireFrameMat.wireframe = false;
latheMesh = THREE.SceneUtils.createMultiMaterialObject(latheGeometry,[meshMaterial, wireFrameMat]);
latheMesh.rotation.x = Math.PI * -0.5;
latheMesh.position.z = 0;
latheMesh.castShadow = true;
scene.add(latheMesh);
My lighting:
var pointColor = "#ffffff";
directionalLight = new THREE.DirectionalLight(pointColor);
directionalLight.position.set(-50,50,50);
directionalLight.castShadow = true;
directionalLight.receiveShadow = false;
directionalLight.shadowCameraVisible = true;
directionalLight.intensity = 1;
directionalLight.shadowCameraNear = 50;
directionalLight.shadowCameraFar = 200;
directionalLight.shadowCameraLeft = -50;
directionalLight.shadowCameraRight = 40;
directionalLight.shadowCameraTop = 50;
directionalLight.shadowCameraBottom = -50;
directionalLight.distance = 0;
directionalLight.shadowMapHeight = 1024;
directionalLight.shadowMapWidth = 1024;
//scene.add( new THREE.DirectionalLightHelper(directionalLight, 0.5) );
scene.add(directionalLight);
As you can see, only sphere can cast shadow and not latheGeometry.
THREE.SceneUtils.createMultiMaterialObject() creates a THREE.Group with a child Mesh for each material.
You need to specify the castShadow property not for the group, but for the child mesh you want to cast the shadow.
three.js r.76

Three JS - Casting Shadows

I am trying to get the shadow from the ball appear on the floor, but it doesn't seem to work. Here is my code that declares the renderer, camera, lights, and objects:
var renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.shadowMapEnabled = true;
renderer.shadowMapType = THREE.PCFSoftShadowMap;
document.body.appendChild( renderer.domElement );
var planegeo = new THREE.PlaneGeometry(100,100);
var geomaterial = new THREE.MeshLambertMaterial({color: "#EA8E12", side: THREE.DoubleSide});
var plane = new THREE.Mesh(planegeo, geomaterial);
plane.rotation.x += 90;
plane.position.z = -2;
scene.add(plane);
var light = new THREE.AmbientLight( "#EA8E12", 101);
var light2 = new THREE.DirectionalLight("yellow", 100);
light.position.set(0, 100, 0);
light2.position.set(0, 100, 0);
scene.add(light);
scene.add(light2);
var sphereParent = new THREE.Object3D();
var geometry = new THREE.SphereGeometry(1, 100, 100);
var material = new THREE.MeshPhongMaterial( {color: "yellow", shininess: 100});
var circle = new THREE.Mesh(geometry, material);
sphereParent.add(circle);
sphereParent.position.set(0,3,0);
scene.add(sphereParent);
light2.castShadow = true;
circle.castShadow = true;
sphereParent.castShadow = true;
plane.receiveShadow = true;
Does anyone can tell me what I am missing? Thanks
This should get you started. Modify the parameters as needed:
light2.castShadow = true;
light2.shadowMapWidth = 1024;
light2.shadowMapHeight = 1024;
light2.shadowMapDarkness = 0.75;
light2.shadowCameraNear = 1;
light2.shadowCameraFar = 1000;
light2.shadowDarkness = 0.75;
/* since you have a directional light */
light2.shadowCameraLeft = -500;
light2.shadowCameraRight = 500;
light2.shadowCameraTop = 500;
light2.shadowCameraBottom = -500;
light2.shadowCameraVisible = true; /* debugging */
on the renderer side this might help:
renderer.shadowMapDebug = true;

Resources