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)
|
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())
|
if (!List[i]->isVisible())
|
||||||
continue;
|
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()))
|
if (!isCulledPrecise(cam, List[i], irr_driver->getBoundingBoxesViz()))
|
||||||
CPUParticleManager::getInstance()->addParticleNode(node);
|
CPUParticleManager::getInstance()->addParticleNode(node);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
else if (scene::IBillboardSceneNode *node =
|
||||||
if (scene::IBillboardSceneNode *node =
|
|
||||||
dynamic_cast<scene::IBillboardSceneNode*>(List[i]))
|
dynamic_cast<scene::IBillboardSceneNode*>(List[i]))
|
||||||
{
|
{
|
||||||
|
node->updateAbsolutePosition();
|
||||||
if (!isCulledPrecise(cam, List[i]))
|
if (!isCulledPrecise(cam, List[i]))
|
||||||
CPUParticleManager::getInstance()->addBillboardNode(node);
|
CPUParticleManager::getInstance()->addBillboardNode(node);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
else if (STKTextBillboard *tb =
|
||||||
if (STKTextBillboard *tb =
|
|
||||||
dynamic_cast<STKTextBillboard*>(List[i]))
|
dynamic_cast<STKTextBillboard*>(List[i]))
|
||||||
{
|
{
|
||||||
|
node->updateAbsolutePosition();
|
||||||
if (!isCulledPrecise(cam, List[i], irr_driver->getBoundingBoxesViz()))
|
if (!isCulledPrecise(cam, List[i], irr_driver->getBoundingBoxesViz()))
|
||||||
TextBillboardDrawer::addTextBillboard(tb);
|
TextBillboardDrawer::addTextBillboard(tb);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
SP::SPMeshNode* node = dynamic_cast<SP::SPMeshNode*>(List[i]);
|
|
||||||
if (node)
|
|
||||||
{
|
|
||||||
SP::addObject(node);
|
|
||||||
}
|
|
||||||
parseSceneManager(List[i]->getChildren(), cam);
|
parseSceneManager(List[i]->getChildren(), cam);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,13 +49,8 @@ LODNode::LODNode(std::string group_name, scene::ISceneNode* parent,
|
|||||||
|
|
||||||
m_forced_lod = -1;
|
m_forced_lod = -1;
|
||||||
m_area = 0;
|
m_area = 0;
|
||||||
#ifndef SERVER_ONLY
|
m_current_level = -1;
|
||||||
if (!CVS->isGLSL())
|
m_current_level_dirty = true;
|
||||||
{
|
|
||||||
m_current_level.reset(new int);
|
|
||||||
*m_current_level = -1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LODNode::~LODNode()
|
LODNode::~LODNode()
|
||||||
@ -79,6 +74,10 @@ int LODNode::getLevel()
|
|||||||
if (m_forced_lod >- 1)
|
if (m_forced_lod >- 1)
|
||||||
return m_forced_lod;
|
return m_forced_lod;
|
||||||
|
|
||||||
|
if (!m_current_level_dirty)
|
||||||
|
return m_current_level;
|
||||||
|
m_current_level_dirty = false;
|
||||||
|
|
||||||
Camera* camera = Camera::getActiveCamera();
|
Camera* camera = Camera::getActiveCamera();
|
||||||
if (camera == NULL)
|
if (camera == NULL)
|
||||||
return (int)m_detail.size() - 1;
|
return (int)m_detail.size() - 1;
|
||||||
@ -90,9 +89,12 @@ int LODNode::getLevel()
|
|||||||
for (unsigned int n=0; n<m_detail.size(); n++)
|
for (unsigned int n=0; n<m_detail.size(); n++)
|
||||||
{
|
{
|
||||||
if (dist < m_detail[n])
|
if (dist < m_detail[n])
|
||||||
|
{
|
||||||
|
m_current_level = n;
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
m_current_level = -1;
|
||||||
return -1;
|
return -1;
|
||||||
} // getLevel
|
} // getLevel
|
||||||
|
|
||||||
@ -108,6 +110,8 @@ void LODNode::forceLevelOfDetail(int n)
|
|||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
void LODNode::OnAnimate(u32 timeMs)
|
void LODNode::OnAnimate(u32 timeMs)
|
||||||
{
|
{
|
||||||
|
updateVisibility();
|
||||||
|
|
||||||
if (isVisible() && m_nodes.size() > 0)
|
if (isVisible() && m_nodes.size() > 0)
|
||||||
{
|
{
|
||||||
// update absolute position
|
// update absolute position
|
||||||
@ -126,7 +130,6 @@ void LODNode::OnAnimate(u32 timeMs)
|
|||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
int level = getLevel();
|
int level = getLevel();
|
||||||
*m_current_level = level;
|
|
||||||
// Assume all the scene node have the same bouding box
|
// Assume all the scene node have the same bouding box
|
||||||
if(level >= 0)
|
if(level >= 0)
|
||||||
{
|
{
|
||||||
@ -154,29 +157,22 @@ void LODNode::OnAnimate(u32 timeMs)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LODNode::updateVisibility(bool* shown)
|
void LODNode::updateVisibility()
|
||||||
{
|
{
|
||||||
if (!isVisible()) return;
|
if (!isVisible()) return;
|
||||||
if (m_nodes.size() == 0) return;
|
if (m_nodes.size() == 0) return;
|
||||||
|
|
||||||
unsigned int level = 0;
|
m_current_level_dirty = true;
|
||||||
if (m_current_level)
|
unsigned int level = getLevel();
|
||||||
level = *m_current_level;
|
|
||||||
else
|
|
||||||
level = getLevel();
|
|
||||||
for (size_t i = 0; i < m_nodes.size(); i++)
|
for (size_t i = 0; i < m_nodes.size(); i++)
|
||||||
{
|
{
|
||||||
m_nodes[i]->setVisible(i == level);
|
m_nodes[i]->setVisible(i == level);
|
||||||
if (i == level && shown != NULL)
|
|
||||||
*shown = (i > 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LODNode::OnRegisterSceneNode()
|
void LODNode::OnRegisterSceneNode()
|
||||||
{
|
{
|
||||||
bool shown = false;
|
|
||||||
updateVisibility(&shown);
|
|
||||||
|
|
||||||
#ifndef SERVER_ONLY
|
#ifndef SERVER_ONLY
|
||||||
if (CVS->isGLSL())
|
if (CVS->isGLSL())
|
||||||
{
|
{
|
||||||
@ -184,14 +180,20 @@ void LODNode::OnRegisterSceneNode()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef SERVER_ONLY
|
if (isVisible() && m_nodes.size() > 0)
|
||||||
if (!CVS->isGLSL())
|
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < Children.size(); ++i)
|
int level = getLevel();
|
||||||
Children[i]->updateAbsolutePosition();
|
|
||||||
|
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
|
/* 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. */
|
* m_forced_lod is >=0, only this level is be used. */
|
||||||
int m_forced_lod;
|
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)
|
// Area of the bounding box (for autoLOD computation)
|
||||||
float m_area;
|
float m_area;
|
||||||
@ -79,7 +80,7 @@ public:
|
|||||||
|
|
||||||
int getLevel();
|
int getLevel();
|
||||||
|
|
||||||
void updateVisibility(bool* shown = NULL);
|
void updateVisibility();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
//! Returns a reference to the current relative transformation matrix.
|
//! Returns a reference to the current relative transformation matrix.
|
||||||
@ -115,6 +116,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<scene::ISceneNode*>& getAllNodes() { return m_nodes; }
|
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.
|
//! OnAnimate() is called just before rendering the whole scene.
|
||||||
/** This method will be called once per frame, independent
|
/** This method will be called once per frame, independent
|
||||||
|
Loading…
Reference in New Issue
Block a user