Closed nimrod-gileadi closed 3 months ago
@pixelflinger isn't that a change you made recently?
I feel like I fixed this recently. Can you confirm this is with a recent version?
I can confirm this is happening with the latest code in the main branch (and google3 HEAD).
To demonstrate, I edited the loop here to be:
auto const& passList = prepareShadowPass.getData().passList;
int i = 0;
static int render_count = 0;
render_count++;
for (auto const& entry: passList) {
if (render_count <= 3) {
std::cerr << "Render " << render_count << ", pass " << i
<< "(shadowType = " << (int) entry.shadowMap->getShadowType()
<< ") visibleShadows="
<< entry.shadowMap->hasVisibleShadows()
<< "\n";
}
i++;
if (!entry.shadowMap->hasVisibleShadows()) {
continue;
}
When I run the lightbulb sample (with ./samples/lightbulb -m -d -p -i ../../third_party/environments/lightroom_14b.hdr ../../assets/models/monkey/monkey.obj
), I get the following logs, showing that on the first frame, the spot lights don't cast a shadow, but on the second and third frame they do:
Render 1, pass 0(shadowType = 0) visibleShadows=1
Render 1, pass 1(shadowType = 1) visibleShadows=0
Render 1, pass 2(shadowType = 1) visibleShadows=0
Render 2, pass 0(shadowType = 0) visibleShadows=1
Render 2, pass 1(shadowType = 1) visibleShadows=1
Render 2, pass 2(shadowType = 1) visibleShadows=1
Render 3, pass 0(shadowType = 0) visibleShadows=1
Render 3, pass 1(shadowType = 1) visibleShadows=1
Render 3, pass 2(shadowType = 1) visibleShadows=1
In the original bug I mentioned point lights specifically, but this seems to apply to spot lights too.
Or more visually, edit FilamentApp.cpp to stop rendering after the first 1 or 2 frames: https://github.com/google/filament/blob/a068143953d9f5feb7a79b5318898ccbced30080/libs/filamentapp/src/FilamentApp.cpp#L458
to:
static int render_count = 0;
constexpr int kFramesToRender = 1;
render_count++;
if (render_count <= kFramesToRender && renderer->beginFrame(window->getSwapChain())) {
First render vs second render (note the effect of the red FOCUSED_SPOT
light):
Okay, I'm able to reproduce and understand the problem. As things are set-up right now, the shadow visible/not visible status of point/spot lights is delayed by one frame. This is because it is set in the "execute" closure of AddPass(), but consumed in the "setup" closure of the next addPass(), so it's not ready yet at that point.
I have a piece of code which sets up a scene with some POINT light sources, and renders one frame only. The point lights are meant to cast shadows but they don't. If I render two frames, instead, I get shadows.
I figured out the reason. In this piece of code, there is filtering based on
shadowMap->hasVisibleShadows()
: https://github.com/google/filament/blob/90d90094dc9eed59b7e75969b8128857217cea2c/filament/src/ShadowMapManager.cpp#L388However, the value of
shadowMap->hasVisibleShadows()
is not available until the call toupdatePoint
here, which is part of the Execute phase of prepareShadowPass: https://github.com/google/filament/blob/90d90094dc9eed59b7e75969b8128857217cea2c/filament/src/ShadowMapManager.cpp#L897Commenting out the if statement makes the shadows appear on the first frame. ShadowMap instances are cached between render calls, which is why on the second frame I get shadows.
Desktop (please complete the following information):
Additional context
I'm working in the Google code base and can share internal code to reproduce. I haven't tried building externally.