The old API is now deprecated and will eventually go away. There are
two reasons for this change:
1. Pipeline was a sort of pseudo-scene, and in many simple use cases it
was not clear which should be used to hold Renderables. Scenes are
intended as grouping primitives.
2. It was possible to add multiple passes with the same tag and different
rendering state, but there was no way to add a Renderable for only one of
them. This led to tags doubling as a way to filter different passes at
the level of individual Renderables. The intended purpose of tags is to
select between different presentations of a Renderable.
Pipeline::Pass &Pipeline::add_pass(const Tag &tag)
{
Pipeline::Pass &Pipeline::add_pass(const Tag &tag)
{
- passes.push_back(Pass(tag));
+ passes.push_back(Pass(tag, 0));
+Pipeline::Pass &Pipeline::add_pass(const Tag &tag, const Renderable &r)
+{
+ passes.push_back(Pass(tag, &r));
+ return passes.back();
+}
+
void Pipeline::add_postprocessor(PostProcessor &pp)
{
postproc.push_back(&pp);
void Pipeline::add_postprocessor(PostProcessor &pp)
{
postproc.push_back(&pp);
void Pipeline::setup_frame() const
{
in_frame = true;
void Pipeline::setup_frame() const
{
in_frame = true;
+ for(PassList::const_iterator i=passes.begin(); i!=passes.end(); ++i)
+ if(const Renderable *renderable = i->get_renderable())
+ renderable->setup_frame();
for(vector<Slot>::const_iterator i=renderables.begin(); i!=renderables.end(); ++i)
i->renderable->setup_frame();
}
for(vector<Slot>::const_iterator i=renderables.begin(); i!=renderables.end(); ++i)
i->renderable->setup_frame();
}
void Pipeline::finish_frame() const
{
in_frame = false;
void Pipeline::finish_frame() const
{
in_frame = false;
+ for(PassList::const_iterator i=passes.begin(); i!=passes.end(); ++i)
+ if(const Renderable *renderable = i->get_renderable())
+ renderable->finish_frame();
for(vector<Slot>::const_iterator i=renderables.begin(); i!=renderables.end(); ++i)
i->renderable->finish_frame();
}
for(vector<Slot>::const_iterator i=renderables.begin(); i!=renderables.end(); ++i)
i->renderable->finish_frame();
}
renderer.set_lighting(i->get_lighting());
renderer.set_clipping(i->get_clipping());
renderer.set_lighting(i->get_lighting());
renderer.set_clipping(i->get_clipping());
+ if(const Renderable *renderable = i->get_renderable())
+ renderer.render(*renderable, i->get_tag());
+
for(vector<Slot>::const_iterator j=renderables.begin(); j!=renderables.end(); ++j)
if(j->passes.empty() || j->passes.count(i->get_tag()))
renderer.render(*j->renderable, i->get_tag());
for(vector<Slot>::const_iterator j=renderables.begin(); j!=renderables.end(); ++j)
if(j->passes.empty() || j->passes.count(i->get_tag()))
renderer.render(*j->renderable, i->get_tag());
-Pipeline::Pass::Pass(const Tag &t):
+Pipeline::Pass::Pass(const Tag &t, const Renderable *r):
tag(t),
lighting(0),
depth_test(0),
blend(0),
tag(t),
lighting(0),
depth_test(0),
blend(0),
+ clipping(0),
+ renderable(r)
{ }
void Pipeline::Pass::set_lighting(const Lighting *l)
{ }
void Pipeline::Pass::set_lighting(const Lighting *l)
/**
Encapsulates all of the information used to produce a complete image in the
/**
Encapsulates all of the information used to produce a complete image in the
-framebuffer. This is the highest level rendering class, combining Renderables
-with a camera, lights and some other influential objects.
+framebuffer. This is the highest level rendering class.
-A Pipeline is also a Renderable itself. Externally, it only exposes the
-default pass. Internally, it can hold any number of passes, which are invoked
-in sequence when rendering the default pass is requested. Each pass can have a
-Lighting, a DepthTest and a Blend to control how it is rendered.
+A Pipeline contains a sequence of passes. Each pass has a Renderable along
+with Lighting, Clipping, DepthTest and Blend states. Scenes can be used to
+organize Renderables within a pass. A Camera can be specified for the entire
+Pipeline.
+
+A Pipeline is also a Renderable itself. It will only respond to the default
+pass. The Renderables within the Pipeline will be invoked with whatever tags
+were specified when adding them.
A Pipeline's render method should normally be called without a Renderer; it
will create one itself, using the camera specified for the Pipeline. If a
Renderer is passed, its camera will be used instead.
A Pipeline's render method should normally be called without a Renderer; it
will create one itself, using the camera specified for the Pipeline. If a
Renderer is passed, its camera will be used instead.
-Renderables are rendered in the order they were added to the Pipeline. While
-it's possible to remove renderables as well, using a Scene is recommended if
-frequent add/remove operations are needed.
-
-Pipelines may have post-processors to apply full-screen effects. Framebuffer
-objects are automatically used to pass render results to the post-processors.
-High dynamic range and multisample rendering can also be used.
+PostProcessors can be applied after all of the passes in the Pipeline have been
+rendered. Framebuffer objects are automatically used to pass render results to
+the PostProcessors. High dynamic range and multisample rendering can be
+requested for increased quality.
*/
class Pipeline: public Renderable
{
*/
class Pipeline: public Renderable
{
const DepthTest *depth_test;
const Blend *blend;
const Clipping *clipping;
const DepthTest *depth_test;
const Blend *blend;
const Clipping *clipping;
+ const Renderable *renderable;
+ Pass(const Tag &, const Renderable *);
const Tag &get_tag() const { return tag; }
const Tag &get_tag() const { return tag; }
const DepthTest *get_depth_test() const { return depth_test; }
const Blend *get_blend() const { return blend; }
const Clipping *get_clipping() const { return clipping; }
const DepthTest *get_depth_test() const { return depth_test; }
const Blend *get_blend() const { return blend; }
const Clipping *get_clipping() const { return clipping; }
+ const Renderable *get_renderable() const { return renderable; }
void set_multisample(unsigned);
void set_camera(const Camera *);
void set_multisample(unsigned);
void set_camera(const Camera *);
Pass &add_pass(const Tag &tag);
Pass &add_pass(const Tag &tag);
void add_renderable(const Renderable &);
void add_renderable_for_pass(const Renderable &, const Tag &);
void remove_renderable(const Renderable &);
void add_renderable(const Renderable &);
void add_renderable_for_pass(const Renderable &, const Tag &);
void remove_renderable(const Renderable &);
+
+ /** Adds a pass to the pipeline. It's permissible to add the same
+ Renderable multiple times. */
+ Pass &add_pass(const Tag &, const Renderable &);
+
+ /** Adds a postprocessor to the pipeline. */
void add_postprocessor(PostProcessor &);
virtual void setup_frame() const;
void add_postprocessor(PostProcessor &);
virtual void setup_frame() const;