]> git.tdb.fi Git - libs/gl.git/commitdiff
Rename Pipeline to Sequence
authorMikko Rasa <tdb@tdb.fi>
Wed, 14 Apr 2021 11:42:11 +0000 (14:42 +0300)
committerMikko Rasa <tdb@tdb.fi>
Wed, 14 Apr 2021 12:24:27 +0000 (15:24 +0300)
Pipeline::Pass is now Sequence::Step.  These better match what the
classes do.

17 files changed:
demos/desertpillars.cpp
source/builders/pipelinebuilder.cpp [deleted file]
source/builders/pipelinebuilder.h [deleted file]
source/builders/pipelinetemplate.cpp [deleted file]
source/builders/pipelinetemplate.h [deleted file]
source/builders/sequencebuilder.cpp [new file with mode: 0644]
source/builders/sequencebuilder.h [new file with mode: 0644]
source/builders/sequencetemplate.cpp [new file with mode: 0644]
source/builders/sequencetemplate.h [new file with mode: 0644]
source/effects/environmentmap.h
source/materials/light.h
source/render/pipeline.cpp [deleted file]
source/render/pipeline.h [deleted file]
source/render/sequence.cpp [new file with mode: 0644]
source/render/sequence.h [new file with mode: 0644]
source/resources/resources.cpp
tools/viewer.cpp

index 89a0fe51333c9d97cd31d22b54dd6a57bbc9c9a7..d741beea5390b0eb8307fdb78d401fb47c62b314 100644 (file)
@@ -17,7 +17,7 @@
 #include <msp/gl/mesh.h>
 #include <msp/gl/meshbuilder.h>
 #include <msp/gl/object.h>
 #include <msp/gl/mesh.h>
 #include <msp/gl/meshbuilder.h>
 #include <msp/gl/object.h>
-#include <msp/gl/pipeline.h>
+#include <msp/gl/sequence.h>
 #include <msp/gl/program.h>
 #include <msp/gl/renderer.h>
 #include <msp/gl/resources.h>
 #include <msp/gl/program.h>
 #include <msp/gl/renderer.h>
 #include <msp/gl/resources.h>
@@ -46,7 +46,7 @@ including:
 - Shadow mapping
 - Environment mapped reflections
 - Skybox using a cube map texture
 - Shadow mapping
 - Environment mapped reflections
 - Skybox using a cube map texture
-- Effects with nested pipelines
+- Effects with nested sequences
 - Complex multitexturing
 - Shader-based deformations
 - Creating a normalmapped texture through rendering
 - Complex multitexturing
 - Shader-based deformations
 - Creating a normalmapped texture through rendering
@@ -132,7 +132,7 @@ private:
        GL::EnvironmentMap *env_cube;
 
        GL::WindowView view;
        GL::EnvironmentMap *env_cube;
 
        GL::WindowView view;
-       GL::Pipeline pipeline;
+       GL::Sequence sequence;
        GL::Camera camera;
        GL::SimpleScene sky_scene;
        GL::InstanceScene scene;
        GL::Camera camera;
        GL::SimpleScene sky_scene;
        GL::InstanceScene scene;
@@ -142,7 +142,7 @@ private:
        GL::Bloom bloom;
        GL::ColorCurve colorcurve;
 
        GL::Bloom bloom;
        GL::ColorCurve colorcurve;
 
-       GL::Pipeline env_pipeline;
+       GL::Sequence env_sequence;
 
        Time::TimeStamp last_tick;
        float camera_angle;
 
        Time::TimeStamp last_tick;
        float camera_angle;
@@ -166,7 +166,7 @@ public:
 
 private:
        void setup_view();
 
 private:
        void setup_view();
-       void create_pipeline();
+       void create_sequence();
        void create_skybox();
        static void create_skybox_face(GL::TextureCube &, GL::TextureCubeFace);
        void create_tiles_texture();
        void create_skybox();
        static void create_skybox_face(GL::TextureCube &, GL::TextureCubeFace);
        void create_tiles_texture();
@@ -299,11 +299,11 @@ DesertPillars::DesertPillars(int argc, char **argv):
        cube_shprog(cube_src),
        cube_shadow_shprog(string(cube_src)+cube_shadow_src_tail),
        view(window, gl_context),
        cube_shprog(cube_src),
        cube_shadow_shprog(string(cube_src)+cube_shadow_src_tail),
        view(window, gl_context),
-       pipeline(view),
+       sequence(view),
        shadow_scene(resources, 2048, scene, light),
        bloom(resources, window.get_width(), window.get_height()),
        colorcurve(resources),
        shadow_scene(resources, 2048, scene, light),
        bloom(resources, window.get_width(), window.get_height()),
        colorcurve(resources),
-       env_pipeline(512, 512),
+       env_sequence(512, 512),
        camera_angle(0),
        camera_stopped(false),
        cube_angle(0),
        camera_angle(0),
        camera_stopped(false),
        cube_angle(0),
@@ -319,7 +319,7 @@ DesertPillars::DesertPillars(int argc, char **argv):
        keyboard.signal_button_press.connect(sigc::bind_return(sigc::mem_fun(this, &DesertPillars::key_press), false));
 
        setup_view();
        keyboard.signal_button_press.connect(sigc::bind_return(sigc::mem_fun(this, &DesertPillars::key_press), false));
 
        setup_view();
-       create_pipeline();
+       create_sequence();
        create_skybox();
        create_ground();
        create_pillars();
        create_skybox();
        create_ground();
        create_pillars();
@@ -340,13 +340,13 @@ void DesertPillars::setup_view()
        camera.set_up_direction(GL::Vector3(0, 0, 1));
        camera.set_depth_clip(1, 50);
        view.set_camera(&camera);
        camera.set_up_direction(GL::Vector3(0, 0, 1));
        camera.set_depth_clip(1, 50);
        view.set_camera(&camera);
-       view.set_content(&pipeline);
+       view.set_content(&sequence);
 }
 
 }
 
-void DesertPillars::create_pipeline()
+void DesertPillars::create_sequence()
 {
 {
-       pipeline.set_multisample(8);
-       pipeline.set_hdr(true);
+       sequence.set_multisample(8);
+       sequence.set_hdr(true);
 
        /* The shadow map is focused on the part of the scene that contains the
        pillars and the cube.  Making the ground cast shadows as well would result
 
        /* The shadow map is focused on the part of the scene that contains the
        pillars and the cube.  Making the ground cast shadows as well would result
@@ -362,26 +362,26 @@ void DesertPillars::create_pipeline()
        lighting.set_ambient(GL::Color(0.2));
 
        // The skybox is rendered first
        lighting.set_ambient(GL::Color(0.2));
 
        // The skybox is rendered first
-       pipeline.add_pass(0, sky_scene);
+       sequence.add_pass(0, sky_scene);
 
 
-       GL::Pipeline::Pass *pass = &pipeline.add_pass(0, shadow_scene);
+       GL::Sequence::Pass *pass = &sequence.add_pass(0, shadow_scene);
        pass->set_lighting(&lighting);
        pass->set_depth_test(&GL::DepthTest::lequal());
 
        /* A bloom filter enhances the realism of bright surfaces, even if there
        isn't anything really glowy in the scene. */
        bloom.set_strength(0.3);
        pass->set_lighting(&lighting);
        pass->set_depth_test(&GL::DepthTest::lequal());
 
        /* A bloom filter enhances the realism of bright surfaces, even if there
        isn't anything really glowy in the scene. */
        bloom.set_strength(0.3);
-       pipeline.add_postprocessor(bloom);
+       sequence.add_postprocessor(bloom);
 
        /* Lighting calculations are best done in linear color space, so the final
        image must be converted to srgb for display. */
        colorcurve.set_srgb();
 
        /* Lighting calculations are best done in linear color space, so the final
        image must be converted to srgb for display. */
        colorcurve.set_srgb();
-       pipeline.add_postprocessor(colorcurve);
+       sequence.add_postprocessor(colorcurve);
 
 
-       /* Initialize a second pipeline to render the environment map.  It has the
+       /* Initialize a second sequence to render the environment map.  It has the
        same renderables and passes, but no postprocessors or camera. */
        same renderables and passes, but no postprocessors or camera. */
-       env_pipeline.add_pass(0, sky_scene);
-       pass = &env_pipeline.add_pass(0, shadow_scene);
+       env_sequence.add_pass(0, sky_scene);
+       pass = &env_sequence.add_pass(0, shadow_scene);
        pass->set_lighting(&lighting);
        pass->set_depth_test(&GL::DepthTest::lequal());
 }
        pass->set_lighting(&lighting);
        pass->set_depth_test(&GL::DepthTest::lequal());
 }
@@ -778,7 +778,7 @@ void DesertPillars::create_cube()
        cube_data.object = new GL::Object(cube_data.mesh, &cube_tech);
 
        cube = new Cube(*cube_data.object);
        cube_data.object = new GL::Object(cube_data.mesh, &cube_tech);
 
        cube = new Cube(*cube_data.object);
-       env_cube = new GL::EnvironmentMap(resources, 512, *cube, env_pipeline);
+       env_cube = new GL::EnvironmentMap(resources, 512, *cube, env_sequence);
        scene.add(*env_cube);
 }
 
        scene.add(*env_cube);
 }
 
diff --git a/source/builders/pipelinebuilder.cpp b/source/builders/pipelinebuilder.cpp
deleted file mode 100644 (file)
index 12a5312..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-#include <msp/core/algorithm.h>
-#include <msp/core/maputils.h>
-#include "error.h"
-#include "pipeline.h"
-#include "pipelinebuilder.h"
-#include "pipelinetemplate.h"
-#include "renderbuffer.h"
-
-using namespace std;
-
-namespace Msp {
-namespace GL {
-
-PipelineBuilder::PipelineBuilder(const PipelineTemplate &t):
-       tmpl(t)
-{
-       const vector<PipelineTemplate::Pass> &passes = tmpl.get_passes();
-       for(vector<PipelineTemplate::Pass>::const_iterator i=passes.begin(); i!=passes.end(); ++i)
-               renderables[i->renderable_name] = 0;
-       const vector<PipelineTemplate::PostProcessor> &postprocs = tmpl.get_postprocessors();
-       for(PipelineTemplate::PostProcessorArray::const_iterator i=postprocs.begin(); i!=postprocs.end(); ++i)
-               if(!i->slot_name.empty())
-                       postprocessors[i->slot_name] = 0;
-}
-
-void PipelineBuilder::set_renderable(const string &name, Renderable &rend)
-{
-       get_item(renderables, name) = &rend;
-}
-
-void PipelineBuilder::set_postprocessor(const string &name, PostProcessor &pproc)
-{
-       get_item(postprocessors, name) = &pproc;
-}
-
-void PipelineBuilder::build(Pipeline &pipeline) const
-{
-       pipeline.set_hdr(tmpl.get_hdr());
-       pipeline.set_alpha(tmpl.get_alpha());
-       unsigned samples = min(tmpl.get_maximum_multisample(), Renderbuffer::get_max_samples());
-       if(samples<tmpl.get_required_multisample())
-               throw invalid_operation("PipelineBuilder::build");
-
-       pipeline.set_multisample(samples);
-
-       const PipelineTemplate::PassArray &passes = tmpl.get_passes();
-       for(PipelineTemplate::PassArray::const_iterator i=passes.begin(); i!=passes.end(); ++i)
-       {
-               Renderable *renderable = get_item(renderables, i->renderable_name);
-               if(!renderable)
-                       continue;
-
-               Pipeline::Pass &pass = pipeline.add_pass(i->tag, *renderable);
-               pass.set_blend(i->blend.get());
-               pass.set_depth_test(i->depth_test.get());
-               pass.set_lighting(i->lighting.get());
-       }
-
-       const PipelineTemplate::PostProcessorArray &postprocs = tmpl.get_postprocessors();
-       for(PipelineTemplate::PostProcessorArray::const_iterator i=postprocs.begin(); i!=postprocs.end(); ++i)
-       {
-               PostProcessor *proc = 0;
-               if(!i->slot_name.empty())
-                       proc = get_item(postprocessors, i->slot_name);
-               if(proc)
-                       pipeline.add_postprocessor(*proc);
-               else if(i->postprocessor_template)
-               {
-                       proc = i->postprocessor_template->create(tmpl.get_resources(), pipeline.get_width(), pipeline.get_height());
-                       if(proc)
-                               pipeline.add_postprocessor_owned(proc);
-               }
-       }
-}
-
-Pipeline *PipelineBuilder::build(unsigned w, unsigned h) const
-{
-       RefPtr<Pipeline> pipeline = new Pipeline(w, h);
-       build(*pipeline);
-       return pipeline.release();
-}
-
-Pipeline *PipelineBuilder::build(const View &view) const
-{
-       RefPtr<Pipeline> pipeline = new Pipeline(view);
-       build(*pipeline);
-       return pipeline.release();
-}
-
-Pipeline *PipelineBuilder::build(const Framebuffer &fbo) const
-{
-       RefPtr<Pipeline> pipeline = new Pipeline(fbo);
-       build(*pipeline);
-       return pipeline.release();
-}
-
-} // namespace GL
-} // namespace Msp
diff --git a/source/builders/pipelinebuilder.h b/source/builders/pipelinebuilder.h
deleted file mode 100644 (file)
index ab0dc4b..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-#ifndef PIPELINEBUILDER_H_
-#define PIPELINEBUILDER_H_
-
-#include <map>
-#include <string>
-
-namespace Msp {
-namespace GL {
-
-class Framebuffer;
-class Pipeline;
-class PipelineTemplate;
-class PostProcessor;
-class Renderable;
-class View;
-
-class PipelineBuilder
-{
-private:
-       const PipelineTemplate &tmpl;
-       std::map<std::string, Renderable *> renderables;
-       std::map<std::string, PostProcessor *> postprocessors;
-
-public:
-       PipelineBuilder(const PipelineTemplate &);
-
-       void set_renderable(const std::string &, Renderable &);
-       void set_postprocessor(const std::string &, PostProcessor &);
-
-       void build(Pipeline &) const;
-       Pipeline *build(unsigned, unsigned) const;
-       Pipeline *build(const View &) const;
-       Pipeline *build(const Framebuffer &) const;
-};
-
-} // namespace GL
-} // namespace Msp
-
-#endif
diff --git a/source/builders/pipelinetemplate.cpp b/source/builders/pipelinetemplate.cpp
deleted file mode 100644 (file)
index de91450..0000000
+++ /dev/null
@@ -1,202 +0,0 @@
-#include <msp/core/maputils.h>
-#include <msp/datafile/collection.h>
-#include "ambientocclusion.h"
-#include "blend.h"
-#include "bloom.h"
-#include "colorcurve.h"
-#include "lighting.h"
-#include "pipelinetemplate.h"
-#include "resources.h"
-#include "tests.h"
-
-using namespace std;
-
-namespace Msp {
-namespace GL {
-
-PipelineTemplate::PipelineTemplate():
-       resources(0),
-       hdr(false),
-       alpha(false),
-       required_multisample(0),
-       max_multisample(0)
-{ }
-
-PipelineTemplate::~PipelineTemplate()
-{
-       for(PostProcessorArray::iterator i=postprocessors.begin(); i!=postprocessors.end(); ++i)
-               delete i->postprocessor_template;
-}
-
-Resources &PipelineTemplate::get_resources() const
-{
-       if(!resources)  
-               throw logic_error("no resources");
-       return *resources;
-}
-
-
-PipelineTemplate::PostProcessorRegistry &PipelineTemplate::get_postprocessor_registry()
-{
-       static PostProcessorRegistry registry;
-       static bool initialized = false;
-       if(!initialized)
-       {
-               registry.register_type<AmbientOcclusion>("ambient_occlusion");
-               registry.register_type<Bloom>("bloom");
-               registry.register_type<ColorCurve>("colorcurve");
-               initialized = true;
-       }
-       return registry;
-}
-
-
-PipelineTemplate::Pass::~Pass()
-{ }
-
-
-PipelineTemplate::PostProcessor::PostProcessor(GL::PostProcessor::Template *ppt):
-       postprocessor_template(ppt)
-{ }
-
-
-PipelineTemplate::PostProcLoader::PostProcLoader()
-{
-       get_postprocessor_registry().invoke_all(*this);
-}
-
-
-PipelineTemplate::Loader::Loader(PipelineTemplate &t, Collection &c):
-       DataFile::CollectionObjectLoader<PipelineTemplate, Resources>(t, &c)
-{
-       add("hdr", &PipelineTemplate::hdr);
-       add("alpha", &PipelineTemplate::alpha);
-       add("multisample", &Loader::multisample);
-       add("multisample", &Loader::multisample_range);
-       add("pass", &Loader::pass);
-       add("postprocessor", &Loader::postprocessor);
-
-       obj.resources = &c;
-}
-
-void PipelineTemplate::Loader::postprocessor_loaded()
-{
-       obj.postprocessors.push_back(get_postprocessor_template());
-}
-
-void PipelineTemplate::Loader::multisample(unsigned samples)
-{
-       obj.required_multisample = samples;
-       obj.max_multisample = samples;
-}
-
-void PipelineTemplate::Loader::multisample_range(unsigned req, unsigned max)
-{
-       obj.required_multisample = req;
-       obj.max_multisample = max;
-}
-
-void PipelineTemplate::Loader::pass(const string &tag, const string &rend)
-{
-       Pass pss;;
-       pss.tag = tag;
-       pss.renderable_name = rend;
-       if(coll)
-               load_sub(pss, *coll);
-       else
-               load_sub(pss);
-
-       obj.passes.push_back(pss);
-}
-
-void PipelineTemplate::Loader::postprocessor(const string &slot)
-{
-       PostProcLoader ldr;
-       load_sub_with(ldr);
-       PostProcessor pp;
-       pp.postprocessor_template = ldr.get_postprocessor_template();
-       pp.slot_name = slot;
-       obj.postprocessors.push_back(pp);
-}
-
-
-PipelineTemplate::Pass::Loader::Loader(Pass &p):
-       DataFile::CollectionObjectLoader<Pass>(p, 0)
-{
-       init();
-}
-
-PipelineTemplate::Pass::Loader::Loader(Pass &p, Collection &c):
-       DataFile::CollectionObjectLoader<Pass>(p, &c)
-{
-       init();
-}
-
-void PipelineTemplate::Pass::Loader::init()
-{
-       add("blend", &Loader::blend);
-       add("blend", &Loader::blend_predefined);
-       add("depth_test", &Loader::depth_test);
-       add("depth_test", &Loader::depth_test_predefined);
-       add("lighting", &Loader::lighting);
-       add("lighting", &Loader::lighting_inline);
-}
-
-void PipelineTemplate::Pass::Loader::blend_predefined(const string &name)
-{
-       const Blend *bln = 0;
-       if(name=="alpha")
-               bln = &Blend::alpha();
-       else if(name=="additive")
-               bln = &Blend::additive();
-       else if(name=="additive_alpha")
-               bln = &Blend::additive_alpha();
-       else
-               throw key_error(name);
-
-       obj.blend = bln;
-       obj.blend.keep();
-}
-
-void PipelineTemplate::Pass::Loader::blend(BlendFactor src, BlendFactor dest)
-{
-       obj.blend = new Blend(src, dest);
-}
-
-void PipelineTemplate::Pass::Loader::depth_test_predefined(const string &name)
-{
-       const DepthTest *dtest = 0;
-       if(name=="lequal")
-               dtest = &DepthTest::lequal();
-       else
-               throw key_error(name);
-
-       obj.depth_test = dtest;
-       obj.depth_test.keep();
-}
-
-void PipelineTemplate::Pass::Loader::depth_test(Predicate pred)
-{
-       obj.depth_test = new DepthTest(pred);
-}
-
-void PipelineTemplate::Pass::Loader::lighting_inline()
-{
-       RefPtr<Lighting> lightn = new Lighting;
-       load_sub(*lightn);
-       obj.lighting = lightn;
-}
-
-void PipelineTemplate::Pass::Loader::lighting(const string &name)
-{
-       obj.lighting = &get_collection().get<Lighting>(name);
-       obj.lighting.keep();
-}
-
-/*void PipelineTemplate::Pass::Loader::scene(const string &name)
-{
-       obj.default_renderable = get_collection().get<Scene>(name);
-}*/
-
-} // namespace GL
-} // namespace Msp
diff --git a/source/builders/pipelinetemplate.h b/source/builders/pipelinetemplate.h
deleted file mode 100644 (file)
index 515ebfa..0000000
+++ /dev/null
@@ -1,152 +0,0 @@
-#ifndef PIPELINETEMPLATE_H_
-#define PIPELINETEMPLATE_H_
-
-#include <string>
-#include <vector>
-#include <msp/core/typeregistry.h>
-#include <msp/datafile/objectloader.h>
-#include "blend.h"
-#include "postprocessor.h"
-#include "predicate.h"
-
-namespace Msp {
-namespace GL {
-
-class DepthTest;
-class Lighting;
-
-class PipelineTemplate
-{
-private:
-       class PostProcLoader: virtual public DataFile::Loader
-       {
-       private:
-               template<typename T>
-               struct AddPostProc
-               {
-                       void operator()(const std::string &kw, PostProcLoader &ldr) const { ldr.add(kw, &PostProcLoader::postprocessor<T>); }
-               };
-
-       protected:
-               RefPtr<PostProcessor::Template> postproc;
-
-       public:
-               PostProcLoader();
-
-               PostProcessor::Template *get_postprocessor_template() { return postproc.release(); }
-
-       protected:
-               virtual void postprocessor_loaded() { }
-
-       private:
-               template<typename T>
-               void postprocessor();
-
-               friend class PipelineTemplate;
-       };
-
-public:
-       class Loader: public DataFile::CollectionObjectLoader<PipelineTemplate, Resources>, public PostProcLoader
-       {
-       public:
-               Loader(PipelineTemplate &, Collection &);
-
-               virtual void postprocessor_loaded();
-               void multisample(unsigned);
-               void multisample_range(unsigned, unsigned);
-               void pass(const std::string &, const std::string &);
-               void postprocessor(const std::string &);
-       };
-
-       struct Pass
-       {
-               class Loader: public DataFile::CollectionObjectLoader<Pass>
-               {
-               public:
-                       Loader(Pass &);
-                       Loader(Pass &, Collection &);
-               private:
-                       void init();
-
-                       void blend(BlendFactor, BlendFactor);
-                       void blend_predefined(const std::string &);
-                       void depth_test(Predicate);
-                       void depth_test_predefined(const std::string &);
-                       void lighting(const std::string &);
-                       void lighting_inline();
-                       // TODO requires support for scenes in Resources
-                       //void scene(const std::string &);
-               };
-
-               std::string tag;
-               RefPtr<Lighting> lighting;
-               RefPtr<const DepthTest> depth_test;
-               RefPtr<const Blend> blend;
-               std::string renderable_name;
-               //Renderable *default_renderable;
-
-               ~Pass();
-       };
-
-       struct PostProcessor
-       {
-               GL::PostProcessor::Template *postprocessor_template;
-               std::string slot_name;
-
-               PostProcessor(GL::PostProcessor::Template * = 0);
-       };
-
-       typedef std::vector<Pass> PassArray;
-       typedef std::vector<PostProcessor> PostProcessorArray;
-
-private:
-       typedef TypeRegistry<PostProcLoader::AddPostProc, PostProcLoader &> PostProcessorRegistry;
-
-       Resources *resources;
-       bool hdr;
-       bool alpha;
-       unsigned required_multisample;
-       unsigned max_multisample;
-       PassArray passes;
-       PostProcessorArray postprocessors;
-
-public:
-       PipelineTemplate();
-       ~PipelineTemplate();
-
-       Resources &get_resources() const;
-       bool get_hdr() const { return hdr; }
-       bool get_alpha() const { return alpha; }
-       unsigned get_required_multisample() const { return required_multisample; }
-       unsigned get_maximum_multisample() const { return max_multisample; }
-       const PassArray &get_passes() const { return passes; }
-       const PostProcessorArray &get_postprocessors() const { return postprocessors; }
-
-       template<typename T>
-       static void register_postprocessor(const std::string &);
-private:
-       static PostProcessorRegistry &get_postprocessor_registry();
-};
-
-template<typename T>
-void PipelineTemplate::register_postprocessor(const std::string &kw)
-{
-       get_postprocessor_registry().register_type<T>(kw);
-}
-
-template<typename T>
-void PipelineTemplate::PostProcLoader::postprocessor()
-{
-       if(postproc)
-               throw std::logic_error("Only one postprocessor allowed per slot");
-       RefPtr<typename T::Template> pp = new typename T::Template;
-       load_sub(*pp);
-       postproc = pp;
-       pp = 0;
-       postprocessor_loaded();
-}
-
-} // namespace GL
-} // namespace Msp
-
-#endif
diff --git a/source/builders/sequencebuilder.cpp b/source/builders/sequencebuilder.cpp
new file mode 100644 (file)
index 0000000..0f2a1b5
--- /dev/null
@@ -0,0 +1,98 @@
+#include <msp/core/algorithm.h>
+#include <msp/core/maputils.h>
+#include "error.h"
+#include "renderbuffer.h"
+#include "sequence.h"
+#include "sequencebuilder.h"
+#include "sequencetemplate.h"
+
+using namespace std;
+
+namespace Msp {
+namespace GL {
+
+SequenceBuilder::SequenceBuilder(const SequenceTemplate &t):
+       tmpl(t)
+{
+       const vector<SequenceTemplate::Step> &steps = tmpl.get_steps();
+       for(vector<SequenceTemplate::Step>::const_iterator i=steps.begin(); i!=steps.end(); ++i)
+               renderables[i->renderable_name] = 0;
+       const vector<SequenceTemplate::PostProcessor> &postprocs = tmpl.get_postprocessors();
+       for(SequenceTemplate::PostProcessorArray::const_iterator i=postprocs.begin(); i!=postprocs.end(); ++i)
+               if(!i->slot_name.empty())
+                       postprocessors[i->slot_name] = 0;
+}
+
+void SequenceBuilder::set_renderable(const string &name, Renderable &rend)
+{
+       get_item(renderables, name) = &rend;
+}
+
+void SequenceBuilder::set_postprocessor(const string &name, PostProcessor &pproc)
+{
+       get_item(postprocessors, name) = &pproc;
+}
+
+void SequenceBuilder::build(Sequence &sequence) const
+{
+       sequence.set_hdr(tmpl.get_hdr());
+       sequence.set_alpha(tmpl.get_alpha());
+       unsigned samples = min(tmpl.get_maximum_multisample(), Renderbuffer::get_max_samples());
+       if(samples<tmpl.get_required_multisample())
+               throw invalid_operation("SequenceBuilder::build");
+
+       sequence.set_multisample(samples);
+
+       const vector<SequenceTemplate::Step> &steps = tmpl.get_steps();
+       for(vector<SequenceTemplate::Step>::const_iterator i=steps.begin(); i!=steps.end(); ++i)
+       {
+               Renderable *renderable = get_item(renderables, i->renderable_name);
+               if(!renderable)
+                       continue;
+
+               Sequence::Step &step = sequence.add_step(i->tag, *renderable);
+               step.set_blend(i->blend.get());
+               step.set_depth_test(i->depth_test.get());
+               step.set_lighting(i->lighting.get());
+       }
+
+       const SequenceTemplate::PostProcessorArray &postprocs = tmpl.get_postprocessors();
+       for(SequenceTemplate::PostProcessorArray::const_iterator i=postprocs.begin(); i!=postprocs.end(); ++i)
+       {
+               PostProcessor *proc = 0;
+               if(!i->slot_name.empty())
+                       proc = get_item(postprocessors, i->slot_name);
+               if(proc)
+                       sequence.add_postprocessor(*proc);
+               else if(i->postprocessor_template)
+               {
+                       proc = i->postprocessor_template->create(tmpl.get_resources(), sequence.get_width(), sequence.get_height());
+                       if(proc)
+                               sequence.add_postprocessor_owned(proc);
+               }
+       }
+}
+
+Sequence *SequenceBuilder::build(unsigned w, unsigned h) const
+{
+       RefPtr<Sequence> sequence = new Sequence(w, h);
+       build(*sequence);
+       return sequence.release();
+}
+
+Sequence *SequenceBuilder::build(const View &view) const
+{
+       RefPtr<Sequence> sequence = new Sequence(view);
+       build(*sequence);
+       return sequence.release();
+}
+
+Sequence *SequenceBuilder::build(const Framebuffer &fbo) const
+{
+       RefPtr<Sequence> sequence = new Sequence(fbo);
+       build(*sequence);
+       return sequence.release();
+}
+
+} // namespace GL
+} // namespace Msp
diff --git a/source/builders/sequencebuilder.h b/source/builders/sequencebuilder.h
new file mode 100644 (file)
index 0000000..739cc5e
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef SEQUENCEBUILDER_H_
+#define SEQUENCEBUILDER_H_
+
+#include <map>
+#include <string>
+
+namespace Msp {
+namespace GL {
+
+class Framebuffer;
+class Sequence;
+class SequenceTemplate;
+class PostProcessor;
+class Renderable;
+class View;
+
+class SequenceBuilder
+{
+private:
+       const SequenceTemplate &tmpl;
+       std::map<std::string, Renderable *> renderables;
+       std::map<std::string, PostProcessor *> postprocessors;
+
+public:
+       SequenceBuilder(const SequenceTemplate &);
+
+       void set_renderable(const std::string &, Renderable &);
+       void set_postprocessor(const std::string &, PostProcessor &);
+
+       void build(Sequence &) const;
+       Sequence *build(unsigned, unsigned) const;
+       Sequence *build(const View &) const;
+       Sequence *build(const Framebuffer &) const;
+};
+
+} // namespace GL
+} // namespace Msp
+
+#endif
diff --git a/source/builders/sequencetemplate.cpp b/source/builders/sequencetemplate.cpp
new file mode 100644 (file)
index 0000000..bfab280
--- /dev/null
@@ -0,0 +1,205 @@
+#include <msp/core/maputils.h>
+#include <msp/datafile/collection.h>
+#include "ambientocclusion.h"
+#include "blend.h"
+#include "bloom.h"
+#include "colorcurve.h"
+#include "lighting.h"
+#include "resources.h"
+#include "sequencetemplate.h"
+#include "tests.h"
+
+using namespace std;
+
+namespace Msp {
+namespace GL {
+
+SequenceTemplate::SequenceTemplate():
+       resources(0),
+       hdr(false),
+       alpha(false),
+       required_multisample(0),
+       max_multisample(0)
+{ }
+
+SequenceTemplate::~SequenceTemplate()
+{
+       for(PostProcessorArray::iterator i=postprocessors.begin(); i!=postprocessors.end(); ++i)
+               delete i->postprocessor_template;
+}
+
+Resources &SequenceTemplate::get_resources() const
+{
+       if(!resources)  
+               throw logic_error("no resources");
+       return *resources;
+}
+
+
+SequenceTemplate::PostProcessorRegistry &SequenceTemplate::get_postprocessor_registry()
+{
+       static PostProcessorRegistry registry;
+       static bool initialized = false;
+       if(!initialized)
+       {
+               registry.register_type<AmbientOcclusion>("ambient_occlusion");
+               registry.register_type<Bloom>("bloom");
+               registry.register_type<ColorCurve>("colorcurve");
+               initialized = true;
+       }
+       return registry;
+}
+
+
+SequenceTemplate::Step::~Step()
+{ }
+
+
+SequenceTemplate::PostProcessor::PostProcessor(GL::PostProcessor::Template *ppt):
+       postprocessor_template(ppt)
+{ }
+
+
+SequenceTemplate::PostProcLoader::PostProcLoader()
+{
+       get_postprocessor_registry().invoke_all(*this);
+}
+
+
+SequenceTemplate::Loader::Loader(SequenceTemplate &t, Collection &c):
+       DataFile::CollectionObjectLoader<SequenceTemplate, Resources>(t, &c)
+{
+       add("hdr", &SequenceTemplate::hdr);
+       add("alpha", &SequenceTemplate::alpha);
+       add("multisample", &Loader::multisample);
+       add("multisample", &Loader::multisample_range);
+       add("postprocessor", &Loader::postprocessor);
+       add("step", &Loader::step);
+
+       // Deprecated
+       add("pass", &Loader::step);
+
+       obj.resources = &c;
+}
+
+void SequenceTemplate::Loader::postprocessor_loaded()
+{
+       obj.postprocessors.push_back(get_postprocessor_template());
+}
+
+void SequenceTemplate::Loader::multisample(unsigned samples)
+{
+       obj.required_multisample = samples;
+       obj.max_multisample = samples;
+}
+
+void SequenceTemplate::Loader::multisample_range(unsigned req, unsigned max)
+{
+       obj.required_multisample = req;
+       obj.max_multisample = max;
+}
+
+void SequenceTemplate::Loader::postprocessor(const string &slot)
+{
+       PostProcLoader ldr;
+       load_sub_with(ldr);
+       PostProcessor pp;
+       pp.postprocessor_template = ldr.get_postprocessor_template();
+       pp.slot_name = slot;
+       obj.postprocessors.push_back(pp);
+}
+
+void SequenceTemplate::Loader::step(const string &tag, const string &rend)
+{
+       Step stp;
+       stp.tag = tag;
+       stp.renderable_name = rend;
+       if(coll)
+               load_sub(stp, *coll);
+       else
+               load_sub(stp);
+
+       obj.steps.push_back(stp);
+}
+
+
+SequenceTemplate::Step::Loader::Loader(Step &p):
+       DataFile::CollectionObjectLoader<Step>(p, 0)
+{
+       init();
+}
+
+SequenceTemplate::Step::Loader::Loader(Step &p, Collection &c):
+       DataFile::CollectionObjectLoader<Step>(p, &c)
+{
+       init();
+}
+
+void SequenceTemplate::Step::Loader::init()
+{
+       add("blend", &Loader::blend);
+       add("blend", &Loader::blend_predefined);
+       add("depth_test", &Loader::depth_test);
+       add("depth_test", &Loader::depth_test_predefined);
+       add("lighting", &Loader::lighting);
+       add("lighting", &Loader::lighting_inline);
+}
+
+void SequenceTemplate::Step::Loader::blend_predefined(const string &name)
+{
+       const Blend *bln = 0;
+       if(name=="alpha")
+               bln = &Blend::alpha();
+       else if(name=="additive")
+               bln = &Blend::additive();
+       else if(name=="additive_alpha")
+               bln = &Blend::additive_alpha();
+       else
+               throw key_error(name);
+
+       obj.blend = bln;
+       obj.blend.keep();
+}
+
+void SequenceTemplate::Step::Loader::blend(BlendFactor src, BlendFactor dest)
+{
+       obj.blend = new Blend(src, dest);
+}
+
+void SequenceTemplate::Step::Loader::depth_test_predefined(const string &name)
+{
+       const DepthTest *dtest = 0;
+       if(name=="lequal")
+               dtest = &DepthTest::lequal();
+       else
+               throw key_error(name);
+
+       obj.depth_test = dtest;
+       obj.depth_test.keep();
+}
+
+void SequenceTemplate::Step::Loader::depth_test(Predicate pred)
+{
+       obj.depth_test = new DepthTest(pred);
+}
+
+void SequenceTemplate::Step::Loader::lighting_inline()
+{
+       RefPtr<Lighting> lightn = new Lighting;
+       load_sub(*lightn);
+       obj.lighting = lightn;
+}
+
+void SequenceTemplate::Step::Loader::lighting(const string &name)
+{
+       obj.lighting = &get_collection().get<Lighting>(name);
+       obj.lighting.keep();
+}
+
+/*void SequenceTemplate::Step::Loader::scene(const string &name)
+{
+       obj.default_renderable = get_collection().get<Scene>(name);
+}*/
+
+} // namespace GL
+} // namespace Msp
diff --git a/source/builders/sequencetemplate.h b/source/builders/sequencetemplate.h
new file mode 100644 (file)
index 0000000..5c5b04b
--- /dev/null
@@ -0,0 +1,151 @@
+#ifndef SEQUENCETEMPLATE_H_
+#define SEQUENCETEMPLATE_H_
+
+#include <string>
+#include <vector>
+#include <msp/core/typeregistry.h>
+#include <msp/datafile/objectloader.h>
+#include "blend.h"
+#include "postprocessor.h"
+#include "predicate.h"
+
+namespace Msp {
+namespace GL {
+
+class DepthTest;
+class Lighting;
+
+class SequenceTemplate
+{
+private:
+       class PostProcLoader: virtual public DataFile::Loader
+       {
+       private:
+               template<typename T>
+               struct AddPostProc
+               {
+                       void operator()(const std::string &kw, PostProcLoader &ldr) const { ldr.add(kw, &PostProcLoader::postprocessor<T>); }
+               };
+
+       protected:
+               RefPtr<PostProcessor::Template> postproc;
+
+       public:
+               PostProcLoader();
+
+               PostProcessor::Template *get_postprocessor_template() { return postproc.release(); }
+
+       protected:
+               virtual void postprocessor_loaded() { }
+
+       private:
+               template<typename T>
+               void postprocessor();
+
+               friend class SequenceTemplate;
+       };
+
+public:
+       class Loader: public DataFile::CollectionObjectLoader<SequenceTemplate, Resources>, public PostProcLoader
+       {
+       public:
+               Loader(SequenceTemplate &, Collection &);
+
+               virtual void postprocessor_loaded();
+               void multisample(unsigned);
+               void multisample_range(unsigned, unsigned);
+               void postprocessor(const std::string &);
+               void step(const std::string &, const std::string &);
+       };
+
+       struct Step
+       {
+               class Loader: public DataFile::CollectionObjectLoader<Step>
+               {
+               public:
+                       Loader(Step &);
+                       Loader(Step &, Collection &);
+               private:
+                       void init();
+
+                       void blend(BlendFactor, BlendFactor);
+                       void blend_predefined(const std::string &);
+                       void depth_test(Predicate);
+                       void depth_test_predefined(const std::string &);
+                       void lighting(const std::string &);
+                       void lighting_inline();
+                       // TODO requires support for scenes in Resources
+                       //void scene(const std::string &);
+               };
+
+               std::string tag;
+               RefPtr<Lighting> lighting;
+               RefPtr<const DepthTest> depth_test;
+               RefPtr<const Blend> blend;
+               std::string renderable_name;
+               //Renderable *default_renderable;
+
+               ~Step();
+       };
+
+       struct PostProcessor
+       {
+               GL::PostProcessor::Template *postprocessor_template;
+               std::string slot_name;
+
+               PostProcessor(GL::PostProcessor::Template * = 0);
+       };
+
+       typedef std::vector<PostProcessor> PostProcessorArray;
+
+private:
+       typedef TypeRegistry<PostProcLoader::AddPostProc, PostProcLoader &> PostProcessorRegistry;
+
+       Resources *resources;
+       bool hdr;
+       bool alpha;
+       unsigned required_multisample;
+       unsigned max_multisample;
+       std::vector<Step> steps;
+       PostProcessorArray postprocessors;
+
+public:
+       SequenceTemplate();
+       ~SequenceTemplate();
+
+       Resources &get_resources() const;
+       bool get_hdr() const { return hdr; }
+       bool get_alpha() const { return alpha; }
+       unsigned get_required_multisample() const { return required_multisample; }
+       unsigned get_maximum_multisample() const { return max_multisample; }
+       const std::vector<Step> &get_steps() const { return steps; }
+       const PostProcessorArray &get_postprocessors() const { return postprocessors; }
+
+       template<typename T>
+       static void register_postprocessor(const std::string &);
+private:
+       static PostProcessorRegistry &get_postprocessor_registry();
+};
+
+template<typename T>
+void SequenceTemplate::register_postprocessor(const std::string &kw)
+{
+       get_postprocessor_registry().register_type<T>(kw);
+}
+
+template<typename T>
+void SequenceTemplate::PostProcLoader::postprocessor()
+{
+       if(postproc)
+               throw std::logic_error("Only one postprocessor allowed per slot");
+       RefPtr<typename T::Template> pp = new typename T::Template;
+       load_sub(*pp);
+       postproc = pp;
+       pp = 0;
+       postprocessor_loaded();
+}
+
+} // namespace GL
+} // namespace Msp
+
+#endif
index bd6800a6f16da78b299b1cec3af3435fd678b97b..a13bea3faeeea6eaea41e1d594700c48437a16b1 100644 (file)
@@ -19,9 +19,9 @@ class Resources;
 Creates a cube map texture of the surroundings of the renderable.  This texture
 can then be used to implement effects such as reflections or refractions.
 
 Creates a cube map texture of the surroundings of the renderable.  This texture
 can then be used to implement effects such as reflections or refractions.
 
-If the EnvironmentMap is used in a Pipeline, it's worth noting that the cube
+If the EnvironmentMap is used in a Sequence, it's worth noting that the cube
 map will be prepared outside of any rendering pass.  It's recommended to use
 map will be prepared outside of any rendering pass.  It's recommended to use
-another Pipeline to define which passes should be used to render the
+another Sequence to define which passes should be used to render the
 environment.
 */
 class EnvironmentMap: public Effect
 environment.
 */
 class EnvironmentMap: public Effect
index e94f3c5aca8b333c5a73f6c31082cd2d0afa34a3..c7e281887651c7f3d5495f86c34960055d9429e9 100644 (file)
@@ -21,7 +21,7 @@ is not 180 degrees, it's a spotlight.  Otherwise it's an omnidirectional point
 light.
 
 Lights are usually grouped with a Lighting object, which can be used in a
 light.
 
 Lights are usually grouped with a Lighting object, which can be used in a
-Pipeline::Pass.
+Sequence::Step.
 
 Lights do not cast shadows by themselves.  See ShadowMap for that.
 */
 
 Lights do not cast shadows by themselves.  See ShadowMap for that.
 */
diff --git a/source/render/pipeline.cpp b/source/render/pipeline.cpp
deleted file mode 100644 (file)
index 21f9e85..0000000
+++ /dev/null
@@ -1,287 +0,0 @@
-#include <msp/core/maputils.h>
-#include "blend.h"
-#include "camera.h"
-#include "framebuffer.h"
-#include "lighting.h"
-#include "pipeline.h"
-#include "postprocessor.h"
-#include "renderbuffer.h"
-#include "renderer.h"
-#include "tests.h"
-#include "texture2d.h"
-#include "view.h"
-
-using namespace std;
-
-namespace Msp {
-namespace GL {
-
-Pipeline::Pipeline(unsigned w, unsigned h, bool d)
-{
-       init(w, h);
-       hdr = d;
-}
-
-Pipeline::Pipeline(const View &view)
-{
-       init(view.get_width(), view.get_height());
-}
-
-Pipeline::Pipeline(const Framebuffer &fbo)
-{
-       init(fbo.get_width(), fbo.get_height());
-}
-
-void Pipeline::init(unsigned w, unsigned h)
-{
-       camera = 0;
-       width = w;
-       height = h;
-       hdr = false;
-       alpha = false;
-       samples = 0;
-       target_ms = 0;
-       target[0] = 0;
-       target[1] = 0;
-}
-
-Pipeline::~Pipeline()
-{
-       delete target[0];
-       delete target[1];
-       delete target_ms;
-}
-
-void Pipeline::set_hdr(bool h)
-{
-       if(h==hdr)
-               return;
-
-       bool old_hdr = hdr;
-       hdr = h;
-       try
-       {
-               create_targets(2);
-       }
-       catch(...)
-       {
-               hdr = old_hdr;
-               throw;
-       }
-}
-
-void Pipeline::set_alpha(bool a)
-{
-       if(a==alpha)
-               return;
-
-       bool old_alpha = alpha;
-       alpha = a;
-       try
-       {
-               create_targets(2);
-       }
-       catch(...)
-       {
-               alpha = old_alpha;
-               throw;
-       }
-}
-
-void Pipeline::set_multisample(unsigned s)
-{
-       if(s==samples)
-               return;
-
-       unsigned old_samples = samples;
-       samples = s;
-       try
-       {
-               create_targets(1);
-       }
-       catch(...)
-       {
-               samples = old_samples;
-               throw;
-       }
-}
-
-Pipeline::Pass &Pipeline::add_pass(Tag tag, Renderable &r)
-{
-       passes.push_back(Pass(tag, &r));
-       return passes.back();
-}
-
-void Pipeline::add_postprocessor(PostProcessor &pp)
-{
-       add_postprocessor(&pp, true);
-}
-
-void Pipeline::add_postprocessor_owned(PostProcessor *pp)
-{
-       add_postprocessor(pp, false);
-}
-
-void Pipeline::add_postprocessor(PostProcessor *pp, bool keep)
-{
-       postproc.push_back(pp);
-       if(keep)
-               postproc.back().keep();
-       try
-       {
-               create_targets(0);
-       }
-       catch(...)
-       {
-               postproc.pop_back();
-               throw;
-       }
-}
-
-void Pipeline::setup_frame(Renderer &renderer)
-{
-       for(PassList::const_iterator i=passes.begin(); i!=passes.end(); ++i)
-               if(Renderable *renderable = i->get_renderable())
-                       renderable->setup_frame(renderer);
-       for(vector<Slot>::const_iterator i=renderables.begin(); i!=renderables.end(); ++i)
-               i->renderable->setup_frame(renderer);
-}
-
-void Pipeline::finish_frame()
-{
-       for(PassList::const_iterator i=passes.begin(); i!=passes.end(); ++i)
-               if(Renderable *renderable = i->get_renderable())
-                       renderable->finish_frame();
-       for(vector<Slot>::const_iterator i=renderables.begin(); i!=renderables.end(); ++i)
-               i->renderable->finish_frame();
-}
-
-void Pipeline::render(Renderer &renderer, Tag tag) const
-{
-       if(tag.id)
-               return;
-
-       const Framebuffer *out_fbo = Framebuffer::current();
-       // These are no-ops but will ensure the related state gets restored
-       BindRestore restore_fbo(out_fbo);
-       BindRestore restore_depth_test(DepthTest::current());
-       BindRestore restore_blend(Blend::current());
-
-       if(target[0])
-       {
-               Framebuffer &fbo = (samples ? target_ms : target[0])->get_framebuffer();
-               fbo.bind();
-               fbo.clear();
-       }
-
-       for(PassList::const_iterator i=passes.begin(); i!=passes.end(); ++i)
-       {
-               if(const DepthTest *dt = i->get_depth_test())
-                       dt->bind();
-               else
-                       DepthTest::unbind();
-
-               if(const Blend *b = i->get_blend())
-                       b->bind();
-               else
-                       Blend::unbind();
-
-               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());
-       }
-
-       if(target[0])
-       {
-               DepthTest::unbind();
-               Blend::unbind();
-
-               if(samples)
-                       target[0]->blit_from(*target_ms);
-
-               for(unsigned i=0; i<postproc.size(); ++i)
-               {
-                       unsigned j = i%2;
-                       if(i+1<postproc.size())
-                               target[1-j]->get_framebuffer().bind();
-                       else
-                               out_fbo->bind();
-                       const Texture2D &color = target[j]->get_target_texture(RENDER_COLOR);
-                       const Texture2D &depth = target[j]->get_target_texture(RENDER_DEPTH);
-                       postproc[i]->render(renderer, color, depth);
-               }
-       }
-}
-
-void Pipeline::create_targets(unsigned recreate)
-{
-       if(recreate>=2)
-       {
-               delete target[0];
-               delete target[1];
-               target[0] = 0;
-               target[1] = 0;
-       }
-       if(recreate>=1)
-       {
-               delete target_ms;
-               target_ms = 0;
-       }
-
-       PixelFormat color_pf = (hdr ? (alpha ? RGBA16F : RGB16F) : (alpha ? RGBA8 : RGB8));
-       RenderTargetFormat fmt = (RENDER_COLOR,color_pf, RENDER_DEPTH);
-       if(!postproc.empty() || samples)
-       {
-               if(!target[0])
-                       target[0] = new RenderTarget(width, height, fmt);
-               if(!target[1] && postproc.size()>1)
-                       target[1] = new RenderTarget(width, height, fmt);
-       }
-
-       if(!target_ms && samples)
-               target_ms = new RenderTarget(width, height, samples, fmt);
-}
-
-
-Pipeline::Pass::Pass(Tag t, Renderable *r):
-       tag(t),
-       lighting(0),
-       depth_test(0),
-       blend(0),
-       clipping(0),
-       renderable(r)
-{ }
-
-void Pipeline::Pass::set_lighting(const Lighting *l)
-{
-       lighting = l;
-}
-
-void Pipeline::Pass::set_depth_test(const DepthTest *d)
-{
-       depth_test = d;
-}
-
-void Pipeline::Pass::set_blend(const Blend *b)
-{
-       blend = b;
-}
-
-void Pipeline::Pass::set_clipping(const Clipping *c)
-{
-       clipping =c;
-}
-
-
-Pipeline::Slot::Slot(Renderable *r):
-       renderable(r)
-{ }
-
-} // namespace GL
-} // namespace Msp
diff --git a/source/render/pipeline.h b/source/render/pipeline.h
deleted file mode 100644 (file)
index 9199618..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-#ifndef MSP_GL_PIPELINE_H_
-#define MSP_GL_PIPELINE_H_
-
-#include <map>
-#include <set>
-#include "framebuffer.h"
-#include "renderable.h"
-#include "renderbuffer.h"
-#include "rendertarget.h"
-#include "texture2d.h"
-
-namespace Msp {
-namespace GL {
-
-class Blend;
-class Camera;
-class Clipping;
-class DepthTest;
-class Lighting;
-class PostProcessor;
-class View;
-
-/**
-Top-level content class.  Typically a Pipeline is used as the content
-Renderable for a View or effects such as ShadowMap or EnvironmentMap.
-
-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.
-
-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
-{
-public:
-       class Pass
-       {
-       private:
-               Tag tag;
-               const Lighting *lighting;
-               const DepthTest *depth_test;
-               const Blend *blend;
-               const Clipping *clipping;
-               Renderable *renderable;
-
-       public:
-               Pass(Tag, Renderable *);
-
-               Tag get_tag() const { return tag; }
-
-               void set_lighting(const Lighting *);
-               void set_depth_test(const DepthTest *);
-               void set_blend(const Blend *);
-               void set_clipping(const Clipping *);
-               const Lighting *get_lighting() const { return lighting; }
-               const DepthTest *get_depth_test() const { return depth_test; }
-               const Blend *get_blend() const { return blend; }
-               const Clipping *get_clipping() const { return clipping; }
-               Renderable *get_renderable() const { return renderable; }
-       };
-
-private:
-       struct Slot
-       {
-               Renderable *renderable;
-               std::set<Tag> passes;
-
-               Slot(Renderable *);
-       };
-
-       typedef std::list<Pass> PassList;
-
-       PassList passes;
-       const Camera *camera;
-       std::vector<Slot> renderables;
-       std::vector<RefPtr<PostProcessor> > postproc;
-       unsigned width;
-       unsigned height;
-       bool hdr;
-       bool alpha;
-       unsigned samples;
-       RenderTarget *target[2];
-       RenderTarget *target_ms;
-
-public:
-       Pipeline(unsigned, unsigned, bool = false);
-       Pipeline(const View &);
-       Pipeline(const Framebuffer &);
-private:
-       void init(unsigned, unsigned);
-public:
-       ~Pipeline();
-
-       /* Sets high dynamic range mode.  Requires floating-point texture support.
-       A ColorCurve postprocessor is recommended for full benefit. */
-       void set_hdr(bool);
-
-       /* Enable or disable alpha channel.  When enabled, all render targets are
-       created with an RGBA pixel format instead of RGB. */
-       void set_alpha(bool);
-
-       void set_multisample(unsigned);
-
-       unsigned get_width() const { return width; }
-       unsigned get_height() const { return height; }
-       bool get_hdr() const { return hdr; }
-       unsigned get_multisample() const { return samples; }
-
-       /** Adds a pass to the pipeline.  It's permissible to add the same
-       Renderable multiple times. */
-       Pass &add_pass(Tag, Renderable &);
-
-       /** Adds a postprocessor to the pipeline. */
-       void add_postprocessor(PostProcessor &);
-
-       /** Adds a postprocessor to the pipeline, transferring ownership.  The
-       postprocessor will be deleted together with with pipeline.  It is also
-       deleted if this call throws an exception. */
-       void add_postprocessor_owned(PostProcessor *);
-
-private:
-       void add_postprocessor(PostProcessor *, bool);
-
-public:
-       virtual void setup_frame(Renderer &);
-       virtual void finish_frame();
-
-       virtual void render(Renderer &, Tag tag = Tag()) const;
-
-private:
-       void create_targets(unsigned);
-};
-
-} // namespace GL
-} // namespace Msp
-
-#endif
diff --git a/source/render/sequence.cpp b/source/render/sequence.cpp
new file mode 100644 (file)
index 0000000..6898e66
--- /dev/null
@@ -0,0 +1,287 @@
+#include <msp/core/maputils.h>
+#include "blend.h"
+#include "camera.h"
+#include "framebuffer.h"
+#include "lighting.h"
+#include "postprocessor.h"
+#include "renderbuffer.h"
+#include "renderer.h"
+#include "sequence.h"
+#include "tests.h"
+#include "texture2d.h"
+#include "view.h"
+
+using namespace std;
+
+namespace Msp {
+namespace GL {
+
+Sequence::Sequence(unsigned w, unsigned h, bool d)
+{
+       init(w, h);
+       hdr = d;
+}
+
+Sequence::Sequence(const View &view)
+{
+       init(view.get_width(), view.get_height());
+}
+
+Sequence::Sequence(const Framebuffer &fbo)
+{
+       init(fbo.get_width(), fbo.get_height());
+}
+
+void Sequence::init(unsigned w, unsigned h)
+{
+       camera = 0;
+       width = w;
+       height = h;
+       hdr = false;
+       alpha = false;
+       samples = 0;
+       target_ms = 0;
+       target[0] = 0;
+       target[1] = 0;
+}
+
+Sequence::~Sequence()
+{
+       delete target[0];
+       delete target[1];
+       delete target_ms;
+}
+
+void Sequence::set_hdr(bool h)
+{
+       if(h==hdr)
+               return;
+
+       bool old_hdr = hdr;
+       hdr = h;
+       try
+       {
+               create_targets(2);
+       }
+       catch(...)
+       {
+               hdr = old_hdr;
+               throw;
+       }
+}
+
+void Sequence::set_alpha(bool a)
+{
+       if(a==alpha)
+               return;
+
+       bool old_alpha = alpha;
+       alpha = a;
+       try
+       {
+               create_targets(2);
+       }
+       catch(...)
+       {
+               alpha = old_alpha;
+               throw;
+       }
+}
+
+void Sequence::set_multisample(unsigned s)
+{
+       if(s==samples)
+               return;
+
+       unsigned old_samples = samples;
+       samples = s;
+       try
+       {
+               create_targets(1);
+       }
+       catch(...)
+       {
+               samples = old_samples;
+               throw;
+       }
+}
+
+Sequence::Step &Sequence::add_step(Tag tag, Renderable &r)
+{
+       steps.push_back(Step(tag, &r));
+       return steps.back();
+}
+
+void Sequence::add_postprocessor(PostProcessor &pp)
+{
+       add_postprocessor(&pp, true);
+}
+
+void Sequence::add_postprocessor_owned(PostProcessor *pp)
+{
+       add_postprocessor(pp, false);
+}
+
+void Sequence::add_postprocessor(PostProcessor *pp, bool keep)
+{
+       postproc.push_back(pp);
+       if(keep)
+               postproc.back().keep();
+       try
+       {
+               create_targets(0);
+       }
+       catch(...)
+       {
+               postproc.pop_back();
+               throw;
+       }
+}
+
+void Sequence::setup_frame(Renderer &renderer)
+{
+       for(StepList::const_iterator i=steps.begin(); i!=steps.end(); ++i)
+               if(Renderable *renderable = i->get_renderable())
+                       renderable->setup_frame(renderer);
+       for(vector<Slot>::const_iterator i=renderables.begin(); i!=renderables.end(); ++i)
+               i->renderable->setup_frame(renderer);
+}
+
+void Sequence::finish_frame()
+{
+       for(StepList::const_iterator i=steps.begin(); i!=steps.end(); ++i)
+               if(Renderable *renderable = i->get_renderable())
+                       renderable->finish_frame();
+       for(vector<Slot>::const_iterator i=renderables.begin(); i!=renderables.end(); ++i)
+               i->renderable->finish_frame();
+}
+
+void Sequence::render(Renderer &renderer, Tag tag) const
+{
+       if(tag.id)
+               return;
+
+       const Framebuffer *out_fbo = Framebuffer::current();
+       // These are no-ops but will ensure the related state gets restored
+       BindRestore restore_fbo(out_fbo);
+       BindRestore restore_depth_test(DepthTest::current());
+       BindRestore restore_blend(Blend::current());
+
+       if(target[0])
+       {
+               Framebuffer &fbo = (samples ? target_ms : target[0])->get_framebuffer();
+               fbo.bind();
+               fbo.clear();
+       }
+
+       for(StepList::const_iterator i=steps.begin(); i!=steps.end(); ++i)
+       {
+               if(const DepthTest *dt = i->get_depth_test())
+                       dt->bind();
+               else
+                       DepthTest::unbind();
+
+               if(const Blend *b = i->get_blend())
+                       b->bind();
+               else
+                       Blend::unbind();
+
+               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());
+       }
+
+       if(target[0])
+       {
+               DepthTest::unbind();
+               Blend::unbind();
+
+               if(samples)
+                       target[0]->blit_from(*target_ms);
+
+               for(unsigned i=0; i<postproc.size(); ++i)
+               {
+                       unsigned j = i%2;
+                       if(i+1<postproc.size())
+                               target[1-j]->get_framebuffer().bind();
+                       else
+                               out_fbo->bind();
+                       const Texture2D &color = target[j]->get_target_texture(RENDER_COLOR);
+                       const Texture2D &depth = target[j]->get_target_texture(RENDER_DEPTH);
+                       postproc[i]->render(renderer, color, depth);
+               }
+       }
+}
+
+void Sequence::create_targets(unsigned recreate)
+{
+       if(recreate>=2)
+       {
+               delete target[0];
+               delete target[1];
+               target[0] = 0;
+               target[1] = 0;
+       }
+       if(recreate>=1)
+       {
+               delete target_ms;
+               target_ms = 0;
+       }
+
+       PixelFormat color_pf = (hdr ? (alpha ? RGBA16F : RGB16F) : (alpha ? RGBA8 : RGB8));
+       RenderTargetFormat fmt = (RENDER_COLOR,color_pf, RENDER_DEPTH);
+       if(!postproc.empty() || samples)
+       {
+               if(!target[0])
+                       target[0] = new RenderTarget(width, height, fmt);
+               if(!target[1] && postproc.size()>1)
+                       target[1] = new RenderTarget(width, height, fmt);
+       }
+
+       if(!target_ms && samples)
+               target_ms = new RenderTarget(width, height, samples, fmt);
+}
+
+
+Sequence::Step::Step(Tag t, Renderable *r):
+       tag(t),
+       lighting(0),
+       depth_test(0),
+       blend(0),
+       clipping(0),
+       renderable(r)
+{ }
+
+void Sequence::Step::set_lighting(const Lighting *l)
+{
+       lighting = l;
+}
+
+void Sequence::Step::set_depth_test(const DepthTest *d)
+{
+       depth_test = d;
+}
+
+void Sequence::Step::set_blend(const Blend *b)
+{
+       blend = b;
+}
+
+void Sequence::Step::set_clipping(const Clipping *c)
+{
+       clipping =c;
+}
+
+
+Sequence::Slot::Slot(Renderable *r):
+       renderable(r)
+{ }
+
+} // namespace GL
+} // namespace Msp
diff --git a/source/render/sequence.h b/source/render/sequence.h
new file mode 100644 (file)
index 0000000..97d376d
--- /dev/null
@@ -0,0 +1,145 @@
+#ifndef MSP_GL_SEQUENCE_H_
+#define MSP_GL_SEQUENCE_H_
+
+#include <map>
+#include <set>
+#include "framebuffer.h"
+#include "renderable.h"
+#include "renderbuffer.h"
+#include "rendertarget.h"
+#include "texture2d.h"
+
+namespace Msp {
+namespace GL {
+
+class Blend;
+class Camera;
+class Clipping;
+class DepthTest;
+class Lighting;
+class PostProcessor;
+class View;
+
+/**
+Top-level content class.  Typically a Sequence is used as the content
+Renderable for a View or effects such as ShadowMap or EnvironmentMap.
+
+A Sequence consists of a number of steps.  Each step is defined with a
+Renderable and a tag to render it with and may also have Lighting, Clipping,
+DepthTest and Blend states.  Scenes can be used to further organize Renderables
+within a step.
+
+PostProcessors can be applied after all of the steps in the Sequence have been
+processed.  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 Sequence: public Renderable
+{
+public:
+       class Step
+       {
+       private:
+               Tag tag;
+               const Lighting *lighting;
+               const DepthTest *depth_test;
+               const Blend *blend;
+               const Clipping *clipping;
+               Renderable *renderable;
+
+       public:
+               Step(Tag, Renderable *);
+
+               Tag get_tag() const { return tag; }
+
+               void set_lighting(const Lighting *);
+               void set_depth_test(const DepthTest *);
+               void set_blend(const Blend *);
+               void set_clipping(const Clipping *);
+               const Lighting *get_lighting() const { return lighting; }
+               const DepthTest *get_depth_test() const { return depth_test; }
+               const Blend *get_blend() const { return blend; }
+               const Clipping *get_clipping() const { return clipping; }
+               Renderable *get_renderable() const { return renderable; }
+       };
+
+       DEPRECATED typedef Step Pass;
+
+private:
+       struct Slot
+       {
+               Renderable *renderable;
+               std::set<Tag> passes;
+
+               Slot(Renderable *);
+       };
+
+       typedef std::list<Step> StepList;
+
+       StepList steps;
+       const Camera *camera;
+       std::vector<Slot> renderables;
+       std::vector<RefPtr<PostProcessor> > postproc;
+       unsigned width;
+       unsigned height;
+       bool hdr;
+       bool alpha;
+       unsigned samples;
+       RenderTarget *target[2];
+       RenderTarget *target_ms;
+
+public:
+       Sequence(unsigned, unsigned, bool = false);
+       Sequence(const View &);
+       Sequence(const Framebuffer &);
+private:
+       void init(unsigned, unsigned);
+public:
+       ~Sequence();
+
+       /* Sets high dynamic range mode.  Requires floating-point texture support.
+       A ColorCurve postprocessor is recommended for full benefit. */
+       void set_hdr(bool);
+
+       /* Enable or disable alpha channel.  When enabled, all render targets are
+       created with an RGBA pixel format instead of RGB. */
+       void set_alpha(bool);
+
+       void set_multisample(unsigned);
+
+       unsigned get_width() const { return width; }
+       unsigned get_height() const { return height; }
+       bool get_hdr() const { return hdr; }
+       unsigned get_multisample() const { return samples; }
+
+       /** Adds a step to the sequence.  It's permissible to add the same
+       Renderable multiple times. */
+       Step &add_step(Tag, Renderable &);
+
+       DEPRECATED Step &add_pass(Tag t, Renderable &r) { return add_step(t, r); }
+
+       /** Adds a postprocessor to the sequence. */
+       void add_postprocessor(PostProcessor &);
+
+       /** Adds a postprocessor to the sequence, transferring ownership.  The
+       postprocessor will be deleted together with with sequence.  It is also
+       deleted if this call throws an exception. */
+       void add_postprocessor_owned(PostProcessor *);
+
+private:
+       void add_postprocessor(PostProcessor *, bool);
+
+public:
+       virtual void setup_frame(Renderer &);
+       virtual void finish_frame();
+
+       virtual void render(Renderer &, Tag tag = Tag()) const;
+
+private:
+       void create_targets(unsigned);
+};
+
+} // namespace GL
+} // namespace Msp
+
+#endif
index dca3e8d3d82158947b33ae743a3deb0cf6ecf0ee..e83f33eb529078f80c1bd08d426c40dc49a9a08e 100644 (file)
@@ -10,7 +10,7 @@
 #include "mesh.h"
 #include "module.h"
 #include "object.h"
 #include "mesh.h"
 #include "module.h"
 #include "object.h"
-#include "pipelinetemplate.h"
+#include "sequencetemplate.h"
 #include "pose.h"
 #include "program.h"
 #include "resourcemanager.h"
 #include "pose.h"
 #include "program.h"
 #include "resourcemanager.h"
@@ -48,7 +48,7 @@ Resources::Resources():
        add_type<Mesh>().keyword("mesh").creator(&Resources::create_mesh);
        add_type<Module>().suffix(".glsl").suffix(".spv").creator(&Resources::create_module);
        add_type<Object>().keyword("object");
        add_type<Mesh>().keyword("mesh").creator(&Resources::create_mesh);
        add_type<Module>().suffix(".glsl").suffix(".spv").creator(&Resources::create_module);
        add_type<Object>().keyword("object");
-       add_type<PipelineTemplate>().suffix(".pipe").keyword("pipeline");
+       add_type<SequenceTemplate>().suffix(".seq").keyword("sequence");
        add_type<Pose>().keyword("pose");
        add_type<Program>().keyword("shader").creator(&Resources::create_program);
        add_type<Sampler>().suffix(".samp").keyword("sampler");
        add_type<Pose>().keyword("pose");
        add_type<Program>().keyword("shader").creator(&Resources::create_program);
        add_type<Sampler>().suffix(".samp").keyword("sampler");
index 4ae9c87b26c7483bdb1ad7c4fd2b1637d5d80aa0..ffdc4ec6eb513e4ad2955ddfedc8004f53032692 100644 (file)
@@ -16,7 +16,7 @@
 #include <msp/gl/lighting.h>
 #include <msp/gl/mesh.h>
 #include <msp/gl/object.h>
 #include <msp/gl/lighting.h>
 #include <msp/gl/mesh.h>
 #include <msp/gl/object.h>
-#include <msp/gl/pipeline.h>
+#include <msp/gl/sequence.h>
 #include <msp/gl/renderer.h>
 #include <msp/gl/resources.h>
 #include <msp/gl/simplescene.h>
 #include <msp/gl/renderer.h>
 #include <msp/gl/resources.h>
 #include <msp/gl/simplescene.h>
@@ -65,7 +65,7 @@ private:
        Input::Mouse mouse;
        Resources resources;
        GL::WindowView view;
        Input::Mouse mouse;
        Resources resources;
        GL::WindowView view;
-       GL::Pipeline pipeline;
+       GL::Sequence sequence;
        GL::Renderable *renderable;
        GL::AnimatedObject *anim_object;
        GL::AnimationPlayer *anim_player;
        GL::Renderable *renderable;
        GL::AnimatedObject *anim_object;
        GL::AnimationPlayer *anim_player;
@@ -121,7 +121,7 @@ Viewer::Viewer(int argc, char **argv):
        gl_ctx(window, opts.gl_opts),
        mouse(window),
        view(window, gl_ctx),
        gl_ctx(window, opts.gl_opts),
        mouse(window),
        view(window, gl_ctx),
-       pipeline(view),
+       sequence(view),
        renderable(0),
        anim_object(0),
        anim_player(0),
        renderable(0),
        anim_object(0),
        anim_player(0),
@@ -212,12 +212,12 @@ Viewer::Viewer(int argc, char **argv):
        camera.set_up_direction(GL::Vector3(0, 0, 1));
        update_camera();
 
        camera.set_up_direction(GL::Vector3(0, 0, 1));
        update_camera();
 
-       GL::Pipeline::Pass &pass = pipeline.add_pass(0, *renderable);
-       pass.set_lighting(&lighting);
-       pass.set_depth_test(&GL::DepthTest::lequal());
-       pass.set_blend(&GL::Blend::alpha());
+       GL::Sequence::Step &step = sequence.add_step(0, *renderable);
+       step.set_lighting(&lighting);
+       step.set_depth_test(&GL::DepthTest::lequal());
+       step.set_blend(&GL::Blend::alpha());
 
 
-       view.set_content(&pipeline);
+       view.set_content(&sequence);
        view.set_camera(&camera);
 }
 
        view.set_camera(&camera);
 }