Skip to content

Commit

Permalink
LOD improvements (#5038)
Browse files Browse the repository at this point in the history
* 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.
  • Loading branch information
CodingJellyfish authored Apr 15, 2024
1 parent 6cf094a commit 8577408
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 46 deletions.
42 changes: 26 additions & 16 deletions src/graphics/draw_calls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Expand Down
58 changes: 30 additions & 28 deletions src/graphics/lod_node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -76,8 +71,12 @@ 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)
Expand All @@ -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

Expand All @@ -108,6 +110,8 @@ void LODNode::forceLevelOfDetail(int n)
// ----------------------------------------------------------------------------
void LODNode::OnAnimate(u32 timeMs)
{
updateVisibility();

if (isVisible() && m_nodes.size() > 0)
{
// update absolute position
Expand All @@ -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);
Expand All @@ -154,44 +157,43 @@ 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())
{
return;
}
#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
Expand Down
6 changes: 4 additions & 2 deletions src/graphics/lod_node.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ class LODNode : public scene::ISceneNode
* 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;
Expand All @@ -79,7 +80,7 @@ class LODNode : public scene::ISceneNode

int getLevel();

void updateVisibility(bool* shown = NULL);
void updateVisibility();

/*
//! Returns a reference to the current relative transformation matrix.
Expand Down Expand Up @@ -115,6 +116,7 @@ class LODNode : public scene::ISceneNode
}

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
Expand Down

0 comments on commit 8577408

Please sign in to comment.