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.
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.
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.
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.