diff --git a/filament/src/Scene.cpp b/filament/src/Scene.cpp index a9337bc3f3..daa7149b5b 100644 --- a/filament/src/Scene.cpp +++ b/filament/src/Scene.cpp @@ -47,7 +47,7 @@ FScene::FScene(FEngine& engine) : FScene::~FScene() noexcept = default; -void FScene::prepare(const mat4f& worldOriginTransform) { +void FScene::prepare(const mat4f& worldOriginTransform, bool shadowReceiversAreCasters) noexcept { // TODO: can we skip this in most cases? Since we rely on indices staying the same, // we could only skip, if nothing changed in the RCM. @@ -119,12 +119,17 @@ void FScene::prepare(const mat4f& worldOriginTransform) { // compute the world AABB so we can perform culling const Box worldAABB = rigidTransform(rcm.getAABB(ri), worldTransform); + auto visibility = rcm.getVisibility(ri); + if (shadowReceiversAreCasters && visibility.receiveShadows) { + visibility.castShadows = true; + } + // we know there is enough space in the array sceneData.push_back_unsafe( ri, // RENDERABLE_INSTANCE worldTransform, // WORLD_TRANSFORM reversedWindingOrder, // REVERSED_WINDING_ORDER - rcm.getVisibility(ri), // VISIBILITY_STATE + visibility, // VISIBILITY_STATE rcm.getBonesUbh(ri), // BONES_UBH worldAABB.center, // WORLD_AABB_CENTER 0, // VISIBLE_MASK diff --git a/filament/src/View.cpp b/filament/src/View.cpp index cad6d0e546..95d84bbd0a 100644 --- a/filament/src/View.cpp +++ b/filament/src/View.cpp @@ -414,7 +414,7 @@ void FView::prepare(FEngine& engine, backend::DriverApi& driver, ArenaScope& are * Gather all information needed to render this scene. Apply the world origin to all * objects in the scene. */ - scene->prepare(worldOriginScene); + scene->prepare(worldOriginScene, hasVsm()); /* * Light culling: runs in parallel with Renderable culling (below) @@ -594,20 +594,17 @@ void FView::computeVisibilityMasks( // // It is written without if statements to avoid branches, which allows it to be vectorized 16x. - const bool visRenderables = (!v.culling || (mask & VISIBLE_RENDERABLE)) && inVisibleLayer; - const bool vvsmRenderShadow = hasVsm && v.receiveShadows; - const bool visShadowParticipant = v.castShadows || vvsmRenderShadow; - const bool visShadowRenderable = - (!v.culling || (mask & VISIBLE_DIR_SHADOW_RENDERABLE)) && inVisibleLayer && visShadowParticipant; + const bool visRenderables = (!v.culling || (mask & VISIBLE_RENDERABLE)) && inVisibleLayer; + const bool visShadowParticipant = v.castShadows; + const bool visShadowRenderable = (!v.culling || (mask & VISIBLE_DIR_SHADOW_RENDERABLE)) + && inVisibleLayer && visShadowParticipant; visibleMask[i] = Culler::result_type(visRenderables) | Culler::result_type(visShadowRenderable << 1u); // this loop gets fully unrolled for (size_t j = 0; j < CONFIG_MAX_SHADOW_CASTING_SPOTS; ++j) { - const bool vvsmSpotRenderShadow = hasVsm && v.receiveShadows; - const bool visSpotShadowParticipant = v.castShadows || vvsmSpotRenderShadow; const bool visSpotShadowRenderable = - (!v.culling || (mask & VISIBLE_SPOT_SHADOW_RENDERABLE_N(j))) && - inVisibleLayer && visSpotShadowParticipant; + (!v.culling || (mask & VISIBLE_SPOT_SHADOW_RENDERABLE_N(j))) && + inVisibleLayer && visShadowParticipant; visibleMask[i] |= Culler::result_type(visSpotShadowRenderable << VISIBLE_SPOT_SHADOW_RENDERABLE_N_BIT(j)); } diff --git a/filament/src/details/Scene.h b/filament/src/details/Scene.h index 26dcd13610..a490973a95 100644 --- a/filament/src/details/Scene.h +++ b/filament/src/details/Scene.h @@ -84,8 +84,9 @@ public: ~FScene() noexcept; void terminate(FEngine& engine); - void prepare(const math::mat4f& worldOriginTransform); - void prepareDynamicLights(const CameraInfo& camera, ArenaScope& arena, backend::Handle lightUbh) noexcept; + void prepare(const math::mat4f& worldOriginTransform, bool shadowReceiversAreCasters) noexcept; + void prepareDynamicLights(const CameraInfo& camera, ArenaScope& arena, + backend::Handle lightUbh) noexcept; filament::backend::Handle getRenderableUBO() const noexcept {