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:
parent
fff4029047
commit
4f3542356d
|
|
@ -52,6 +52,9 @@ namespace Nz
|
||||||
RenderSystem& operator=(RenderSystem&&) = delete;
|
RenderSystem& operator=(RenderSystem&&) = delete;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct GraphicsEntity;
|
||||||
|
struct LightEntity;
|
||||||
|
|
||||||
void OnCameraDestroy(entt::registry& registry, entt::entity entity);
|
void OnCameraDestroy(entt::registry& registry, entt::entity entity);
|
||||||
void OnDisabledConstructed(entt::registry& registry, entt::entity entity);
|
void OnDisabledConstructed(entt::registry& registry, entt::entity entity);
|
||||||
void OnGraphicsDestroy(entt::registry& registry, entt::entity entity);
|
void OnGraphicsDestroy(entt::registry& registry, entt::entity entity);
|
||||||
|
|
@ -59,9 +62,10 @@ namespace Nz
|
||||||
void OnNodeDestroy(entt::registry& registry, entt::entity entity);
|
void OnNodeDestroy(entt::registry& registry, entt::entity entity);
|
||||||
void OnSharedSkeletonDestroy(entt::registry& registry, entt::entity entity);
|
void OnSharedSkeletonDestroy(entt::registry& registry, entt::entity entity);
|
||||||
void OnSkeletonDestroy(entt::registry& registry, entt::entity entity);
|
void OnSkeletonDestroy(entt::registry& registry, entt::entity entity);
|
||||||
|
void UpdateGraphicsVisibility(GraphicsEntity* gfxData, GraphicsComponent& gfxComponent, bool isVisible);
|
||||||
|
void UpdateLightVisibility(LightEntity* gfxData, LightComponent& lightComponent, bool isVisible);
|
||||||
void UpdateInstances();
|
void UpdateInstances();
|
||||||
void UpdateObservers();
|
void UpdateObservers();
|
||||||
void UpdateVisibility();
|
|
||||||
|
|
||||||
static constexpr std::size_t NoInstance = std::numeric_limits<std::size_t>::max();
|
static constexpr std::size_t NoInstance = std::numeric_limits<std::size_t>::max();
|
||||||
|
|
||||||
|
|
@ -132,10 +136,6 @@ namespace Nz
|
||||||
std::unordered_map<entt::entity, GraphicsEntity*> m_graphicsEntities;
|
std::unordered_map<entt::entity, GraphicsEntity*> m_graphicsEntities;
|
||||||
std::unordered_map<entt::entity, LightEntity*> m_lightEntities;
|
std::unordered_map<entt::entity, LightEntity*> m_lightEntities;
|
||||||
std::unordered_map<Skeleton*, SharedSkeleton> m_sharedSkeletonInstances;
|
std::unordered_map<Skeleton*, SharedSkeleton> m_sharedSkeletonInstances;
|
||||||
std::unordered_set<GraphicsEntity*> m_newlyHiddenGfxEntities;
|
|
||||||
std::unordered_set<GraphicsEntity*> m_newlyVisibleGfxEntities;
|
|
||||||
std::unordered_set<LightEntity*> m_newlyHiddenLightEntities;
|
|
||||||
std::unordered_set<LightEntity*> m_newlyVisibleLightEntities;
|
|
||||||
std::vector<std::unique_ptr<WindowSwapchain>> m_windowSwapchains;
|
std::vector<std::unique_ptr<WindowSwapchain>> m_windowSwapchains;
|
||||||
ElementRendererRegistry m_elementRegistry;
|
ElementRendererRegistry m_elementRegistry;
|
||||||
MemoryPool<CameraEntity> m_cameraEntityPool;
|
MemoryPool<CameraEntity> m_cameraEntityPool;
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,6 @@ namespace Nz
|
||||||
void RenderSystem::Update(Time /*elapsedTime*/)
|
void RenderSystem::Update(Time /*elapsedTime*/)
|
||||||
{
|
{
|
||||||
UpdateObservers();
|
UpdateObservers();
|
||||||
UpdateVisibility();
|
|
||||||
UpdateInstances();
|
UpdateInstances();
|
||||||
|
|
||||||
for (auto& windowPtr : m_windowSwapchains)
|
for (auto& windowPtr : m_windowSwapchains)
|
||||||
|
|
@ -109,8 +108,6 @@ namespace Nz
|
||||||
|
|
||||||
m_graphicsEntities.erase(entity);
|
m_graphicsEntities.erase(entity);
|
||||||
m_invalidatedGfxWorldNode.erase(graphicsEntity);
|
m_invalidatedGfxWorldNode.erase(graphicsEntity);
|
||||||
m_newlyHiddenGfxEntities.erase(graphicsEntity);
|
|
||||||
m_newlyVisibleGfxEntities.erase(graphicsEntity);
|
|
||||||
|
|
||||||
GraphicsComponent& entityGfx = m_registry.get<GraphicsComponent>(entity);
|
GraphicsComponent& entityGfx = m_registry.get<GraphicsComponent>(entity);
|
||||||
if (entityGfx.IsVisible())
|
if (entityGfx.IsVisible())
|
||||||
|
|
@ -142,8 +139,6 @@ namespace Nz
|
||||||
|
|
||||||
m_lightEntities.erase(entity);
|
m_lightEntities.erase(entity);
|
||||||
m_invalidatedLightWorldNode.erase(lightEntity);
|
m_invalidatedLightWorldNode.erase(lightEntity);
|
||||||
m_newlyHiddenLightEntities.erase(lightEntity);
|
|
||||||
m_newlyVisibleLightEntities.erase(lightEntity);
|
|
||||||
|
|
||||||
LightComponent& entityLight = m_registry.get<LightComponent>(entity);
|
LightComponent& entityLight = m_registry.get<LightComponent>(entity);
|
||||||
if (entityLight.IsVisible())
|
if (entityLight.IsVisible())
|
||||||
|
|
@ -221,6 +216,58 @@ namespace Nz
|
||||||
graphicsEntity->skeletonInstanceIndex = NoInstance;
|
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()
|
void RenderSystem::UpdateInstances()
|
||||||
{
|
{
|
||||||
for (CameraEntity* cameraEntity : m_invalidatedCameraNode)
|
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)
|
UpdateGraphicsVisibility(graphicsEntity, *gfx, isVisible);
|
||||||
{
|
|
||||||
m_newlyHiddenGfxEntities.erase(graphicsEntity);
|
|
||||||
m_newlyVisibleGfxEntities.insert(graphicsEntity);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_newlyHiddenGfxEntities.insert(graphicsEntity);
|
|
||||||
m_newlyVisibleGfxEntities.erase(graphicsEntity);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
m_invalidatedGfxWorldNode.insert(graphicsEntity);
|
m_invalidatedGfxWorldNode.insert(graphicsEntity);
|
||||||
|
|
||||||
if (entityGfx.IsVisible())
|
if (entityGfx.IsVisible())
|
||||||
m_newlyVisibleGfxEntities.insert(graphicsEntity);
|
UpdateGraphicsVisibility(graphicsEntity, m_registry.get<GraphicsComponent>(entity), true);
|
||||||
|
|
||||||
assert(m_graphicsEntities.find(entity) == m_graphicsEntities.end());
|
assert(m_graphicsEntities.find(entity) == m_graphicsEntities.end());
|
||||||
m_graphicsEntities.emplace(entity, graphicsEntity);
|
m_graphicsEntities.emplace(entity, graphicsEntity);
|
||||||
|
|
@ -402,33 +440,15 @@ namespace Nz
|
||||||
m_pipeline->UnregisterLight(lightEntity->lightIndices[lightIndex]);
|
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)
|
UpdateLightVisibility(lightEntity, *light, isVisible);
|
||||||
{
|
|
||||||
m_newlyHiddenLightEntities.erase(lightEntity);
|
|
||||||
m_newlyVisibleLightEntities.insert(lightEntity);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_newlyHiddenLightEntities.insert(lightEntity);
|
|
||||||
m_newlyVisibleLightEntities.erase(lightEntity);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
m_invalidatedLightWorldNode.insert(lightEntity);
|
m_invalidatedLightWorldNode.insert(lightEntity);
|
||||||
|
|
||||||
if (entityLight.IsVisible())
|
if (entityLight.IsVisible())
|
||||||
{
|
UpdateLightVisibility(lightEntity, m_registry.get<LightComponent>(entity), true);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(m_lightEntities.find(entity) == m_lightEntities.end());
|
assert(m_lightEntities.find(entity) == m_lightEntities.end());
|
||||||
m_lightEntities.emplace(entity, lightEntity);
|
m_lightEntities.emplace(entity, lightEntity);
|
||||||
|
|
@ -466,73 +486,4 @@ namespace Nz
|
||||||
graphicsEntity->skeletonInstanceIndex = m_pipeline->RegisterSkeleton(std::make_shared<SkeletonInstance>(skeleton));
|
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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue