I am trying to make a sunrise/sunset effect, but the directional light penetrates the model from the backside. So I need your helps to deal with it.
My system is Fedora 32, master Panda3D, master Simplepbr, master blend2bam, Blender 2.8. Everything else works very well. The model (terrain) you see on this picture is just one single static mesh, with a very basic material and a very basic texture, nothing more. The shadow effect of simplepbr is on, and it works very well. The shadow caster is the directional light (the sun), it works very well because I set up the frustum and the shadow mapping size very carefully.
The only problem is that, when the sun going below the horizon, it slightly penetrates from the backside of the terrain model, as you can see in the picture. I have tried something but most of them doesn’t help to fix the issue:
Solidify the terrain model – Doesn’t help.
Made a plane under the terrain to block the sun – Doesn’t help.
terrain.set_two_sides(True) – Doesn’t help
sun.set_color(0) after sunset – It helps a little, but I don’t like this way, because it also disables the beautiful sunset twilight effect when the sun just slightly below the horizon. And also, sometime if my character (camera) stands beside a high mountain, the directional light penetrates the mountain too, even if the directional light’s angle is 30 degrees from the horizon like 10 o’clock in the morning. I certainly do not want to sun.set_color(0) at daytime.
Looks like it is all about the metal roughness number of the model. If I turn the metal roughness to a higher number, it looks much better. But I don’t think this should be a good solution too, because maybe sometime I need a shiny terrain surface like an iced lake.
So I really need your help and advice about how I could set up my codes to avoid or reduce this problem. Thank you very much again.
I thing your problem is that your shadow map does not cover your scene properly. Could you check, using bufferViewer or modifying the SimplePBR shader to output only the shadow value, that the area where you see the artefact is properly covered by the shadows ? (It’s not clear from your screenshot that there is actually a shadow over)
SimplePBR, like several PBR shaders I’ve looked at, does not clamp the output pixel color to (0, 0, 0) when N dot L < 0 (i.e. when the source light direction is below the surface) but instead clamp the value of the vector parameters to 0 (e.g. NdotL, VdotL, …). SimplePBR goes a bit beyond and clamp the values not to 0 but to 0.001, and also takes the abs value of NdotV, which I think could be the root cause of what you see (Though you should not see it anyway due to the surface self-shadowing).
From this video, I think we can actually see that the shadow is working, but I don’t know if it really properly covers this area. (It does not cover a big area though because I set the frustum smaller.) Can you please take a look?
Ah, it looks like you’ve got shadow acne on the terrain; so some parts get no longer covered by the shadow and the specular artefacts become visible. You should apply a bias or use backface culling to solve it (or at least diminish the visual impact). Note that to see the problem (and solve it), it’s better to use a uniform bright color for the mesh (for example a saturated red) and disable all other light sources. Even better, use a debug shader to only output the shadow value.
(Btw, the specular artefacts look quite bright to me, something I would see with a more classical Phong specular. Maybe check also that simplepbr is applied on the terrain too)
Panda does indeed enable reverse culling already on shadow cameras. However, this is nullified if your model is double-sided. You should make sure your terrain is single-sided and does not use the solidifier modifier.
You should also make sure that the near/far clips of the camera are as tight as you can make them. Also see:
Yes, my terrain is single-sided and has no solidifier. I cannot see it if I put the camera underground.
I think when you said the “camera”, you mean the light’s camera right? My scene and project design are very different from your example, but I already try some similar ways to reduce the near/far clips.
I am now thinking about another way. Is it possible to cast a ray like the bullet’s world.ray_test_closest() to detect the backside of the terrain? Be like
If I remember correctly, you can use setDepthOffset(x) on your model to apply a bias, try -2 as a start.
I guess that’s only a convoluted way to set the sun colour when the angle between the normal and the light direction is greater than 90°
If the shadow bias or frustum adjustment does not work, maybe it’s easier to modify simplepbr and add a check on ndotl > 0 in the fragment shader ?
After trying all of these ways: set depth offset, adjusted the frustum to a more plausible size, set_color based on the sunset time, it finally became slightly better. The penetrated specular artefacts is not very obvious now, but sometime still can see a little bit.
So maybe my next step will be taking a look at the simplepbr.
Hi, I think it still has some issues. I think I should not be able to see anything at the frontside if the directional light is casting from the backside of an object, even if I turn off the shadow. However, I still can see the specular artifact even if there is no shadow at all.
In this video, I turned off all the shadow, removed the ambient light, removed the texture from the terrain, only plain green color. As you can see, the directional light lit up the house as what we expect, the front face of the house the bright, and the back face is dark. However, for the ground, although the surface is dark, we still can see the specular artifacts.
I don’t think there is anything to do with the shadow anymore at this time, so how can I solve or at least reduce this issue?
Any advices and helps are so much appreciated! Thanks again!
That’s what i thought at first, but in my test the light direction is actually coming from under the surface, the dot product of the surface normal and the light direction is negative, so there shouldn’t be any lighting at all on the surface.
The current clamp value may be small, but with smooth surface it still gives some light reflection