LOD improvements (#5038)
* Quick cull invisible LOD nodes * Reduce dynamic cast * Fix for Vulkan Maintainer's comment: Helps only in select tracks and more in already fast frames than in the more problematic slow frames, but an improvement nonetheless.
This commit is contained in:
parent
6cf094ab78
commit
8577408cec
@ -145,42 +145,52 @@ void DrawCalls::parseSceneManager(core::array<scene::ISceneNode*> &List,
|
||||
{
|
||||
for (unsigned i = 0; i < List.size(); ++i)
|
||||
{
|
||||
if (LODNode *node = dynamic_cast<LODNode *>(List[i]))
|
||||
{
|
||||
node->updateVisibility();
|
||||
}
|
||||
List[i]->updateAbsolutePosition();
|
||||
if (!List[i]->isVisible())
|
||||
continue;
|
||||
|
||||
if (STKParticle *node = dynamic_cast<STKParticle*>(List[i]))
|
||||
if (List[i]->getType() == ESNT_LOD_NODE)
|
||||
{
|
||||
LODNode *node = static_cast<LODNode *>(List[i]);
|
||||
|
||||
core::array<scene::ISceneNode*> child;
|
||||
if (node->getLevel() >= 0)
|
||||
child.push_back(node->getAllNodes()[node->getLevel()]);
|
||||
for (int i = 0; i < node->getChildren().size(); i++)
|
||||
{
|
||||
if (node->getNodesSet().find(node->getChildren()[i]) == node->getNodesSet().end())
|
||||
child.push_back(node->getChildren()[i]);
|
||||
}
|
||||
parseSceneManager(child, cam);
|
||||
continue;
|
||||
}
|
||||
else if (List[i]->getType() == ESNT_ANIMATED_MESH)
|
||||
{
|
||||
SP::SPMeshNode* node = static_cast<SP::SPMeshNode*>(List[i]);
|
||||
SP::addObject(node);
|
||||
}
|
||||
else if (STKParticle *node = dynamic_cast<STKParticle*>(List[i]))
|
||||
{
|
||||
node->updateAbsolutePosition();
|
||||
if (!isCulledPrecise(cam, List[i], irr_driver->getBoundingBoxesViz()))
|
||||
CPUParticleManager::getInstance()->addParticleNode(node);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (scene::IBillboardSceneNode *node =
|
||||
else if (scene::IBillboardSceneNode *node =
|
||||
dynamic_cast<scene::IBillboardSceneNode*>(List[i]))
|
||||
{
|
||||
node->updateAbsolutePosition();
|
||||
if (!isCulledPrecise(cam, List[i]))
|
||||
CPUParticleManager::getInstance()->addBillboardNode(node);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (STKTextBillboard *tb =
|
||||
else if (STKTextBillboard *tb =
|
||||
dynamic_cast<STKTextBillboard*>(List[i]))
|
||||
{
|
||||
node->updateAbsolutePosition();
|
||||
if (!isCulledPrecise(cam, List[i], irr_driver->getBoundingBoxesViz()))
|
||||
TextBillboardDrawer::addTextBillboard(tb);
|
||||
continue;
|
||||
}
|
||||
|
||||
SP::SPMeshNode* node = dynamic_cast<SP::SPMeshNode*>(List[i]);
|
||||
if (node)
|
||||
{
|
||||
SP::addObject(node);
|
||||
}
|
||||
parseSceneManager(List[i]->getChildren(), cam);
|
||||
}
|
||||
}
|
||||
|
@ -49,13 +49,8 @@ LODNode::LODNode(std::string group_name, scene::ISceneNode* parent,
|
||||
|
||||
m_forced_lod = -1;
|
||||
m_area = 0;
|
||||
#ifndef SERVER_ONLY
|
||||
if (!CVS->isGLSL())
|
||||
{
|
||||
m_current_level.reset(new int);
|
||||
*m_current_level = -1;
|
||||
}
|
||||
#endif
|
||||
m_current_level = -1;
|
||||
m_current_level_dirty = true;
|
||||
}
|
||||
|
||||
LODNode::~LODNode()
|
||||
@ -76,9 +71,13 @@ int LODNode::getLevel()
|
||||
return -1;
|
||||
|
||||
// If a level is forced, use it
|
||||
if(m_forced_lod>-1)
|
||||
if (m_forced_lod >- 1)
|
||||
return m_forced_lod;
|
||||
|
||||
if (!m_current_level_dirty)
|
||||
return m_current_level;
|
||||
m_current_level_dirty = false;
|
||||
|
||||
Camera* camera = Camera::getActiveCamera();
|
||||
if (camera == NULL)
|
||||
return (int)m_detail.size() - 1;
|
||||
@ -90,9 +89,12 @@ int LODNode::getLevel()
|
||||
for (unsigned int n=0; n<m_detail.size(); n++)
|
||||
{
|
||||
if (dist < m_detail[n])
|
||||
{
|
||||
m_current_level = n;
|
||||
return n;
|
||||
}
|
||||
|
||||
}
|
||||
m_current_level = -1;
|
||||
return -1;
|
||||
} // getLevel
|
||||
|
||||
@ -108,6 +110,8 @@ void LODNode::forceLevelOfDetail(int n)
|
||||
// ----------------------------------------------------------------------------
|
||||
void LODNode::OnAnimate(u32 timeMs)
|
||||
{
|
||||
updateVisibility();
|
||||
|
||||
if (isVisible() && m_nodes.size() > 0)
|
||||
{
|
||||
// update absolute position
|
||||
@ -126,9 +130,8 @@ void LODNode::OnAnimate(u32 timeMs)
|
||||
#endif
|
||||
{
|
||||
int level = getLevel();
|
||||
*m_current_level = level;
|
||||
// Assume all the scene node have the same bouding box
|
||||
if(level>=0)
|
||||
if(level >= 0)
|
||||
{
|
||||
m_nodes[level]->setVisible(true);
|
||||
m_nodes[level]->OnAnimate(timeMs);
|
||||
@ -154,29 +157,22 @@ void LODNode::OnAnimate(u32 timeMs)
|
||||
}
|
||||
}
|
||||
|
||||
void LODNode::updateVisibility(bool* shown)
|
||||
void LODNode::updateVisibility()
|
||||
{
|
||||
if (!isVisible()) return;
|
||||
if (m_nodes.size() == 0) return;
|
||||
|
||||
unsigned int level = 0;
|
||||
if (m_current_level)
|
||||
level = *m_current_level;
|
||||
else
|
||||
level = getLevel();
|
||||
m_current_level_dirty = true;
|
||||
unsigned int level = getLevel();
|
||||
|
||||
for (size_t i = 0; i < m_nodes.size(); i++)
|
||||
{
|
||||
m_nodes[i]->setVisible(i == level);
|
||||
if (i == level && shown != NULL)
|
||||
*shown = (i > 0);
|
||||
}
|
||||
}
|
||||
|
||||
void LODNode::OnRegisterSceneNode()
|
||||
{
|
||||
bool shown = false;
|
||||
updateVisibility(&shown);
|
||||
|
||||
#ifndef SERVER_ONLY
|
||||
if (CVS->isGLSL())
|
||||
{
|
||||
@ -184,14 +180,20 @@ void LODNode::OnRegisterSceneNode()
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef SERVER_ONLY
|
||||
if (!CVS->isGLSL())
|
||||
if (isVisible() && m_nodes.size() > 0)
|
||||
{
|
||||
for (unsigned i = 0; i < Children.size(); ++i)
|
||||
Children[i]->updateAbsolutePosition();
|
||||
int level = getLevel();
|
||||
|
||||
if (level >= 0)
|
||||
{
|
||||
m_nodes[level]->OnRegisterSceneNode();
|
||||
}
|
||||
for (int i = 0; i < Children.size(); i++)
|
||||
{
|
||||
if (m_nodes_set.find(Children[i]) == m_nodes_set.end())
|
||||
Children[i]->OnRegisterSceneNode();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
scene::ISceneNode::OnRegisterSceneNode();
|
||||
}
|
||||
|
||||
/* Each model with LoD has specific distances beyond which it is rendered at a lower
|
||||
|
@ -63,7 +63,8 @@ private:
|
||||
* m_forced_lod is >=0, only this level is be used. */
|
||||
int m_forced_lod;
|
||||
|
||||
std::unique_ptr<int> m_current_level;
|
||||
int m_current_level;
|
||||
bool m_current_level_dirty;
|
||||
|
||||
// Area of the bounding box (for autoLOD computation)
|
||||
float m_area;
|
||||
@ -79,7 +80,7 @@ public:
|
||||
|
||||
int getLevel();
|
||||
|
||||
void updateVisibility(bool* shown = NULL);
|
||||
void updateVisibility();
|
||||
|
||||
/*
|
||||
//! Returns a reference to the current relative transformation matrix.
|
||||
@ -115,6 +116,7 @@ public:
|
||||
}
|
||||
|
||||
std::vector<scene::ISceneNode*>& getAllNodes() { return m_nodes; }
|
||||
std::set<scene::ISceneNode*>& getNodesSet() { return m_nodes_set; }
|
||||
|
||||
//! OnAnimate() is called just before rendering the whole scene.
|
||||
/** This method will be called once per frame, independent
|
||||
|
Loading…
Reference in New Issue
Block a user