Detect if a mesh surface is hit by a light or not

I am trying to write a small Python script in Blender which should be able to detect whether a surface of a mesh is hit by the light or not. Any ideas?

For example, in this image, I should output in binary form (e.g. “0” means that the surface is shadowed), while “1” means that the surface is lit by the sun) the the vertical wall of the small cube facing the tall building is shadowed (I should get a 0).

Perhaps there can be techniques with pixel buffers etc or perhaps voxel based, but I don’t know any of these. I know about stencil shadows only.

Everything starts with an occlusion query, a raycast from the light source to the target surface. If the raycast hits something before the target surface, it means that the light won’t see the surface.

Now the next step is to determine if the shadow hits the surface. You do a raycast from the light source to the vertex of the occluder mesh. Then you expand this ray towards the target surface. If the ray hits both of them it means that the shadow is cast correctly onto the target surface.
Shadow = Light + Occluder + Target Surface.

The next idea is to determine if you have partial shadowing. Which is instead of taking the center of the surface, you get all of the vertices of the surface and then you find the median term. Say for example you have four vertices and only two are hit and two are not. 1 + 1 + 0 + 0 = 2 / 4 = 0.5 However as said this is a statistical way to determine it, so you make an assumption that anything more than 0.5 is shadowed for good in any way, or anything less than 0.1 is almost a no-count.

More or less this is the theoretical approach. Is rather easy, because you only need to know one thing. Raycast. Then the rest is only about to think for optimizations, this is a continuous process that never ends.

blender\3.2\scripts\templates_py\operator_modal_view3d_raycast.py
2 Likes

Additionally, since the templates scripts is placed in the Python templates folder, you can simply select it from one of the Text Editor script templates.

No need to manually go look for it among your Blender files (unless you want to).

1 Like

Hey, thanks for the suggestions.
I am probably missing some basics about raycast, as I tried to run the template script “Operator Modal View 3d raycast”, but nothing really happen. Any suggestion?

PS: I am not interested in partial shadowing. For my use case it’s enough to do an approximation saying that if the center point of the surface is hit by the light, then the surface is illuminated. Otherwise, it’s in the shadow.

Hi, you can do it from geometry nodes but the value will be stored on vertices so you’ll need great definition for great accuracy.

Depends on what you want to do with this data.

Here is an idea about this:

https://github.com/justinac0/raylib-raycaster

However do not pay attention on the pixel plotting part, because this is another technique based on rasterization or rendering.

For a collision based approach, you hit only one point (the middle of the face). When you get a perfect hit it means that the tile is lit (based on light distance etc). When you get a hit but ray gets interrupted first, it means that you have a shadow hit.

I think that it will be feasible to draw this example with blender api and gpu module just to get it rolling. And then expand it to 3D math and 3D meshes.

Thank you all for the suggestions! Hope I will find a way to implement this.