From: Mikko Rasa Date: Sun, 14 Aug 2016 20:29:49 +0000 (+0300) Subject: Add a new API to Pipeline that ties Renderables and passes together X-Git-Url: http://git.tdb.fi/?a=commitdiff_plain;h=aa7955f9adfab4395b00fba84fa2d7c286a83c70;p=libs%2Fgl.git Add a new API to Pipeline that ties Renderables and passes together 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. --- diff --git a/source/pipeline.cpp b/source/pipeline.cpp index 1833001f..a27058ef 100644 --- a/source/pipeline.cpp +++ b/source/pipeline.cpp @@ -78,7 +78,7 @@ void Pipeline::set_camera(const Camera *c) Pipeline::Pass &Pipeline::add_pass(const Tag &tag) { - passes.push_back(Pass(tag)); + passes.push_back(Pass(tag, 0)); return passes.back(); } @@ -117,6 +117,12 @@ void Pipeline::remove_renderable(const Renderable &r) } } +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); @@ -134,6 +140,9 @@ void Pipeline::add_postprocessor(PostProcessor &pp) 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::const_iterator i=renderables.begin(); i!=renderables.end(); ++i) i->renderable->setup_frame(); } @@ -141,6 +150,9 @@ void Pipeline::setup_frame() const 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::const_iterator i=renderables.begin(); i!=renderables.end(); ++i) i->renderable->finish_frame(); } @@ -180,6 +192,9 @@ void Pipeline::render(Renderer &renderer, const Tag &tag) const 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::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()); @@ -238,12 +253,13 @@ void Pipeline::create_targets(unsigned recreate) } -Pipeline::Pass::Pass(const Tag &t): +Pipeline::Pass::Pass(const Tag &t, const Renderable *r): tag(t), lighting(0), depth_test(0), blend(0), - clipping(0) + clipping(0), + renderable(r) { } void Pipeline::Pass::set_lighting(const Lighting *l) diff --git a/source/pipeline.h b/source/pipeline.h index 2c61a537..d07e6431 100644 --- a/source/pipeline.h +++ b/source/pipeline.h @@ -20,25 +20,25 @@ class PostProcessor; /** 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. -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 { @@ -51,9 +51,10 @@ public: const DepthTest *depth_test; const Blend *blend; const Clipping *clipping; + const Renderable *renderable; public: - Pass(const Tag &); + Pass(const Tag &, const Renderable *); const Tag &get_tag() const { return tag; } @@ -65,6 +66,7 @@ public: 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; } }; private: @@ -116,11 +118,17 @@ public: void set_multisample(unsigned); void set_camera(const Camera *); + // Deprecated 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 &); + + /** 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;