#include <algorithm>
-#include <msp/gl/extensions/arb_occlusion_query.h>
-#include <msp/gl/extensions/arb_occlusion_query2.h>
#include "camera.h"
+#include "mesh.h"
#include "occludedscene.h"
+#include "program.h"
#include "renderer.h"
#include "resources.h"
-#include "sphere.h"
using namespace std;
OccludedScene::OccludedScene():
bounding_mesh(Resources::get_global().get<Mesh>("_occluder.mesh")),
- bounding_shader(Resources::get_global().get<Program>("_occluder.glsl.shader")),
- occluder_min_size(0.25f),
- cache_dirty(false)
+ bounding_shader(Resources::get_global().get<Program>("occluder.glsl.shader")),
+ queries(OCCLUSION_QUERY, 0)
{
- static Require req(ARB_occlusion_query);
- static Require req2(ARB_occlusion_query2);
-}
-
-OccludedScene::~OccludedScene()
-{
- vector<unsigned> queries;
- queries.reserve(occluded_cache.size());
- for(OccludedArray::iterator i=occluded_cache.begin(); i!=occluded_cache.end(); ++i)
- queries.push_back(i->query);
- glDeleteQueries(queries.size(), &queries[0]);
+ no_color_write.write_mask = WRITE_NONE;
}
void OccludedScene::add(Renderable &r)
if(!cache_dirty)
return;
+ if(queries.get_size()<renderables.size())
+ queries.resize(renderables.size());
if(occluded_cache.size()<renderables.size())
- {
- unsigned old_size = occluded_cache.size();
occluded_cache.resize(renderables.size());
- vector<unsigned> new_queries(occluded_cache.size()-old_size);
- glGenQueries(new_queries.size(), &new_queries[0]);
- for(unsigned i=0; i<new_queries.size(); ++i)
- occluded_cache[old_size+i].query = new_queries[i];
- }
- OccludedArray::iterator j = occluded_cache.begin();
- for(RenderableSet::iterator i=renderables.begin(); i!=renderables.end(); ++i, ++j)
- j->renderable = *i;
+ auto j = occluded_cache.begin();
+ for(Renderable *r: renderables)
+ j++->renderable = r;
for(; j!=occluded_cache.end(); ++j)
{
j->renderable = 0;
void OccludedScene::setup_frame(Renderer &renderer)
{
populate_cache();
- for(OccludedArray::const_iterator i=occluded_cache.begin(); i!=occluded_cache.end(); ++i)
- i->renderable->setup_frame(renderer);
+ for(const OccludedRenderable &o: occluded_cache)
+ o.renderable->setup_frame(renderer);
}
void OccludedScene::finish_frame()
{
- for(OccludedArray::const_iterator i=occluded_cache.begin(); i!=occluded_cache.end(); ++i)
- i->renderable->finish_frame();
+ for(const OccludedRenderable &o: occluded_cache)
+ o.renderable->finish_frame();
}
void OccludedScene::render(Renderer &renderer, Tag tag) const
const Camera *camera = renderer.get_camera();
if(!camera)
{
- for(OccludedArray::const_iterator i=occluded_cache.begin(); i!=occluded_cache.end(); ++i)
- renderer.render(*i->renderable, tag);
+ for(const OccludedRenderable &o: occluded_cache)
+ renderer.render(*o.renderable, tag);
return;
}
// Perform frustum culling and render any major occluders
bool use_frustum = setup_frustum(renderer);
- for(OccludedArray::iterator i=occluded_cache.begin(); (i!=occluded_cache.end() && i->renderable); ++i)
+ for(auto i=occluded_cache.begin(); (i!=occluded_cache.end() && i->renderable); ++i)
{
i->in_frustum = (!use_frustum || !frustum_cull(*i->renderable));
if(!i->in_frustum)
}
// Move all objects within the frustum to the beginning of the array
- for(OccludedArray::iterator i=occluded_cache.begin(), j=i+renderables.size()-1; i!=j; )
+ for(auto i=occluded_cache.begin(), j=i+renderables.size()-1; i!=j; )
{
if(i->in_frustum)
++i;
Renderer::Push push(renderer);
renderer.set_shader_program(&bounding_shader);
- glColorMask(false, false, false, false);
- glDepthMask(false);
+ renderer.set_blend(&no_color_write);
+ // XXX Preserve existing depth test predicate
+ renderer.set_depth_test(&no_depth_write);
// Fire off the occlusion queries
- for(OccludedArray::const_iterator i=occluded_cache.begin(); (i!=occluded_cache.end() && i->in_frustum); ++i)
+ for(auto i=occluded_cache.begin(); (i!=occluded_cache.end() && i->in_frustum); ++i)
if(!i->occluder)
{
- glBeginQuery(GL_ANY_SAMPLES_PASSED, i->query);
+ QueryPool::Activate activate_query(renderer, queries, i-occluded_cache.begin());
Renderer::Push push2(renderer);
renderer.transform(Matrix(*i->renderable->get_matrix())
.translate(i->bounding_sphere->get_center())
.scale(i->bounding_sphere->get_radius()));
bounding_mesh.draw(renderer);
- glEndQuery(GL_ANY_SAMPLES_PASSED);
}
-
- glColorMask(true, true, true, true);
- glDepthMask(true);
}
// Render anything that has a chance of being visible
- for(OccludedArray::const_iterator i=occluded_cache.begin(); (i!=occluded_cache.end() && i->in_frustum); ++i)
- if(!i->occluder)
- {
- unsigned any_passed = 0;
- glGetQueryObjectuiv(i->query, GL_QUERY_RESULT, &any_passed);
- if(any_passed)
- renderer.render(*i->renderable, tag);
- }
+ for(auto i=occluded_cache.begin(); (i!=occluded_cache.end() && i->in_frustum); ++i)
+ if(!i->occluder && queries.get_result(i-occluded_cache.begin()))
+ renderer.render(*i->renderable, tag);
}
-
-OccludedScene::OccludedRenderable::OccludedRenderable():
- renderable(0),
- bounding_sphere(0),
- in_frustum(false),
- occluder(false),
- query(0)
-{ }
-
} // namespace GL
} // namespace Msp