void disable_for_pass(const Tag &);
virtual const Matrix *get_matrix() const { return renderable.get_matrix(); }
+
+ virtual void setup_frame() const { renderable.setup_frame(); }
+ virtual void finish_frame() const { renderable.finish_frame(); }
};
} // namespace GL
}
}
+void InstanceScene::setup_frame() const
+{
+ for(InstanceMap::const_iterator i=renderables.begin(); i!=renderables.end(); ++i)
+ for(RenderableSet::const_iterator j=i->second.begin(); j!=i->second.end(); ++j)
+ (*j)->setup_frame();
+}
+
+void InstanceScene::finish_frame() const
+{
+ for(InstanceMap::const_iterator i=renderables.begin(); i!=renderables.end(); ++i)
+ for(RenderableSet::const_iterator j=i->second.begin(); j!=i->second.end(); ++j)
+ (*j)->finish_frame();
+}
+
void InstanceScene::render(Renderer &renderer, const Tag &tag) const
{
for(InstanceMap::const_iterator i=renderables.begin(); i!=renderables.end(); ++i)
virtual void add(const Renderable &);
virtual void remove(const Renderable &);
+ virtual void setup_frame() const;
+ virtual void finish_frame() const;
+
using Scene::render;
virtual void render(Renderer &, const Tag &tag = Tag()) const;
};
renderables.insert(i, &r);
}
+void OrderedScene::setup_frame() const
+{
+ for(RenderableList::const_iterator i=renderables.begin(); i!=renderables.end(); ++i)
+ (*i)->setup_frame();
+}
+
+void OrderedScene::finish_frame() const
+{
+ for(RenderableList::const_iterator i=renderables.begin(); i!=renderables.end(); ++i)
+ (*i)->finish_frame();
+}
+
void OrderedScene::render(Renderer &renderer, const Tag &tag) const
{
for(RenderableList::const_iterator i=renderables.begin(); i!=renderables.end(); ++i)
void insert(unsigned, const Renderable &);
void insert_after(const Renderable &, const Renderable &);
+ virtual void setup_frame() const;
+ virtual void finish_frame() const;
+
using Scene::render;
virtual void render(Renderer &, const Tag & = Tag()) const;
};
height(h),
hdr(d),
samples(0),
- target_ms(0)
+ target_ms(0),
+ in_frame(false)
{
target[0] = 0;
target[1] = 0;
create_targets(false);
}
+void Pipeline::setup_frame() const
+{
+ in_frame = true;
+ for(vector<Slot>::const_iterator i=renderables.begin(); i!=renderables.end(); ++i)
+ i->renderable->setup_frame();
+}
+
+void Pipeline::finish_frame() const
+{
+ in_frame = false;
+ for(vector<Slot>::const_iterator i=renderables.begin(); i!=renderables.end(); ++i)
+ i->renderable->finish_frame();
+}
+
void Pipeline::render(const Tag &tag) const
{
if(tag.id)
if(tag.id)
return;
+ bool was_in_frame = in_frame;
+ if(!in_frame)
+ setup_frame();
+
if(target[0])
{
Framebuffer &fbo = (samples ? target_ms->fbo : target[0]->fbo);
Framebuffer::unbind();
}
+
+ if(!was_in_frame)
+ finish_frame();
}
void Pipeline::create_targets(bool recreate)
unsigned samples;
RenderTarget *target[2];
MultisampleTarget *target_ms;
+ mutable bool in_frame;
public:
Pipeline(unsigned, unsigned, bool = false);
void remove_renderable(const Renderable &);
void add_postprocessor(PostProcessor &);
+ virtual void setup_frame() const;
+ virtual void finish_frame() const;
+
virtual void render(const Tag &tag = Tag()) const;
virtual void render(Renderer &, const Tag &tag = Tag()) const;
The render methods take a Tag to identify a render pass. It is most commonly
used together with Techniques and Pipelines to implement multipass rendering.
+
+The setup_frame and finish_frame methods provide a mechanism for performing
+once-per-frame operations. This is most useful for effects, which may need to
+do auxiliary rendering. With complex rendering hierarchies, these methods may
+be called multiple times for one frame, but it's guaranteed that no rendering
+will occur before a setup_frame call or after a finish_frame call.
*/
class Renderable
{
matrix exists. */
virtual const Matrix *get_matrix() const { return 0; }
+ /** Called when starting to render a new frame. */
+ virtual void setup_frame() const { }
+
+ /** Called when a complete frame has been rendered. */
+ virtual void finish_frame() const { }
+
/** Renders the renderable without a renderer. This can be convenient in
some simple cases, but most renderables don't need to implement this
method. */
renderables.erase(&r);
}
+void SimpleScene::setup_frame() const
+{
+ for(RenderableSet::const_iterator i=renderables.begin(); i!=renderables.end(); ++i)
+ (*i)->setup_frame();
+}
+
+void SimpleScene::finish_frame() const
+{
+ for(RenderableSet::const_iterator i=renderables.begin(); i!=renderables.end(); ++i)
+ (*i)->finish_frame();
+}
+
void SimpleScene::render(Renderer &renderer, const Tag &tag) const
{
for(RenderableSet::const_iterator i=renderables.begin(); i!=renderables.end(); ++i)
virtual void add(const Renderable &);
virtual void remove(const Renderable &);
+ virtual void setup_frame() const;
+ virtual void finish_frame() const;
+
using Scene::render;
virtual void render(Renderer &, const Tag & = Tag()) const;
};