From: Mikko Rasa Date: Fri, 4 Dec 2015 12:09:48 +0000 (+0200) Subject: Remove the culler abstraction and move frustum culling to Scene X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=commitdiff_plain;h=802832425b02be7b3ccb7d585fe63f4b68b5275f Remove the culler abstraction and move frustum culling to Scene It turns out that different culling methods (such as occlusion queries) have different enough requirements that putting them behind a single abstraction is not feasible. This also seems to provide a slight performance boost. --- diff --git a/source/culler.h b/source/culler.h deleted file mode 100644 index 4d2bdb7b..00000000 --- a/source/culler.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef MSP_GL_CULLER_H_ -#define MSP_GL_CULLER_H_ - -namespace Msp { -namespace GL { - -class Renderable; -class Renderer; - -/** -Base class and interface for cullers. Scenes can use cullers to avoid -rendering things that are not visible. -*/ -class Culler -{ -protected: - Culler() { } -public: - virtual ~Culler() { } - - /** Called once at the start of each rendering pass. */ - virtual void setup_pass(const Renderer &) { }; - - /** Decides if a renderable should be culled. If this returns true, the - renderable is skipped. */ - virtual bool cull(const Renderer &, const Renderable &) const = 0; -}; - -} // namespace GL -} // namespace Msp - -#endif diff --git a/source/frustumculler.cpp b/source/frustumculler.cpp deleted file mode 100644 index ca7a3a2d..00000000 --- a/source/frustumculler.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include "camera.h" -#include "frustumculler.h" -#include "renderable.h" -#include "renderer.h" - -#include - -namespace Msp { -namespace GL { - -void FrustumCuller::setup_pass(const Renderer &renderer) -{ - const Camera *camera = renderer.get_camera(); - if(!camera) - return; - - float y = tan(camera->get_field_of_view()/2.0f); - float s = sqrt(y*y+1); - edges[0] = Vector3(0, 1/s, y/s); - edges[1] = Vector3(0, -1/s, y/s); - - float x = y*camera->get_aspect(); - s = sqrt(x*x+1); - edges[2] = Vector3(1/s, 0, x/s); - edges[3] = Vector3(-1/s, 0, x/s); -} - -bool FrustumCuller::cull(const Renderer &renderer, const Renderable &renderable) const -{ - const Matrix *matrix = renderable.get_matrix(); - const Geometry::BoundingSphere *bsphere = renderable.get_bounding_sphere(); - const Camera *camera = renderer.get_camera(); - if(!matrix || !bsphere || !camera) - return false; - - Matrix mvm = camera->get_matrix()**matrix; - float n = camera->get_near_clip(); - float f = camera->get_far_clip(); - - Vector3 center = mvm*bsphere->get_center(); - float radius = bsphere->get_radius(); - - if(center.z-radius>-n || center.z+radius<-f) - return true; - for(unsigned i=0; i<4; ++i) - if(dot(center, edges[i])>radius) - return true; - - return false; -} - -} // namespace GL -} // namespace Msp diff --git a/source/frustumculler.h b/source/frustumculler.h deleted file mode 100644 index 4d227602..00000000 --- a/source/frustumculler.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef MSP_GL_FRUSTUMCULLER_H_ -#define MSP_GL_FRUSTUMCULLER_H_ - -#include "culler.h" -#include "vector.h" - -namespace Msp { -namespace GL { - -/** -Culls objects that are outside of the view frustum. -*/ -class FrustumCuller: public Culler -{ -private: - Vector3 edges[4]; - -public: - virtual void setup_pass(const Renderer &); - - virtual bool cull(const Renderer &, const Renderable &) const; -}; - -} // namespace GL -} // namespace Msp - -#endif diff --git a/source/instancescene.cpp b/source/instancescene.cpp index 0ff9b520..fef3e969 100644 --- a/source/instancescene.cpp +++ b/source/instancescene.cpp @@ -38,10 +38,10 @@ void InstanceScene::finish_frame() const void InstanceScene::render(Renderer &renderer, const Tag &tag) const { - setup_cullers(renderer); + setup_frustum(renderer); for(InstanceMap::const_iterator i=renderables.begin(); i!=renderables.end(); ++i) for(RenderableSet::const_iterator j=i->second.begin(); j!=i->second.end(); ++j) - if(!cull(renderer, **j)) + if(!frustum_cull(renderer, **j)) renderer.render(**j, tag); } diff --git a/source/orderedscene.cpp b/source/orderedscene.cpp index fe968f0c..f129cdab 100644 --- a/source/orderedscene.cpp +++ b/source/orderedscene.cpp @@ -49,9 +49,9 @@ void OrderedScene::finish_frame() const void OrderedScene::render(Renderer &renderer, const Tag &tag) const { - setup_cullers(renderer); + setup_frustum(renderer); for(RenderableList::const_iterator i=renderables.begin(); i!=renderables.end(); ++i) - if(!cull(renderer, **i)) + if(!frustum_cull(renderer, **i)) renderer.render(**i, tag); } diff --git a/source/scene.cpp b/source/scene.cpp index f233a09b..7896d23d 100644 --- a/source/scene.cpp +++ b/source/scene.cpp @@ -1,6 +1,6 @@ #include #include "animatedobject.h" -#include "culler.h" +#include "camera.h" #include "renderer.h" #include "scene.h" @@ -15,35 +15,50 @@ Scene::~Scene() delete *i; } -void Scene::add_culler(Culler &c) -{ - cullers.push_back(&c); -} - -void Scene::remove_culler(Culler &c) -{ - list::iterator i = find(cullers.begin(), cullers.end(), &c); - if(i!=cullers.end()) - cullers.erase(i); -} - void Scene::render(const Tag &tag) const { Renderer renderer(0); render(renderer, tag); } -void Scene::setup_cullers(const Renderer &renderer) const +void Scene::setup_frustum(const Renderer &renderer) const { - for(list::const_iterator i=cullers.begin(); i!=cullers.end(); ++i) - (*i)->setup_pass(renderer); + const Camera *camera = renderer.get_camera(); + if(!camera) + return; + + float y = tan(camera->get_field_of_view()/2.0f); + float s = sqrt(y*y+1); + frustum_edges[0] = Vector3(0, 1/s, y/s); + frustum_edges[1] = Vector3(0, -1/s, y/s); + + float x = y*camera->get_aspect(); + s = sqrt(x*x+1); + frustum_edges[2] = Vector3(1/s, 0, x/s); + frustum_edges[3] = Vector3(-1/s, 0, x/s); } -bool Scene::cull(const Renderer &renderer, const Renderable &renderable) const +bool Scene::frustum_cull(const Renderer &renderer, const Renderable &renderable) const { - for(list::const_iterator i=cullers.begin(); i!=cullers.end(); ++i) - if((*i)->cull(renderer, renderable)) + const Matrix *matrix = renderable.get_matrix(); + const Geometry::BoundingSphere *bsphere = renderable.get_bounding_sphere(); + const Camera *camera = renderer.get_camera(); + if(!matrix || !bsphere || !camera) + return false; + + Matrix mvm = camera->get_matrix()**matrix; + float n = camera->get_near_clip(); + float f = camera->get_far_clip(); + + Vector3 center = mvm*bsphere->get_center(); + float radius = bsphere->get_radius(); + + if(center.z-radius>-n || center.z+radius<-f) + return true; + for(unsigned i=0; i<4; ++i) + if(dot(center, frustum_edges[i])>radius) return true; + return false; } diff --git a/source/scene.h b/source/scene.h index 687c581f..611f3508 100644 --- a/source/scene.h +++ b/source/scene.h @@ -4,12 +4,11 @@ #include #include #include "renderable.h" +#include "vector.h" namespace Msp { namespace GL { -class Culler; - /** Scenes are containers for other Renderables. This is a base class that can't be instantiated. Examples of available Scene types are SimpleScene, @@ -29,7 +28,7 @@ public: protected: std::list owned_data; - std::list cullers; + mutable Vector3 frustum_edges[4]; Scene() { } private: @@ -41,15 +40,12 @@ public: virtual void add(const Renderable &) = 0; virtual void remove(const Renderable &) = 0; - void add_culler(Culler &); - void remove_culler(Culler &); - using Renderable::render; virtual void render(const Tag & = Tag()) const; protected: - virtual void setup_cullers(const Renderer &) const; - virtual bool cull(const Renderer &, const Renderable &) const; + void setup_frustum(const Renderer &) const; + bool frustum_cull(const Renderer &, const Renderable &) const; }; } // namespace GL diff --git a/source/simplescene.cpp b/source/simplescene.cpp index c537ff3b..7629a828 100644 --- a/source/simplescene.cpp +++ b/source/simplescene.cpp @@ -28,9 +28,9 @@ void SimpleScene::finish_frame() const void SimpleScene::render(Renderer &renderer, const Tag &tag) const { - setup_cullers(renderer); + setup_frustum(renderer); for(RenderableSet::const_iterator i=renderables.begin(); i!=renderables.end(); ++i) - if(!cull(renderer, **i)) + if(!frustum_cull(renderer, **i)) renderer.render(**i, tag); } diff --git a/source/zsortedscene.cpp b/source/zsortedscene.cpp index 5cbd2021..c9bce679 100644 --- a/source/zsortedscene.cpp +++ b/source/zsortedscene.cpp @@ -36,9 +36,9 @@ void ZSortedScene::render(Renderer &renderer, const Tag &tag) const float radius_factor = 1.0f-reference; float sign = order*2.0f-1.0f; - setup_cullers(renderer); + setup_frustum(renderer); for(RenderableSet::const_iterator i=renderables.begin(); i!=renderables.end(); ++i) - if(!cull(renderer, **i)) + if(!frustum_cull(renderer, **i)) { float z = 0; if(const Matrix *model_matrix = (*i)->get_matrix())