Directional light not showing shadows

shadow

#1

Hello,

I’ve been trying to add shadows to my huge terrain. I’ve been thinking it would be best to add the shadow to the camera so while to camera moves around the shadows are only rendered for whats within the view of the camera.

Here is my attempt:

let root = new THREE.Group();
root.add(camera);

root.position.set(-3500, 50, -7800); // edge of terrain at -20000, 0, -20000
scene.add(root);

let light = new THREE.DirectionalLight(0xfffffff, 0.5);
light.position.set(0, 1, 0);
light.castShadow = true;
light.shadow.mapSize.width = 512;  
light.shadow.mapSize.height = 512; 
light.shadow.camera.near = 0.5;
light.shadow.camera.far = 500     

scene.add(new THREE.CameraHelper(light.shadow.camera));

scene.add(light);
root.add(light.shadow.camera);

I also did not forget to enable receiveShadows on the terrain and castShadows on the objects on the terrain.

But I only get this:

The shadow camera seems too small. But, if I make the map size beyond 4096, it just slows everything down.

What are my options here? I wanted to have soft shadows from a little angle from the top as if its around afternoon.


#2

It seems you have not yet configured the frustum of the shadow camera correctly. Try it like mentioned here:


#3

I tried adding this:

const d = 100;

light.shadow.camera.left = - d;
light.shadow.camera.right = d;
light.shadow.camera.top = d;
light.shadow.camera.bottom = - d;

And got this:

Looks bigger but unfortunately still no shadows.


#4

Are you sure that materials of your model are not THREE.MeshBasicMaterial()?


#5

Yes, all are THREE.MeshLambertMaterial. Just to be thorough, I also added

 mesh.receiveShadow = true;
 mesh.castShadow = true

to everything in the scene. And made the frustum const d = 1000; to be huge but still nothing:


#6

Is your city one big object? Or does it consist out of many single meshes?

Is it possible for you to demonstrate the issue with an editable fiddle?

BTW: Don’t forget to globally enable shadow maps like so:

renderer.shadowMap.enabled = true;

#7

Yep, I also did that. Including setting the type of shadows to soft. The terrain consist of 1 big mesh, with about 225k vertices and about 500k+ faces. I know I should optimize this in someway but that would be another question as I have no idea. But for now, I’m having issues with shadows.

Unfortunately I can’t host it on websites like JSFiddle as I cannot include the object data. If you don’t mind, I uploaded it to my website. But I did cut it down to the simplest script with the problem.

You can find it here: https://blazekhan.com/public/map_viewer/
It could take awhile because the assets are bit large.

Thank you for taking your time.


#8

Please try to switch to MeshPhongMaterial to see if it helps. Shadow quality with MeshLambertMaterial is poor in any case. It’s not a good choice for rendering shadows.

Besides, there seems to be something wrong with the normal data of your geometries. When I set the intensity of the ambient light to zero so only the directional light illuminates the scene, it looks like so:

I guess that’s not the intended visual result.


#9

Should I just let THREE.JS calculate the normals? Instead of adding them from my assets?

I tried changing all materials from lambert to phong. Removed the ambient light. Tried fixing the normals to no success.

And I got this:

I’m starting to see shadows but I guess the normals issue is causing problems. The data is from DirectX so I tried multiplying the first part of the normals by -1 to make it work for OpenGL/WebGL. Maybe I’m doing ti wrong.


So I decided to just discard all normal data and let THREE.JS calculate all of it. Added the ambient light back to the scene and got this:

Still not very sure about the shadows though. Might be the positioning of the directional light?


#10

With such a large frustum, shadow quality will be bad in any event. Try to keep the frustum as small as possible and also alter the angle of the light a bit (so it does not cast shadow from top).