Help with cast shadows for Mesh3D

Godot Version

4.4.1.stable

Question

Mesh3D cast shadows appear incorrect

Hi.

I’m using a Mesh3D that generates the terrain for my map. Here’s what that looks like:

I spent some time and added elevation in a really simple way, with individual hexagons having random elevation.

I have then added a directional light 3D. My thinking was to animate the rotation of the directional light to act as a simple day/night indicator for the game, with the terrain casting shadows.

However I’m unhappy with the shadows. For example what I circled above. The terrain to the left of the red circle should be casting a shadow facing NE-ish. This appears to kinda be happening, since you can see the end of the shadow, however, at the self-shaded base of the tile (in the rear side), its not only not shaded, it appears bright.

Is there an issue with the approach with directional light, or some issue with my Mesh?

Here’s some extra info:

  • I dont’ provide normals for the mesh to the add_surface_from_arrays call, just vertices. Would computing normals help here?
  • Ideally I’d like shadows to end up looking nice and crisp like the example shown here: https://www.wolfire.com/blog/2008/11/high-detail-terrain-shadows/ . I understand the terrain detail is much higher there, but the current approach I have feels much much worse.
  • I have the directional shadow max distance set to 8192. The terrain maps I’m generating are much bigger than this is there a way I can increase this, or have some different solution ?

Depending on how you generated the mesh, you will need to calculate the surface normals for the new terrain. One of godots mesh tools the normal calculation is just a function called generate_normals, too lazy to search the docs, but will be the easiest way to get proper shading.

The manual way to do it is sampling three vertexes to get two vectors on the surface to calculate the normal with a cross product.

Hey thank you for the reply!

Should I pass these normals to the mesh generation under surface[ArrayMesh.ARRAY_NORMAL] ?

You will need to calculate the normals as wells as just including.

If you are using SurfaceTool generate_normals will work.

If you are using ArrayMesh regen_normals might work

MeshDataTool and ImmediateMesh you need to calculate normals manually

1 Like