Clean up culling code

This commit is contained in:
Benau 2016-11-25 16:45:00 +08:00
parent 0c091125b0
commit 5ca5dc3b3e
9 changed files with 149 additions and 231 deletions

View File

@ -1,5 +1,5 @@
# Modify this file to change the last-modified date when you add/remove a file.
# This will then trigger a new cmake run automatically.
# This will then trigger a new cmake run automatically.
file(GLOB_RECURSE STK_HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.hpp")
file(GLOB_RECURSE STK_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.cpp")
file(GLOB_RECURSE STK_SHADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "data/shaders/*")

View File

@ -25,26 +25,11 @@
#include "graphics/stk_billboard.hpp"
#include "graphics/stk_mesh.hpp"
#include "graphics/stk_mesh_scene_node.hpp"
#include "graphics/stk_scene_manager.hpp"
#include "graphics/vao_manager.hpp"
#include "modes/world.hpp"
#include "tracks/track.hpp"
#include "utils/profiler.hpp"
using namespace irr;
namespace
{
void FixBoundingBoxes(scene::ISceneNode* node)
{
for (scene::ISceneNode *child : node->getChildren())
{
FixBoundingBoxes(child);
const_cast<core::aabbox3df&>(node->getBoundingBox()).addInternalBox(child->getBoundingBox());
}
}
} //namespace
// ----------------------------------------------------------------------------
void DrawCalls::clearLists()
{
@ -72,27 +57,16 @@ void DrawCalls::clearLists()
}
// ----------------------------------------------------------------------------
void DrawCalls::handleSTKCommon(scene::ISceneNode *Node,
std::vector<scene::ISceneNode *> *ImmediateDraw,
const scene::ICameraSceneNode *cam,
scene::ICameraSceneNode *shadowcam[4],
const scene::ICameraSceneNode *rsmcam,
bool &culledforcam,
bool culledforshadowcam[4],
bool &culledforrsm,
bool drawRSM)
bool DrawCalls::isCulledPrecise(const scene::ICameraSceneNode *cam,
const scene::ISceneNode* node,
bool visualization)
{
STKMeshCommon *node = dynamic_cast<STKMeshCommon*>(Node);
if (!node)
return;
node->updateNoGL();
m_deferred_update.push_back(node);
const core::matrix4 &trans = Node->getAbsoluteTransformation();
if (!node->getAutomaticCulling() && !visualization)
return false;
const core::matrix4 &trans = node->getAbsoluteTransformation();
core::vector3df edges[8];
Node->getBoundingBox().getEdges(edges);
node->getBoundingBox().getEdges(edges);
for (unsigned i = 0; i < 8; i++)
trans.transformVect(edges[i]);
@ -107,35 +81,119 @@ void DrawCalls::handleSTKCommon(scene::ISceneNode *Node,
0---------4/
*/
if (irr_driver->getBoundingBoxesViz())
if (visualization)
{
addEdge(edges[0], edges[1]);
addEdge(edges[1], edges[5]);
addEdge(edges[5], edges[4]);
addEdge(edges[4], edges[0]);
addEdge(edges[2], edges[3]);
addEdge(edges[3], edges[7]);
addEdge(edges[7], edges[6]);
addEdge(edges[6], edges[2]);
addEdge(edges[0], edges[2]);
addEdge(edges[1], edges[3]);
addEdge(edges[5], edges[7]);
addEdge(edges[4], edges[6]);
addEdgeForViz(edges[0], edges[1]);
addEdgeForViz(edges[1], edges[5]);
addEdgeForViz(edges[5], edges[4]);
addEdgeForViz(edges[4], edges[0]);
addEdgeForViz(edges[2], edges[3]);
addEdgeForViz(edges[3], edges[7]);
addEdgeForViz(edges[7], edges[6]);
addEdgeForViz(edges[6], edges[2]);
addEdgeForViz(edges[0], edges[2]);
addEdgeForViz(edges[1], edges[3]);
addEdgeForViz(edges[5], edges[7]);
addEdgeForViz(edges[4], edges[6]);
if (!node->getAutomaticCulling())
{
return false;
}
}
const scene::SViewFrustum &frust = *cam->getViewFrustum();
for (s32 i = 0; i < scene::SViewFrustum::VF_PLANE_COUNT; i++)
{
if (isBoxInFrontOfPlane(frust.planes[i], edges))
{
return true;
}
}
return false;
} // isCulledPrecise
// ----------------------------------------------------------------------------
bool DrawCalls::isBoxInFrontOfPlane(const core::plane3df &plane,
const core::vector3df* edges)
{
for (u32 i = 0; i < 8; i++)
{
if (plane.classifyPointRelation(edges[i]) != core::ISREL3D_FRONT)
return false;
}
return true;
} // isBoxInFrontOfPlane
// ----------------------------------------------------------------------------
void DrawCalls::addEdgeForViz(const core::vector3df &p0,
const core::vector3df &p1)
{
m_bounding_boxes.push_back(p0.X);
m_bounding_boxes.push_back(p0.Y);
m_bounding_boxes.push_back(p0.Z);
m_bounding_boxes.push_back(p1.X);
m_bounding_boxes.push_back(p1.Y);
m_bounding_boxes.push_back(p1.Z);
} // addEdgeForViz
// ----------------------------------------------------------------------------
void DrawCalls::renderBoundingBoxes()
{
Shaders::ColoredLine *line = Shaders::ColoredLine::getInstance();
line->use();
line->bindVertexArray();
line->bindBuffer();
line->setUniforms(irr::video::SColor(255, 255, 0, 0));
const float *tmp = m_bounding_boxes.data();
for (unsigned int i = 0; i < m_bounding_boxes.size(); i += 1024 * 6)
{
unsigned count = std::min((unsigned)m_bounding_boxes.size() - i,
(unsigned)1024 * 6);
glBufferSubData(GL_ARRAY_BUFFER, 0, count * sizeof(float), &tmp[i]);
glDrawArrays(GL_LINES, 0, count / 3);
}
m_bounding_boxes.clear();
} // renderBoundingBoxes
// ----------------------------------------------------------------------------
void DrawCalls::handleSTKCommon(scene::ISceneNode *Node,
std::vector<scene::ISceneNode *> *ImmediateDraw,
const scene::ICameraSceneNode *cam,
ShadowMatrices& shadow_matrices)
{
STKMeshCommon* node = dynamic_cast<STKMeshCommon*>(Node);
if (!node)
return;
node->updateNoGL();
m_deferred_update.push_back(node);
if (node->isImmediateDraw())
{
ImmediateDraw->push_back(Node);
return;
}
culledforcam = culledforcam || isCulledPrecise(cam, Node);
culledforrsm = culledforrsm || isCulledPrecise(rsmcam, Node);
for (unsigned i = 0; i < 4; i++)
culledforshadowcam[i] = culledforshadowcam[i] || isCulledPrecise(shadowcam[i], Node);
bool culled_for_cams[6] = { true, true, true, true, true, true };
culled_for_cams[0] = isCulledPrecise(cam, Node,
irr_driver->getBoundingBoxesViz());
if (UserConfigParams::m_gi && !shadow_matrices.isRSMMapAvail())
{
culled_for_cams[1] = isCulledPrecise(shadow_matrices.getSunCam(), Node);
}
if (CVS->isShadowEnabled())
{
for (unsigned i = 0; i < 4; i++)
{
culled_for_cams[i + 2] =
isCulledPrecise(shadow_matrices.getShadowCamNodes()[i], Node);
}
}
// Transparent
if (World::getWorld() && World::getWorld()->isFogEnabled())
{
const Track * const track = World::getWorld()->getTrack();
@ -185,7 +243,7 @@ void DrawCalls::handleSTKCommon(scene::ISceneNode *Node,
for (GLMesh *mesh : node->TransparentMesh[TM_DISPLACEMENT])
pushVector(ListDisplacement::getInstance(), mesh, Node->getAbsoluteTransformation());
if (!culledforcam)
if (!culled_for_cams[0])
{
for (unsigned Mat = 0; Mat < Material::SHADERTYPE_COUNT; ++Mat)
{
@ -297,7 +355,7 @@ void DrawCalls::handleSTKCommon(scene::ISceneNode *Node,
return;
for (unsigned cascade = 0; cascade < 4; ++cascade)
{
if (culledforshadowcam[cascade])
if (culled_for_cams[cascade + 2])
continue;
for (unsigned Mat = 0; Mat < Material::SHADERTYPE_COUNT; ++Mat)
{
@ -356,21 +414,23 @@ void DrawCalls::handleSTKCommon(scene::ISceneNode *Node,
}
}
}
if (!UserConfigParams::m_gi || !drawRSM)
if (!UserConfigParams::m_gi || shadow_matrices.isRSMMapAvail())
return;
if (!culledforrsm)
if (!culled_for_cams[1])
{
for (unsigned Mat = 0; Mat < Material::SHADERTYPE_COUNT; ++Mat)
{
if (CVS->supportsIndirectInstancingRendering())
{
if (Mat == Material::SHADERTYPE_SPLATTING)
{
for (GLMesh *mesh : node->MeshSolidMaterial[Mat])
{
core::matrix4 ModelMatrix = Node->getAbsoluteTransformation(), InvModelMatrix;
ModelMatrix.getInverse(InvModelMatrix);
ListMatSplatting::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix);
}
ListMatSplatting::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix);
}
}
else
{
for (GLMesh *mesh : node->MeshSolidMaterial[Mat])
@ -431,16 +491,11 @@ void DrawCalls::handleSTKCommon(scene::ISceneNode *Node,
}
}
// ----------------------------------------------------------------------------
void DrawCalls::parseSceneManager(core::list<scene::ISceneNode*> &List,
std::vector<scene::ISceneNode *> *ImmediateDraw,
const scene::ICameraSceneNode* cam,
scene::ICameraSceneNode *shadow_cam[4],
const scene::ICameraSceneNode *rsmcam,
bool culledforcam,
bool culledforshadowcam[4],
bool culledforrsm,
bool drawRSM)
const scene::ICameraSceneNode *cam,
ShadowMatrices& shadow_matrices)
{
core::list<scene::ISceneNode*>::Iterator I = List.begin(), E = List.end();
for (; I != E; ++I)
@ -465,13 +520,9 @@ void DrawCalls::parseSceneManager(core::list<scene::ISceneNode*> &List,
continue;
}
bool newculledforcam = culledforcam;
bool newculledforrsm = culledforrsm;
bool newculledforshadowcam[4] = { culledforshadowcam[0], culledforshadowcam[1], culledforshadowcam[2], culledforshadowcam[3] };
handleSTKCommon(*I, ImmediateDraw, cam, shadow_cam, rsmcam, newculledforcam, newculledforshadowcam, newculledforrsm, drawRSM);
parseSceneManager(const_cast<core::list<scene::ISceneNode*>& >((*I)->getChildren()), ImmediateDraw, cam, shadow_cam, rsmcam, newculledforcam, newculledforshadowcam, newculledforrsm, drawRSM);
handleSTKCommon((*I), ImmediateDraw, cam, shadow_matrices);
parseSceneManager((*I)->getChildren(), ImmediateDraw, cam,
shadow_matrices);
}
}
@ -506,15 +557,13 @@ DrawCalls::~DrawCalls()
#endif // !defined(USE_GLES2)
} //~DrawCalls
// ----------------------------------------------------------------------------
/** Prepare draw calls before scene rendering
* \param[out] solid_poly_count Total number of polygons in objects
* that will be rendered in this frame
* \param[out] shadow_poly_count Total number of polygons for shadow
* (rendered this frame)
*/
*/
void DrawCalls::prepareDrawCalls( ShadowMatrices& shadow_matrices,
scene::ICameraSceneNode *camnode,
unsigned &solid_poly_count,
@ -533,23 +582,11 @@ void DrawCalls::prepareDrawCalls( ShadowMatrices& shadow_matrices,
m_glow_pass_mesh.clear();
m_deferred_update.clear();
core::list<scene::ISceneNode*> List = irr_driver->getSceneManager()->getRootSceneNode()->getChildren();
PROFILER_PUSH_CPU_MARKER("- culling", 0xFF, 0xFF, 0x0);
for (scene::ISceneNode *child : List)
FixBoundingBoxes(child);
bool cam = false, rsmcam = false;
bool shadowcam[4] = { false, false, false, false };
parseSceneManager(List,
&m_immediate_draw_list,
camnode,
shadow_matrices.getShadowCamNodes(),
shadow_matrices.getSunCam(),
cam, shadowcam, rsmcam,
!shadow_matrices.isRSMMapAvail());
parseSceneManager(
irr_driver->getSceneManager()->getRootSceneNode()->getChildren(),
&m_immediate_draw_list, camnode, shadow_matrices);
PROFILER_POP_CPU_MARKER();
// Add a 1 s timeout

View File

@ -37,6 +37,8 @@ private:
std::vector<STKBillboard *> m_billboard_list;
std::vector<ParticleSystemProxy *> m_particles_list;
std::vector<float> m_bounding_boxes;
/** meshes to draw */
SolidPassMeshMap m_solid_pass_mesh [ Material::SHADERTYPE_COUNT];
OtherMeshMap m_shadow_pass_mesh [4 * Material::SHADERTYPE_COUNT];
@ -56,23 +58,22 @@ private:
void handleSTKCommon(scene::ISceneNode *Node,
std::vector<scene::ISceneNode *> *ImmediateDraw,
const scene::ICameraSceneNode *cam,
scene::ICameraSceneNode *shadowcam[4],
const scene::ICameraSceneNode *rsmcam,
bool &culledforcam,
bool culledforshadowcam[4],
bool &culledforrsm,
bool drawRSM);
void parseSceneManager(core::list<scene::ISceneNode*> &List,
std::vector<scene::ISceneNode *> *ImmediateDraw,
const scene::ICameraSceneNode* cam,
scene::ICameraSceneNode *shadow_cam[4],
const scene::ICameraSceneNode *rsmcam,
bool culledforcam,
bool culledforshadowcam[4],
bool culledforrsm,
bool drawRSM);
ShadowMatrices& shadow_matrices);
void parseSceneManager(core::list<scene::ISceneNode*> &List,
std::vector<scene::ISceneNode *> *ImmediateDraw,
const scene::ICameraSceneNode *cam,
ShadowMatrices& shadow_matrices);
bool isCulledPrecise(const scene::ICameraSceneNode *cam,
const scene::ISceneNode* node,
bool visualization = false);
bool isBoxInFrontOfPlane(const core::plane3df &plane,
const core::vector3df* edges);
void addEdgeForViz(const core::vector3df &p0, const core::vector3df &p1);
public:
DrawCalls();
~DrawCalls();
@ -103,7 +104,7 @@ public:
void drawIndirectGlow() const;
void multidrawGlow() const;
void renderBoundingBoxes();
};
#endif //HEADER_DRAW_CALLS_HPP

View File

@ -22,7 +22,6 @@
#include "graphics/post_processing.hpp"
#include "graphics/rtts.hpp"
#include "graphics/shaders.hpp"
#include "graphics/stk_scene_manager.hpp"
#include "modes/world.hpp"
#include "utils/tuple.hpp"
#include <SColor.h>

View File

@ -37,7 +37,6 @@
#include "graphics/stk_animated_mesh.hpp"
#include "graphics/stk_billboard.hpp"
#include "graphics/stk_mesh_scene_node.hpp"
#include "graphics/stk_scene_manager.hpp"
#include "graphics/sun.hpp"
#include "graphics/texture_manager.hpp"
#include "guiengine/engine.hpp"

View File

@ -31,7 +31,6 @@
#include "graphics/shaders.hpp"
#include "graphics/skybox.hpp"
#include "graphics/spherical_harmonics.hpp"
#include "graphics/stk_scene_manager.hpp"
#include "graphics/texture_manager.hpp"
#include "items/item_manager.hpp"
#include "items/powerup_manager.hpp"
@ -536,24 +535,6 @@ void ShaderBasedRenderer::renderParticles()
// m_scene_manager->drawAll(scene::ESNRP_TRANSPARENT_EFFECT);
} //renderParticles
// ----------------------------------------------------------------------------
void ShaderBasedRenderer::renderBoundingBoxes()
{
Shaders::ColoredLine *line = Shaders::ColoredLine::getInstance();
line->use();
line->bindVertexArray();
line->bindBuffer();
line->setUniforms(irr::video::SColor(255, 255, 0, 0));
const float *tmp = BoundingBoxes.data();
for (unsigned int i = 0; i < BoundingBoxes.size(); i += 1024 * 6)
{
unsigned count = std::min((unsigned)BoundingBoxes.size() - i, (unsigned)1024 * 6);
glBufferSubData(GL_ARRAY_BUFFER, 0, count * sizeof(float), &tmp[i]);
glDrawArrays(GL_LINES, 0, count / 3);
}
} //renderBoundingBoxes
// ----------------------------------------------------------------------------
void ShaderBasedRenderer::debugPhysics()
{
@ -804,9 +785,7 @@ void ShaderBasedRenderer::render(float dt)
{
resetObjectCount();
resetPolyCount();
BoundingBoxes.clear(); //TODO: do not use a global variable
setOverrideMaterial();
addItemsInGlowingList();
@ -858,7 +837,7 @@ void ShaderBasedRenderer::render(float dt)
if (irr_driver->getBoundingBoxesViz())
{
renderBoundingBoxes();
m_draw_calls.renderBoundingBoxes();
}
debugPhysics();

View File

@ -81,7 +81,6 @@ private:
void renderParticles();
void renderBoundingBoxes();
void debugPhysics();
void renderPostProcessing(Camera * const camera);

View File

@ -1,63 +0,0 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2014-2015 SuperTuxKart-Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "graphics/stk_scene_manager.hpp"
#include <SViewFrustum.h>
#include <vector>
using namespace irr;
// From irrlicht code
static
bool isBoxInFrontOfPlane(const core::plane3df &plane, const core::vector3df edges[8])
{
for (u32 j = 0; j<8; ++j)
if (plane.classifyPointRelation(edges[j]) != core::ISREL3D_FRONT)
return false;
return true;
}
std::vector<float> BoundingBoxes;
void addEdge(const core::vector3df &P0, const core::vector3df &P1)
{
BoundingBoxes.push_back(P0.X);
BoundingBoxes.push_back(P0.Y);
BoundingBoxes.push_back(P0.Z);
BoundingBoxes.push_back(P1.X);
BoundingBoxes.push_back(P1.Y);
BoundingBoxes.push_back(P1.Z);
}
bool isCulledPrecise(const scene::ICameraSceneNode *cam, const scene::ISceneNode *node)
{
if (!node->getAutomaticCulling())
return false;
const core::matrix4 &trans = node->getAbsoluteTransformation();
const scene::SViewFrustum &frust = *cam->getViewFrustum();
core::vector3df edges[8];
node->getBoundingBox().getEdges(edges);
for (unsigned i = 0; i < 8; i++)
trans.transformVect(edges[i]);
for (s32 i = 0; i < scene::SViewFrustum::VF_PLANE_COUNT; ++i)
if (isBoxInFrontOfPlane(frust.planes[i], edges))
return true;
return false;
}

View File

@ -1,33 +0,0 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2014-2015 SuperTuxKart-Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
// Not really a scene manager yet but hold algorithm that
// rework scene manager output
#ifndef HEADER_STKSCENEMANAGER_HPP
#define HEADER_STKSCENEMANAGER_HPP
#include <ICameraSceneNode.h>
#include <ISceneNode.h>
#include <vector3d.h>
void addEdge(const irr::core::vector3df &P0, const irr::core::vector3df &P1);
bool isCulledPrecise(const irr::scene::ICameraSceneNode *cam, const irr::scene::ISceneNode *node);
#endif