Shadow rendering glitch when changing light angle

Hi everyone,

I’m encountering a rendering issue with shadows in Panda3D. The shadows generally work fine, but when the light angle changes, I get a brief visual glitch for one frame. It looks as if the shadow map is temporarily incorrect or misaligned before correcting itself on the next frame.

This happens every time the angle changes. The issue disappears immediately after that single incorrect frame.

Here’s an example of the issue, slowed down for clarity:

Before light angle change:

During the transition (glitch visible):

After the angle change (everything back to normal):

Video demonstration: https://youtu.be/rtW8crUTTMI

Debugging thoughts:

• It looks like the shadow map is not updating correctly for that single frame.

• I’m using custom shaders, so maybe something is wrong with how I handle shadow map updates.

• The issue happens exactly when the light angle changes—in the demo here, to visualize the problem, the angle intentionally changes not smoothly, but in fixed steps (every 5 degrees per second).

How I created this test:

To reproduce the problem, I built a simple scene with a grid of slightly rounded cubes and a directional light. The light changes its angle in steps of 5 degrees per second, making the glitch easy to see. The camera stays fixed, and the cubes don’t move.

Possible causes & questions:

• Could it be related to how Panda3D updates shadow maps?

• Is there a way to force the shadow map update before rendering the next frame?

• Maybe there’s an issue with how I handle shadow filtering or depth bias in my shaders?

Does anyone have suggestions on what to check or debug further? Any help would be greatly appreciated!

As per this post, have you tried setting the sort values of your lights to a negative number?

To explain: my current guess is that what we’re seeing there is the shadow-map being rendered after the final render–thus lagging one frame behind that render. As a result, if the shader that renders shadows is using up-to-date information on the light, it would be comparing that information with a shadow-map rendered from a different position, and thus producing odd results.

Setting the sort-values of the lights should–if I’m right–alleviate this by virtue of causing the shadow-map to be rendered before the final render, thus being up-to-date for it.

1 Like

Thanks for the suggestion! I tried:

directional.setSort(-1)

but got:

AttributeError: 'NodePath' object has no attribute 'setSort'

So I also tried:

directional.node().setPriority(-1)

but visually, the effect is still the same—I’m still getting the one-frame lag on the shadow map.

Any ideas on what else I could try?

Hi Miklesz,

I hope your demo-scene activities are doing well!

Note sure it will solve your issue, but the point mentionned in the post pointed out by @Thaumaturge is:

self._light_np.node().set_shadow_caster(True,self._shadow_map_size,self._shadow_map_size,self._index_for_shadow)

Negative index (here self_index_for_shadow) should be put in the set_shadow_caster method (I was not aware of this possibility until rdb mentionned it to me). This is mandatory for 1.11, not sure how it will work for 1.10.X

Happy demos!

2 Likes

It’s the fourth argument to setShadowCaster:

directional.node().setShadowCaster(True, 512, 512, -10)
3 Likes

Thanks for the suggestion! I added the fourth argument with a negative index:

directional.node().setShadowCaster(True, 2048, 2048, -10)

but unfortunately, the effect is still the same. Is there anything else I could check or try?

By the way, I saw 1.11 mentioned—currently, the latest version I’m using is 1.10.15. Has there been an official release of 1.11, or is it still in development?

And regarding demos and the demoscene—yes, I’m working on another project right now! Actually, I forgot to share one of my 2024 achievements. I’ll try to post it in the showcase section soon. :blush:

1 Like

As mentionned, I don’t know if negative indexes are working with 1.10.x (but let’s suppose it does as per rdb’s above answer).

No “official build” and still in dev but you can use a working one (as I use it) - see Index of /downloads/a7f8c57681522dedfb7d24290c98f3b09bed2a07
(full install or a wheel).

Unfortunately, the builds at that link are only for Windows and Linux, and I’m on macOS. :disappointed:

That being said, after looking closely at my renders, I’m starting to think the issue isn’t actually a one-frame delay in shadow rendering. Take a look for yourselves…

Frame BEFORE the light angle changes by 5 degrees:

Everything looks fine.

Frame IMMEDIATELY AFTER the light angle changes:

Only the light angle has changed—nothing else. If it were just a one-frame delay, we’d expect the lighting to stay the same for one more frame. But since both the camera and the object are stationary, there should be only that one-frame delay and nothing more.

Instead, the shadow shifts (which is expected), but we also get severe artifacts, especially on the cubes to the left. This doesn’t look like just a misaligned shadow—it’s a complete mess with the lighting.

One more frame later:

Everything looks correct again. The light angle hasn’t changed this time, but strangely, the shadow on the right has slightly adjusted itself. No more artifacts on the left.

Any ideas what might be happening? It feels like something isn’t rendering correctly just after the light angle update—maybe something isn’t clearing properly or is temporarily in an incorrect state. But after that, everything fixes itself.

To the contrary, what you’ve presented actually increases my feeling that this stems from a one-frame delay.

Note that the lighting produced by a light (in the sense of rendered light-levels, and thus apparent light-direction) is separate from the shadows produced by that light:

  • The former should be, essentially, just a calculation based on the light-node’s lens, position, etc.,
  • The latter, however, actually requires a separate rendering to be made before it can be used.

And it’s that separate rendering in which a one-frame delay occurs: if the rendering occurs after the final render, then said final render will be using out-of-date shadow-data.

However, as the position, lens, etc. of the light don’t require that rendering, they’ll likely be up-to-date, and thus the final render will not be using out-of-date data for those elements.

As such, if you’re seeing a one-frame-delay issue, then I’d expect to see just what you show: the apparent light-position, and the lighting produced by that, should be up-to-date, but the shadows–and only the shadows–should be out-of-date.

The artefacting that you point out is, I suspect, as result of this discrepancy: the final render is using up-to-date data in order to compare a given fragment to the shadow-buffer–but is doing so with an out-of-date shadow-buffer, one rendered from a different orientation.

That said, if I’m right, then I don’t know why the light-priority didn’t fix the problem.

Would it be possible to post a short program (including a simple version of your shader) that demonstrates the problem, so that we can tinker with it?

1 Like

Hi everyone,

I managed to isolate the bug and create a self-contained mini-project that demonstrates the issue. It’s not the most minimal example, since it’s extracted from a much larger project (a few thousand lines of code), so there’s some leftover “junk.” However, it’s small enough to analyze, and it should work as-is.

glitch.zip (258.2 KB)

How the test works:

• The scene continuously renders 8 frames in a loop with a 0.5-second delay between each batch.

• The light angle is set, and 4 frames are rendered.

• Then the light angle changes, and 4 more frames are rendered.

• This cycle repeats indefinitely.

What causes the issue?

I finally identified the cause of the problem, but I don’t know how to fix it. The culprit is FilterManager.

• If I render to a fullscreen quad using a post-processing pass, even a trivial one that just copies the image (texture() → output), the issue appears.

• Instead of 4 frames per light angle , I get one “corrupt” transition frame (with a weird light angle) and then 3 normal ones .

• Then, after the next switch, again 1 corrupted frame + 3 normal frames.

• While the artifact itself isn’t as dramatic in this minimal example, the shadow direction is clearly wrong for that single frame after the light moves.

How to test it yourself?

• Look for the following comment in glitch.py:

# Comment or uncomment the following lines to see the glitch effect

• If you comment out the renderSceneInto call section (removing the post-processing pass), everything starts working perfectly.

• However, I actually need post-processing in my main project, and in reality, I have multiple passes—but even a single one breaks the shadow updates.

What now?

How do I fix this? Any ideas on why FilterManager messes with shadow rendering?

I really want to keep post-processing, but I also need correct shadows.

Here are all the files needed to run the test:

Python script: glitch.py

Shaders: glitch.vert, basic.vert, quad_glitch.frag, triangle.frag, p3d_in.glsl, p3d_uniform.glsl

Model: cube.egg

Texture: diffuse.jpg

Any suggestions on how to work around this? How can I keep FilterManager without breaking shadow rendering?

Thanks in advance!

Ah, that helps! As does your diagnosis that FilterManager is causing the problem! :slight_smile:

Okay, first of all, a solution:

Set the priority of the shadow-casting light to a negative value.

But of course, and as indeed shown by the program you posted, you’ve tried that, and it doesn’t work. I confirm as much.

So set it to an even more negative value! XD;

(Specifically, I tried with the somewhat-ridiculous value of “-1000000”.)

On my end, this causes the problem to go away!

To speculate, what I think is happening is that FilterManager, naturally, wants to render the scene before the final rendering is done, in order that said final rendering be done with a current view of the scene.

To this end, I imagine that it’s somewhere setting the priority of the scene-rendering to a negative value.

As a result, if the priority of the shadow-casting light isn’t set to a sufficiently negative value, it still ends up having a higher priority than the scene, and so its shadow-buffer is still rendered after the scene, and thus we still get a one-frame delay in shadow-rendering!

3 Likes

We got it! :tada: A huge thank you! :raised_hands:

It worked in the main project as well – setting the even more negative priority actually fixed the issue.

I didn’t even think of just pushing the value even further into the negatives ! Brilliant.

What would I do without you and this amazing forum? :smiley: Thanks again! :rocket:

1 Like