Graphics/RenderSystem: Handle visibility immediatly

This fixes an issue when rendermask/scissor box is updated right after making an entity visible (e.g. widgets)
This commit is contained in:
SirLynix
2023-07-02 14:04:00 +02:00
parent fff4029047
commit 4f3542356d
2 changed files with 63 additions and 112 deletions

View File

@@ -58,7 +58,6 @@ namespace Nz
void RenderSystem::Update(Time /*elapsedTime*/)
{
UpdateObservers();
UpdateVisibility();
UpdateInstances();
for (auto& windowPtr : m_windowSwapchains)
@@ -109,8 +108,6 @@ namespace Nz
m_graphicsEntities.erase(entity);
m_invalidatedGfxWorldNode.erase(graphicsEntity);
m_newlyHiddenGfxEntities.erase(graphicsEntity);
m_newlyVisibleGfxEntities.erase(graphicsEntity);
GraphicsComponent& entityGfx = m_registry.get<GraphicsComponent>(entity);
if (entityGfx.IsVisible())
@@ -142,8 +139,6 @@ namespace Nz
m_lightEntities.erase(entity);
m_invalidatedLightWorldNode.erase(lightEntity);
m_newlyHiddenLightEntities.erase(lightEntity);
m_newlyVisibleLightEntities.erase(lightEntity);
LightComponent& entityLight = m_registry.get<LightComponent>(entity);
if (entityLight.IsVisible())
@@ -221,6 +216,58 @@ namespace Nz
graphicsEntity->skeletonInstanceIndex = NoInstance;
}
void RenderSystem::UpdateGraphicsVisibility(GraphicsEntity* gfxData, GraphicsComponent& gfxComponent, bool isVisible)
{
if (isVisible)
{
for (std::size_t renderableIndex = 0; renderableIndex < GraphicsComponent::MaxRenderableCount; ++renderableIndex)
{
const auto& renderableEntry = gfxComponent.GetRenderableEntry(renderableIndex);
if (!renderableEntry.renderable)
continue;
gfxData->renderableIndices[renderableIndex] = m_pipeline->RegisterRenderable(gfxData->worldInstanceIndex, gfxData->skeletonInstanceIndex, renderableEntry.renderable.get(), renderableEntry.renderMask, gfxComponent.GetScissorBox());
}
}
else
{
for (std::size_t renderableIndex = 0; renderableIndex < GraphicsComponent::MaxRenderableCount; ++renderableIndex)
{
const auto& renderableEntry = gfxComponent.GetRenderableEntry(renderableIndex);
if (!renderableEntry.renderable)
continue;
m_pipeline->UnregisterRenderable(gfxData->renderableIndices[renderableIndex]);
}
}
}
void RenderSystem::UpdateLightVisibility(LightEntity* gfxData, LightComponent& lightComponent, bool isVisible)
{
if (isVisible)
{
for (std::size_t renderableIndex = 0; renderableIndex < LightComponent::MaxLightCount; ++renderableIndex)
{
const auto& lightEntry = lightComponent.GetLightEntry(renderableIndex);
if (!lightEntry.light)
continue;
gfxData->lightIndices[renderableIndex] = m_pipeline->RegisterLight(lightEntry.light.get(), lightEntry.renderMask);
}
}
else
{
for (std::size_t lightIndex = 0; lightIndex < LightComponent::MaxLightCount; ++lightIndex)
{
const auto& lightEntry = lightComponent.GetLightEntry(lightIndex);
if (!lightEntry.light)
continue;
m_pipeline->UnregisterLight(gfxData->lightIndices[lightIndex]);
}
}
}
void RenderSystem::UpdateInstances()
{
for (CameraEntity* cameraEntity : m_invalidatedCameraNode)
@@ -344,23 +391,14 @@ namespace Nz
}
});
graphicsEntity->onVisibilityUpdate.Connect(entityGfx.OnVisibilityUpdate, [this, graphicsEntity](GraphicsComponent* /*gfx*/, bool isVisible)
graphicsEntity->onVisibilityUpdate.Connect(entityGfx.OnVisibilityUpdate, [this, graphicsEntity](GraphicsComponent* gfx, bool isVisible)
{
if (isVisible)
{
m_newlyHiddenGfxEntities.erase(graphicsEntity);
m_newlyVisibleGfxEntities.insert(graphicsEntity);
}
else
{
m_newlyHiddenGfxEntities.insert(graphicsEntity);
m_newlyVisibleGfxEntities.erase(graphicsEntity);
}
UpdateGraphicsVisibility(graphicsEntity, *gfx, isVisible);
});
m_invalidatedGfxWorldNode.insert(graphicsEntity);
if (entityGfx.IsVisible())
m_newlyVisibleGfxEntities.insert(graphicsEntity);
UpdateGraphicsVisibility(graphicsEntity, m_registry.get<GraphicsComponent>(entity), true);
assert(m_graphicsEntities.find(entity) == m_graphicsEntities.end());
m_graphicsEntities.emplace(entity, graphicsEntity);
@@ -402,33 +440,15 @@ namespace Nz
m_pipeline->UnregisterLight(lightEntity->lightIndices[lightIndex]);
});
lightEntity->onVisibilityUpdate.Connect(entityLight.OnVisibilityUpdate, [this, lightEntity](LightComponent* /*light*/, bool isVisible)
lightEntity->onVisibilityUpdate.Connect(entityLight.OnVisibilityUpdate, [this, lightEntity](LightComponent* light, bool isVisible)
{
if (isVisible)
{
m_newlyHiddenLightEntities.erase(lightEntity);
m_newlyVisibleLightEntities.insert(lightEntity);
}
else
{
m_newlyHiddenLightEntities.insert(lightEntity);
m_newlyVisibleLightEntities.erase(lightEntity);
}
UpdateLightVisibility(lightEntity, *light, isVisible);
});
m_invalidatedLightWorldNode.insert(lightEntity);
if (entityLight.IsVisible())
{
for (std::size_t lightIndex = 0; lightIndex < LightComponent::MaxLightCount; ++lightIndex)
{
const auto& lightEntry = entityLight.GetLightEntry(lightIndex);
if (!lightEntry.light)
continue;
lightEntity->lightIndices[lightIndex] = m_pipeline->RegisterLight(lightEntry.light.get(), lightEntry.renderMask);
}
}
UpdateLightVisibility(lightEntity, m_registry.get<LightComponent>(entity), true);
assert(m_lightEntities.find(entity) == m_lightEntities.end());
m_lightEntities.emplace(entity, lightEntity);
@@ -466,73 +486,4 @@ namespace Nz
graphicsEntity->skeletonInstanceIndex = m_pipeline->RegisterSkeleton(std::make_shared<SkeletonInstance>(skeleton));
});
}
void RenderSystem::UpdateVisibility()
{
// Unregister drawable for hidden entities
for (GraphicsEntity* graphicsEntity : m_newlyHiddenGfxEntities)
{
GraphicsComponent& entityGfx = m_registry.get<GraphicsComponent>(graphicsEntity->entity);
for (std::size_t renderableIndex = 0; renderableIndex < GraphicsComponent::MaxRenderableCount; ++renderableIndex)
{
const auto& renderableEntry = entityGfx.GetRenderableEntry(renderableIndex);
if (!renderableEntry.renderable)
continue;
m_pipeline->UnregisterRenderable(graphicsEntity->renderableIndices[renderableIndex]);
}
}
m_newlyHiddenGfxEntities.clear();
// Register drawable for newly visible entities
for (GraphicsEntity* graphicsEntity : m_newlyVisibleGfxEntities)
{
GraphicsComponent& entityGfx = m_registry.get<GraphicsComponent>(graphicsEntity->entity);
for (std::size_t renderableIndex = 0; renderableIndex < GraphicsComponent::MaxRenderableCount; ++renderableIndex)
{
const auto& renderableEntry = entityGfx.GetRenderableEntry(renderableIndex);
if (!renderableEntry.renderable)
continue;
graphicsEntity->renderableIndices[renderableIndex] = m_pipeline->RegisterRenderable(graphicsEntity->worldInstanceIndex, graphicsEntity->skeletonInstanceIndex, renderableEntry.renderable.get(), renderableEntry.renderMask, entityGfx.GetScissorBox());
}
}
m_newlyVisibleGfxEntities.clear();
// Unregister lights for hidden entities
for (LightEntity* lightEntity : m_newlyHiddenLightEntities)
{
LightComponent& entityLights = m_registry.get<LightComponent>(lightEntity->entity);
for (std::size_t lightIndex = 0; lightIndex < LightComponent::MaxLightCount; ++lightIndex)
{
const auto& lightEntry = entityLights.GetLightEntry(lightIndex);
if (!lightEntry.light)
continue;
m_pipeline->UnregisterLight(lightEntity->lightIndices[lightIndex]);
}
}
m_newlyHiddenLightEntities.clear();
// Register lights for newly visible entities
for (LightEntity* lightEntity : m_newlyVisibleLightEntities)
{
LightComponent& entityLights = m_registry.get<LightComponent>(lightEntity->entity);
for (std::size_t renderableIndex = 0; renderableIndex < LightComponent::MaxLightCount; ++renderableIndex)
{
const auto& lightEntry = entityLights.GetLightEntry(renderableIndex);
if (!lightEntry.light)
continue;
lightEntity->lightIndices[renderableIndex] = m_pipeline->RegisterLight(lightEntry.light.get(), lightEntry.renderMask);
}
}
m_newlyVisibleLightEntities.clear();
//FIXME: Handle light visibility
}
}