Best practice for lighting in a cave or dark house?

Hi All,

I am making a seamless scene that includes some caves and dark houses. When the player is outside, they can see the outer surfaces with directional light (sunlight) and ambient light, then when the player is in the caves or houses, they should not be able to see same effect directional light and ambient light as outside. For example, the inner walls of the caves or the house should be darker, maybe some weaker lights such as a torch would be in it to light it up slightly.

My idea is that, I would duplicate the model, and scale it down a just little bit, then rename it to something like “inner_layer”. Then I can do:

Do you think my idea is okay? Or do you have a better practice for this? Or does Panda3D (I use simplepbr too) have any built-in stuffs to do this?

Thank you for your help!


I doubt that there is a single “best practice” for this: what works for one game might be ineffective in another.

As to your idea, something like that could work, I daresay; indeed, I’m doing something similar in a project of my own.

However, it does come with a caveat: at the places where the two “lighting regions” meet there may be a rather obvious discontinuity in the lighting: a sharp divide between “outside lighting” and “inside lighting”. With some care in the level design and a bit of lighting trickery you might be able to cover such borders, but it’s something to be aware of.

Another approach might be to use shadow-mapping in your scene, and thus have the shadows “naturally” darken such interior places. This comes, of course, with its own caveats (shadow-mapping artefacts and performance implications, for example).

I am not sure that scaling down and duplicating the model is the right approach. It would be better to have modelled the interior of these objects in the modelling program, with enough thickness between the outer and inner surfaces. You can, if necessary, use the Solidify modifier in Blender to turn a single infinitely-thin surface into a thick double-sided surface.

If you use shadow casters on the directional light, it is automatically going to be dark inside the cave. This does not apply to the ambient light, so you will need to disable the normal ambient light inside the cave as you have indicated. Inside the cave, you can simulate the effect of the light streaming into the cave using a spot light with wide enough cone at the cave entrance, and an inverse square attenuation to have this diminish as you go deeper into the cave.

It would probably be a good optimization to disable the scene shadow caster entirely when you have moved into the cave.

For a most realistic effect, you should employ HDR lighting techniques (which I think simplepbr supports). This means that the lights outside the cave are very bright compared to the lights inside the cave (to the point where the cave looks very dark seen from the outside), and you would adjust the exposure when moving into the cave (which will make anything outside the cave look very bright). Don’t be afraid to make the lights outside many thousands of times brighter than inside the cave; this is also true in real-life, and our eyes adjust the exposure to make up for the difference.

1 Like

Hi rdb,

Thank you for your reply.

The idea of exposure adjusting for the player camera sounds very good. I will take a look at it. I definitely would like to employ HDR if the simplepbr supports. But currently I am still not very familiar with simplepbr. If you or Moguri can provide me with some links of resources or documents, that would be highly appreciated!


I do not understand about this quite well, so I need further clarifying. I actually use solidify modifier in Blender, so my models (the wall of the caves) are thick. However, if I only have one model (No duplicating as you said), how do I darken the ambient light? Do you mean something like that I set an event trigger on the entrance of the cave, and then when I enter the cave, it darken the ambient light? Or do you mean something else?

Thanks again!

Ah, perhaps I misunderstood? I thought that you were talking about duplicating and scaling down your house model to create the interior walls of the house.

If you want your cave to have a separate ambient light applied, all you should need to do is make the cave a separate mesh in Blender, and select it with find() in Panda3D. Though, this may leave visible seams as has been pointed out earlier.

simplepbr has an exposure argument. This is a linear scale on the luminance of the scene that you would increase when entering the cave, and decrease when leaving it. There is no auto-exposure implemented at the moment, so you would need to manually tweak it to find the right amount of exposure for your lighting conditions.

Sorry my bad. You are not misunderstanding, I did duplicating and scaling before. But I saw you said duplicating may not be a good idea, so I just changed to the way of solidify modifier, then I added shadow mapping on it. But I don’t know if I am doing right.

After I adding the render.setShaderAuto(), all my textures in the scene (all, everything) are completely black. I think it causes the simplepbr crashed, and the blend2bam couldn’t display the textures correctly.

Please let me know if it is a bug of blend2bam and simplepbr, so I would report an issue to the Moguri’s git. Or just I did something wrong?

Calling set_shader_auto() on render is going to override the shaders from simplepbr, but I think the tonemapping will still run. In other words, things aren’t going to look right. simplepbr supports Panda’s shadows, you just have to set enable_shadows=True when initializing simplepbr. However, do note that if you enable shadows for simplepbr and use spotlight or directional light casters, you can no longer use point lights (shadow casting or otherwise). I am working on fixing this, but this is why shadows are disabled by default for simplepbr.

Hi Moguri,

Thank you for your reply! But I am still a little confused and need further guidance.

Do you mean that, I just need to do:
pipeline = simplepbr.init()
pipeline.enable_shadows = True

but NOT calling render.setShaderAuto()?

If it is what you mean, I have tried it, but I cannot see any shadows.

Currently I only have one directional light as a shadow caster. There is no point light in the scene.

You should rather use simplepbr.init(enable_shadows=True).

Keep in mind setting up a directional light with shadows requires extra effort. See:

Hi rdb,

I tried your example; it works well. However, I decided to use your code with simplepbr. I enabled it using simplepbr.init(enable_shadows=True), then I disable your own shader. It doesn’t work. The shadows just don’t show up.

Hello rbd and Moguri,

Thank you for your help, and I finally get the shadows with stable Panda3d 1.10.6, and the simplepbr from the latest git master.

However, shadows do not show up on the Panda3d from the latest the git master built.


I believe there is a bug in master around culling out shadow casters. Could you try setting the view-frustum-cull PRC variable to false and seeing if the shadows come back?

In master, the shadows come back after setting view-frustum-cull PRC variable to false.

So hopefully this bug will be fixed soon.