]> git.tdb.fi Git - libs/gl.git/commitdiff
Add a rendering supervisor class
authorMikko Rasa <tdb@tdb.fi>
Mon, 10 Jan 2011 18:52:05 +0000 (18:52 +0000)
committerMikko Rasa <tdb@tdb.fi>
Mon, 10 Jan 2011 18:52:05 +0000 (18:52 +0000)
Remove bind semantics from RenderPass

23 files changed:
source/camera.h
source/instancescene.cpp
source/instancescene.h
source/mesh.cpp
source/mesh.h
source/object.cpp
source/object.h
source/objectinstance.cpp
source/objectinstance.h
source/orderedscene.cpp
source/orderedscene.h
source/pipeline.cpp
source/pipeline.h
source/renderable.cpp [new file with mode: 0644]
source/renderable.h
source/renderer.cpp [new file with mode: 0644]
source/renderer.h [new file with mode: 0644]
source/renderpass.cpp
source/renderpass.h
source/scene.cpp [new file with mode: 0644]
source/scene.h
source/simplescene.cpp
source/simplescene.h

index cea9c35ef9d02ae2e91769eb6bba3d8e1159c8a6..0390607d5dafd31ffadb22f25ce0cda0a99f5537 100644 (file)
@@ -45,6 +45,7 @@ public:
        const Vector3 &get_position() const { return position; }
        const Vector3 &get_look_direction() const { return look_dir; }
        const Vector3 &get_up_direction() const { return up_dir; }
+       const Matrix &get_matrix() const { return matrix; }
 
        Vector3 project(const Vector4 &) const;
        Vector4 unproject(const Vector4 &) const;
index e3e63767243a1a88ba1ea98655bb480b6ad4584b..adaebbba3ef364b34522df0a49dad2802c990b2f 100644 (file)
@@ -1,13 +1,14 @@
 /* $Id$
 
 This file is part of libmspgl
-Copyright © 2007-2008, 2010  Mikko Rasa, Mikkosoft Productions
+Copyright © 2007-2008, 2010-2011  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
 #include "object.h"
 #include "objectinstance.h"
 #include "instancescene.h"
+#include "renderer.h"
 
 namespace Msp {
 namespace GL {
@@ -36,13 +37,15 @@ void InstanceScene::remove(const Renderable &r)
                renderables.erase(&r);
 }
 
-void InstanceScene::render(const Tag &tag) const
+void InstanceScene::render(Renderer &renderer, const Tag &tag) const
 {
+       // XXX Check that the object has this pass to avoid some unnecessary function calls
        for(ObjectMap::const_iterator i=objects.begin(); i!=objects.end(); ++i)
-               i->first->render(i->second.begin(), i->second.end(), tag);
+               for(InstanceSet::const_iterator j=i->second.begin(); j!=i->second.end(); ++j)
+                       (*j)->render(renderer, tag);
 
        for(RenderableSet::const_iterator i=renderables.begin(); i!=renderables.end(); ++i)
-               (*i)->render(tag);
+               (*i)->render(renderer, tag);
 }
 
 } // namespace GL
index 1f79d767ba0d69cbb48798a820e0f8900792b01b..55bd266d7afbd80ea77dabbb725b620b14b7c1de 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of libmspgl
-Copyright © 2007-2008, 2010  Mikko Rasa, Mikkosoft Productions
+Copyright © 2007-2008, 2010-2011  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
@@ -36,7 +36,8 @@ public:
        virtual void add(const Renderable &);
        virtual void remove(const Renderable &);
 
-       virtual void render(const Tag &tag = Tag()) const;
+       using Scene::render;
+       virtual void render(Renderer &, const Tag &tag = Tag()) const;
 };
 
 } // namespace GL
index a1930d75d124bc35f9d6c40374b9cb7b2f64cb6a..05be2c3745b8562b32f9c9b5a69e722fb4af5058 100644 (file)
@@ -1,13 +1,14 @@
 /* $Id$
 
 This file is part of libmspgl
-Copyright © 2007-2010  Mikko Rasa, Mikkosoft Productions
+Copyright © 2007-2011  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
 #include "buffer.h"
 #include "extension.h"
 #include "mesh.h"
+#include "renderer.h"
 
 using namespace std;
 
@@ -107,6 +108,15 @@ void Mesh::draw() const
                Buffer::unbind_from(ELEMENT_ARRAY_BUFFER);
 }
 
+void Mesh::draw(Renderer &renderer) const
+{
+       renderer.set_vertex_array(&vertices);
+       renderer.set_element_buffer(ibuf);
+
+       for(list<Batch>::const_iterator i=batches.begin(); i!=batches.end(); ++i)
+               renderer.draw(*i);
+}
+
 
 Mesh::Loader::Loader(Mesh &m):
        DataFile::ObjectLoader<Mesh>(m)
index 9ad924f2a246fe00932dc2744531aa94e7b2d3be..1abbefd39746270d6892d83b2fff3f840e22c6de 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of libmspgl
-Copyright © 2007-2010  Mikko Rasa, Mikkosoft Productions
+Copyright © 2007-2011  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
@@ -16,6 +16,7 @@ namespace Msp {
 namespace GL {
 
 class Buffer;
+class Renderer;
 
 class Mesh
 {
@@ -53,6 +54,7 @@ public:
        const std::list<Batch> &get_batches() { return batches; }
 
        void draw() const;
+       void draw(Renderer &) const;
 };
 
 } // namespace GL
index c4787d9fda34d68b4a3cee61b40a6fabf5f79052..f710a7a9c8c5ced2f2e6647c54a16848a90a7fe7 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of libmspgl
-Copyright © 2007  Mikko Rasa, Mikkosoft Productions
+Copyright © 2007-2011  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
@@ -14,9 +14,9 @@ Distributed under the LGPL
 #include "objectinstance.h"
 #include "program.h"
 #include "programdata.h"
+#include "renderer.h"
 #include "technique.h"
-#include "texture.h"
-#include "texunit.h"
+#include "texturing.h"
 
 using namespace std;
 
@@ -55,18 +55,44 @@ void Object::render(const Tag &tag) const
        if(!pass)
                return;
 
-       Bind bind(pass);
+       Bind bind_shader(pass->get_shader_program());
+       if(pass->get_shader_data())
+               pass->get_shader_data()->apply();
+       Bind bind_material(pass->get_material());
+       Bind bind_texturing(pass->get_texturing());
+
        meshes.front()->draw();
 }
 
-void Object::render(const ObjectInstance &inst, const Tag &tag) const
+void Object::render(Renderer &renderer, const Tag &tag) const
 {
        const RenderPass *pass = get_pass(tag);
        if(!pass)
                return;
 
-       Bind bind(pass);
-       render_instance(inst, tag);
+       Renderer::Push push(renderer);
+       renderer.set_shader(pass->get_shader_program(), pass->get_shader_data());
+       renderer.set_material(pass->get_material());
+       renderer.set_texturing(pass->get_texturing());
+
+       meshes.front()->draw(renderer);
+}
+
+void Object::render(Renderer &renderer, const ObjectInstance &inst, const Tag &tag) const
+{
+       const RenderPass *pass = get_pass(tag);
+       if(!pass)
+               return;
+
+       Renderer::Push push(renderer);
+       renderer.set_shader(pass->get_shader_program(), pass->get_shader_data());
+       renderer.set_material(pass->get_material());
+       renderer.set_texturing(pass->get_texturing());
+
+       inst.setup_render(renderer, tag);
+       unsigned lod = min<unsigned>(inst.get_level_of_detail(), meshes.size()-1);
+       meshes[lod]->draw(renderer);
+       inst.finish_render(renderer, tag);
 }
 
 const RenderPass *Object::get_pass(const Tag &tag) const
@@ -76,14 +102,6 @@ const RenderPass *Object::get_pass(const Tag &tag) const
        return &technique->get_pass(tag);
 }
 
-void Object::render_instance(const ObjectInstance &inst, const Tag &tag) const
-{
-       inst.setup_render(tag);
-       unsigned lod = min<unsigned>(inst.get_level_of_detail(), meshes.size()-1);
-       meshes[lod]->draw();
-       inst.finish_render(tag);
-}
-
 
 Object::Loader::Loader(Object &o):
        DataFile::CollectionObjectLoader<Object>(o, 0)
index 4655695b355583d40598a7186eeab915c497d016..e84bc9cf707d5f7c1e0ef10dea9a5c255100a647 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of libmspgl
-Copyright © 2007-2008, 2010  Mikko Rasa, Mikkosoft Productions
+Copyright © 2007-2008, 2010-2011  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
@@ -65,33 +65,17 @@ public:
        */
        virtual void render(const Tag &tag = Tag()) const;
 
+       virtual void render(Renderer &, const Tag & = Tag()) const;
+
        /**
        Renders the object with an instance.  The instance's hook functions are
        called before and after drawing the mesh.  A tag may also be given to render
        a non-default pass.
        */
-       virtual void render(const ObjectInstance &, const Tag &tag = Tag()) const;
+       virtual void render(Renderer &, const ObjectInstance &, const Tag & = Tag()) const;
 
-       /**
-       Renders multiple instances of the object in one go.  This may improve
-       performance, as the object-specific render setup only has to be done once.
-       Each instance's hook functions will be called before and after drawing the
-       mesh.
-       */
-       template<typename Iter>
-       void render(Iter begin, Iter end, const Tag &tag = Tag()) const
-       {
-               const RenderPass *pass = get_pass(tag);
-               if(!pass)
-                       return;
-
-               Bind bind(pass);
-               for(Iter i=begin; i!=end; ++i)
-                       render_instance(**i, tag);
-       }
 private:
        const RenderPass *get_pass(const Tag &) const;
-       void render_instance(const ObjectInstance &, const Tag &) const;
 };
 
 } // namespace GL
index 666d90056774d4fc963fd7d38248f5e19f61f9f7..14341561bc41ac626f80e83cfebfe011113c84e9 100644 (file)
@@ -1,13 +1,13 @@
 /* $Id$
 
 This file is part of libmspgl
-Copyright © 2007  Mikko Rasa, Mikkosoft Productions
+Copyright © 2007, 2010-2011  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
 #include "object.h"
 #include "objectinstance.h"
-#include "programdata.h"
+#include "renderer.h"
 
 using namespace std;
 
@@ -20,7 +20,13 @@ ObjectInstance::ObjectInstance(const Object &obj):
 
 void ObjectInstance::render(const Tag &tag) const
 {
-       object.render(*this, tag);
+       Renderer renderer(0);
+       render(renderer, tag);
+}
+
+void ObjectInstance::render(Renderer &renderer, const Tag &tag) const
+{
+       object.render(renderer, *this, tag);
 }
 
 } // namespace GL
index 61ad55d33ef722400780db5540b63f410eb4133b..d665851fbb5d40fb0201d17c255ea8667572a04c 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of libmspgl
-Copyright © 2007  Mikko Rasa, Mikkosoft Productions
+Copyright © 2007-2008, 2010-2011  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
@@ -21,9 +21,6 @@ class ProgramData;
 Represents a single instance of an Object.  An application can derive another
 class from this and overload the hook functions to specify location and other
 instance-specific parameters for the rendered objects.
-
-The finish_render function generally should clean up everything done by
-setup_render, unless the rendering sequence is known to allow otherwise.
 */
 class ObjectInstance: public Renderable
 {
@@ -36,16 +33,16 @@ public:
        const Object &get_object() const { return object; }
 
        virtual void render(const Tag &tag = Tag()) const;
+       virtual void render(Renderer &, const Tag & = Tag()) const;
 
-       /**
-       Hook function, called from Object just before rendering the mesh.
-       */
-       virtual void setup_render(const Tag &) const { }
+       /** Hook function, called from Object just before rendering the mesh.
+       Renderer state will have been pushed before this is called. */
+       virtual void setup_render(Renderer &, const Tag &) const { }
 
-       /**
-       Hook function, called from Object right after rendering the mesh.
-       */
-       virtual void finish_render(const Tag &) const { }
+       /** Hook function, called from Object right after rendering the mesh.  Since
+       Object takes care of pushing Renderer state, this rarely needs to do
+       anything. */
+       virtual void finish_render(Renderer &, const Tag &) const { }
 
        virtual unsigned get_level_of_detail() const { return 0; }
 };
index 38edf696072405c0b5dbea68c372b70a32683fdb..296ad5105447583309e50de85c864fed82eb47f4 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of libmspgl
-Copyright © 2010  Mikko Rasa, Mikkosoft Productions
+Copyright © 2010-2011  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
@@ -41,10 +41,10 @@ void OrderedScene::insert_after(const Renderable &after, const Renderable &r)
        renderables.insert(i, &r);
 }
 
-void OrderedScene::render(const Tag &tag) const
+void OrderedScene::render(Renderer &renderer, const Tag &tag) const
 {
        for(RenderableList::const_iterator i=renderables.begin(); i!=renderables.end(); ++i)
-               (*i)->render(tag);
+               (*i)->render(renderer, tag);
 }
 
 } // namespace GL
index 6bb12192a851877887dd1b21dc1100c4554a7e18..88321ec93dd5d18ff6203a6cd59ac61a38229121 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of libmspgl
-Copyright © 2010  Mikko Rasa, Mikkosoft Productions
+Copyright © 2010-2011  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
@@ -32,7 +32,8 @@ public:
        void insert(unsigned, const Renderable &);
        void insert_after(const Renderable &, const Renderable &);
 
-       virtual void render(const Tag & = Tag()) const;
+       using Scene::render;
+       virtual void render(Renderer &, const Tag & = Tag()) const;
 };
 
 } // namespace GL
index 5294ffbd859d84f4c29ce7878dcd5a01a6fd376b..570014d3692e4ab1405e22761b90511a02379020 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of libmspgl
-Copyright © 2009-2010  Mikko Rasa, Mikkosoft Productions
+Copyright © 2009-2011  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
@@ -14,6 +14,7 @@ Distributed under the LGPL
 #include "pipeline.h"
 #include "postprocessor.h"
 #include "renderbuffer.h"
+#include "renderer.h"
 #include "tests.h"
 #include "texture2d.h"
 
@@ -133,7 +134,7 @@ void Pipeline::add_postprocessor(PostProcessor &pp)
        }
 }
 
-void Pipeline::render(const Tag &tag) const
+void Pipeline::render(Renderer &renderer, const Tag &tag) const
 {
        const PipelinePass &pass = get_pass(tag);
 
@@ -146,7 +147,7 @@ void Pipeline::render(const Tag &tag) const
 
        for(vector<Slot>::const_iterator i=renderables.begin(); i!=renderables.end(); ++i)
                if(i->passes.empty() || i->passes.count(tag))
-                       i->renderable->render(tag);
+                       i->renderable->render(renderer, tag);
 
        for(vector<Effect *>::const_iterator i=pass.effects.end(); i!=pass.effects.begin();)
                (*--i)->cleanup();
@@ -166,8 +167,9 @@ void Pipeline::render_all() const
        for(vector<Effect *>::const_iterator i=effects.begin(); i!=effects.end(); ++i)
                (*i)->prepare();
 
+       Renderer renderer(camera);
        for(vector<Tag>::const_iterator i=pass_order.begin(); i!=pass_order.end(); ++i)
-               render(*i);
+               render(renderer, *i);
 
        for(vector<Effect *>::const_iterator i=effects.end(); i!=effects.begin();)
                (*--i)->cleanup();
index a63eeb5f686a2deb4cd541e60cd0b05ab0a7101a..e4509af8364c77b84c512f141d8d3f30b66f0a78 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of libmspgl
-Copyright © 2009  Mikko Rasa, Mikkosoft Productions
+Copyright © 2009-2011  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
@@ -65,7 +65,7 @@ public:
        void add_effect(Effect &);
        void add_postprocessor(PostProcessor &);
 
-       virtual void render(const Tag &tag = Tag()) const;
+       virtual void render(Renderer &, const Tag &tag = Tag()) const;
        void render_all() const;
 };
 
diff --git a/source/renderable.cpp b/source/renderable.cpp
new file mode 100644 (file)
index 0000000..73c4a37
--- /dev/null
@@ -0,0 +1,27 @@
+/* $Id$
+
+This file is part of libmspgl
+Copyright © 2011  Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include <msp/core/except.h>
+#include "renderable.h"
+#include "renderer.h"
+
+namespace Msp {
+namespace GL {
+
+void Renderable::render(const Tag &) const
+{
+       throw Exception("This Renderable doesn't support rendering without a Renderer");
+}
+
+void Renderable::render(Renderer &renderer, const Tag &tag) const
+{
+       renderer.escape();
+       render(tag);
+}
+
+} // namespace Msp
+} // namespace GL
index 44b3c257b9a79b825e466be5d9d467827c350b38..8e31d5a7ac79e0f4a379b581da4b68ef37823c05 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of libmspgl
-Copyright © 2007  Mikko Rasa, Mikkosoft Productions
+Copyright © 2007, 2011  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
@@ -14,6 +14,8 @@ Distributed under the LGPL
 namespace Msp {
 namespace GL {
 
+class Renderer;
+
 class Renderable
 {
 protected:
@@ -21,7 +23,8 @@ protected:
 public:
        virtual ~Renderable() { }
 
-       virtual void render(const Tag &tag = Tag()) const =0;
+       virtual void render(const Tag & = Tag()) const;
+       virtual void render(Renderer &, const Tag & = Tag()) const;
 };
 
 } // namespace Msp
diff --git a/source/renderer.cpp b/source/renderer.cpp
new file mode 100644 (file)
index 0000000..71a7ded
--- /dev/null
@@ -0,0 +1,196 @@
+/* $Id$
+
+This file is part of libmspgl
+Copyright © 2011  Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include <msp/core/except.h>
+#include "batch.h"
+#include "buffer.h"
+#include "camera.h"
+#include "material.h"
+#include "program.h"
+#include "programdata.h"
+#include "renderer.h"
+#include "texture.h"
+#include "texturing.h"
+#include "vertexarray.h"
+
+using namespace std;
+
+namespace Msp {
+namespace GL {
+
+Renderer::Renderer(const Camera *c):
+       mtx_changed(false),
+       camera(c),
+       state_stack(1),
+       state(&state_stack.back()),
+       vertex_array(0),
+       vertex_array_changed(false),
+       element_buffer(0)
+{
+       MatrixStack::modelview().push();
+       if(camera)
+       {
+               MatrixStack::projection().push();
+               camera->apply();
+               mtx_stack = camera->get_matrix();
+       }
+       else
+               mtx_stack = MatrixStack::modelview().top();
+}
+
+Renderer::~Renderer()
+{
+       if(camera)
+               MatrixStack::projection().pop();
+       MatrixStack::modelview().pop();
+
+       Texturing::unbind();
+       Texture::unbind_from(0);
+       Material::unbind();
+       Program::unbind();
+       Buffer::unbind_from(ELEMENT_ARRAY_BUFFER);
+}
+
+MatrixStack &Renderer::matrix_stack()
+{
+       mtx_changed = true;
+       return mtx_stack;
+}
+
+void Renderer::set_texture(const Texture *t)
+{
+       state->texture = t;
+       state->texturing = 0;
+}
+
+void Renderer::set_texturing(const Texturing *t)
+{
+       state->texturing = t;
+       state->texture = 0;
+}
+
+void Renderer::set_material(const Material *m)
+{
+       state->material = m;
+}
+
+void Renderer::set_shader(const Program *p, const ProgramData *d)
+{
+       state->shprog = p;
+       if(d)
+               state->shdata.assign(1, d);
+       else
+               state->shdata.clear();
+}
+
+void Renderer::add_shader_data(const ProgramData *d)
+{
+       if(!state->shprog)
+               throw InvalidState("No shader program");
+
+       state->shdata.push_back(d);
+}
+
+void Renderer::set_vertex_array(const VertexArray *a)
+{
+       vertex_array_changed = (a!=vertex_array);
+       vertex_array = a;
+}
+
+void Renderer::set_element_buffer(const Buffer *b)
+{
+       element_buffer = b;
+}
+
+void Renderer::push_state()
+{
+       state_stack.push_back(state_stack.back());
+       state = &state_stack.back();
+       mtx_stack.push();
+}
+
+void Renderer::pop_state()
+{
+       if(state_stack.size()==1)
+               throw InvalidState("Can't pop the last state");
+
+       state_stack.pop_back();
+       state = &state_stack.back();
+       mtx_stack.pop();
+}
+
+void Renderer::escape()
+{
+       apply_state();
+       Buffer::unbind_from(ELEMENT_ARRAY_BUFFER);
+}
+
+void Renderer::draw(const Batch &batch)
+{
+       if(!vertex_array)
+               throw InvalidState("Can't draw without a vertex array");
+
+       apply_state();
+
+       // Until VertexArray acquires VAO support and becomes Bindable
+       if(vertex_array_changed)
+               vertex_array->apply();
+
+       if(element_buffer)
+               element_buffer->bind_to(ELEMENT_ARRAY_BUFFER);
+       else
+               Buffer::unbind_from(ELEMENT_ARRAY_BUFFER);
+
+       batch.draw();
+}
+
+void Renderer::apply_state()
+{
+       // We let the objects themselves figure out if the binding has changed
+
+       if(state->texturing)
+               state->texturing->bind();
+       else
+       {
+               Texturing::unbind();
+               if(state->texture)
+                       state->texture->bind_to(0);
+               else
+                       Texture::unbind_from(0);
+       }
+
+       if(state->material)
+               state->material->bind();
+       else
+               Material::unbind();
+
+       if(state->shprog)
+       {
+               state->shprog->bind();
+               for(vector<const ProgramData *>::const_iterator i=state->shdata.begin(); i!=state->shdata.end(); ++i)
+                       (*i)->apply();
+       }
+       else
+               Program::unbind();
+
+       if(mtx_changed)
+       {
+               MatrixStack::modelview() = mtx_stack.top();
+               mtx_changed = false;
+       }
+}
+
+
+Renderer::State::State():
+       texture(0),
+       texturing(0),
+       material(0),
+       shprog(0)
+{ }
+
+} // namespace GL
+} // namespace Msp
diff --git a/source/renderer.h b/source/renderer.h
new file mode 100644 (file)
index 0000000..c06c17e
--- /dev/null
@@ -0,0 +1,99 @@
+/* $Id$
+
+This file is part of libmspgl
+Copyright © 2011  Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#ifndef MSP_GL_RENDERER_H_
+#define MSP_GL_RENDERER_H_
+
+#include <vector>
+#include "matrix.h"
+
+namespace Msp {
+namespace GL {
+
+class Batch;
+class Buffer;
+class Camera;
+class Material;
+class Program;
+class ProgramData;
+class Texture;
+class Texturing;
+class VertexArray;
+
+/**
+A class for supervising the rendering process.  While many Renderables (in
+particular, Objects and Scenes) can by rendered without a Renderer, using one
+will often be more efficient.  This is especially true for ObjectInstances.
+
+The Renderer works by deferring GL state changes until something is actually
+being drawn.  This avoids many unnecessary GL calls. */
+class Renderer
+{
+public:
+       class Push
+       {
+       private:
+               Renderer &renderer;
+
+       public:
+               Push(Renderer &r): renderer(r) { renderer.push_state(); }
+               ~Push() { renderer.pop_state(); }
+       };
+
+private:
+       struct State
+       {
+               const Texture *texture;
+               const Texturing *texturing;
+               const Material *material;
+               const Program *shprog;
+               std::vector<const ProgramData *> shdata;
+
+               State();
+       };
+
+       MatrixStack mtx_stack;
+       bool mtx_changed;
+       const Camera *camera;
+       std::list<State> state_stack;
+       State *state;
+       const VertexArray *vertex_array;
+       bool vertex_array_changed;
+       const Buffer *element_buffer;
+
+public:
+       Renderer(const Camera *);
+       ~Renderer();
+
+       MatrixStack &matrix_stack();
+
+       const Camera *get_camera() const { return camera; }
+
+       void set_texture(const Texture *);
+       void set_texturing(const Texturing *);
+       void set_material(const Material *);
+       void set_shader(const Program *, const ProgramData *);
+       void add_shader_data(const ProgramData *);
+       void set_vertex_array(const VertexArray *);
+       void set_element_buffer(const Buffer *);
+
+       void push_state();
+       void pop_state();
+
+       /** Prepares for temporarily bypassing the Renderer. */
+       void escape();
+
+       void draw(const Batch &);
+
+private:
+       void apply_state();
+};
+
+} // namespace GL
+} // namespace Msp
+
+#endif
index 5b5f72984b3bbfdbfe293d594ba68b3c17b4bd43..b67be7170ae7cff929d24b115552cce009db05e6 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of libmspgl
-Copyright © 2007  Mikko Rasa, Mikkosoft Productions
+Copyright © 2007-2008, 2010-2011  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
@@ -30,7 +30,6 @@ RenderPass::RenderPass():
 { }
 
 RenderPass::RenderPass(const RenderPass &other):
-       Bindable<RenderPass>(other),
        shprog(other.shprog),
        shdata(other.shdata ? new ProgramData(*other.shdata) : 0),
        material(other.material),
@@ -57,47 +56,6 @@ void RenderPass::set_texture(unsigned index, const Texture *tex)
        texturing->attach(index, *tex);
 }
 
-void RenderPass::bind() const
-{
-       const RenderPass *old = current();
-       if(!set_current(this))
-               return;
-
-       if(shprog)
-       {
-               shprog->bind();
-               shdata->apply();
-       }
-       else if(old && old->shprog)
-               Program::unbind();
-
-       if(material)
-               material->bind();
-       else if(old && old->material)
-               Material::unbind();
-
-       if(texturing)
-               texturing->bind();
-       else if(old && old->texturing)
-               Texturing::unbind();
-}
-
-void RenderPass::unbind()
-{
-       const RenderPass *old = current();
-       if(!set_current(0))
-               return;
-
-       if(old->shprog)
-               Program::unbind();
-
-       if(old->material)
-               Material::unbind();
-
-       if(old->texturing)
-               Texturing::unbind();
-}
-
 
 RenderPass::Loader::Loader(RenderPass &p):
        DataFile::CollectionObjectLoader<RenderPass>(p, 0)
index acbe29491cf9f493477663f8f51954ef63de2605..688327bb84ebb7c067a504c2b03779181f026b2b 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of libmspgl
-Copyright © 2007-2008, 2010  Mikko Rasa, Mikkosoft Productions
+Copyright © 2007-2008, 2010-2011  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
@@ -28,7 +28,7 @@ This includes shader and data for it, material and texturing.
 
 XXX Does not delete inline texture from datafiles properly
 */
-class RenderPass: public Bindable<RenderPass>
+class RenderPass
 {
 public:
        class Loader: public DataFile::CollectionObjectLoader<RenderPass>
@@ -75,12 +75,12 @@ public:
        RenderPass(const RenderPass &);
        ~RenderPass();
 
+       const Program *get_shader_program() const { return shprog; }
+       const ProgramData *get_shader_data() const { return shdata; }
        void set_material(const Material *);
+       const Material *get_material() const { return material.get(); }
        void set_texture(unsigned, const Texture *);
-
-       void bind() const;
-
-       static void unbind();
+       const Texturing *get_texturing() const { return texturing; }
 };
 
 } // namespace GL
diff --git a/source/scene.cpp b/source/scene.cpp
new file mode 100644 (file)
index 0000000..fee81dc
--- /dev/null
@@ -0,0 +1,21 @@
+/* $Id$
+
+This file is part of libmspgl
+Copyright © 2011  Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include "renderer.h"
+#include "scene.h"
+
+namespace Msp {
+namespace GL {
+
+void Scene::render(const Tag &tag) const
+{
+       Renderer renderer(0);
+       render(renderer, tag);
+}
+
+} // namespace GL
+} // namespace Msp
index 92a4a171eb18828e9e6c634f39a7a374edecdac9..3b35f45b5558702a0d7f33019456ab444e5b5be1 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of libmspgl
-Copyright © 2010  Mikko Rasa, Mikkosoft Productions
+Copyright © 2010-2011  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
@@ -27,6 +27,9 @@ public:
 
        virtual void add(const Renderable &) = 0;
        virtual void remove(const Renderable &) = 0;
+
+       using Renderable::render;
+       virtual void render(const Tag & = Tag()) const;
 };
 
 } // namespace GL
index b410374e68de5b18b7e52ae10c45fc083a03903a..f5947707a95bef5b008f332f209ab4dc8117852a 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of libmspgl
-Copyright © 2010  Mikko Rasa, Mikkosoft Productions
+Copyright © 2010-2011  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
@@ -20,10 +20,10 @@ void SimpleScene::remove(const Renderable &r)
        renderables.erase(&r);
 }
 
-void SimpleScene::render(const Tag &tag) const
+void SimpleScene::render(Renderer &renderer, const Tag &tag) const
 {
        for(RenderableSet::const_iterator i=renderables.begin(); i!=renderables.end(); ++i)
-               (*i)->render(tag);
+               (*i)->render(renderer, tag);
 }
 
 } // namespace GL
index b28b5c0ce12e628d4bfb1b1b1dbe7550746a7658..35315926460d0727f3d9471e392e3e05744872fa 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of libmspgl
-Copyright © 2010  Mikko Rasa, Mikkosoft Productions
+Copyright © 2010-2011  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
@@ -28,7 +28,8 @@ public:
        virtual void add(const Renderable &);
        virtual void remove(const Renderable &);
 
-       virtual void render(const Tag &tag = Tag()) const;
+       using Scene::render;
+       virtual void render(Renderer &, const Tag & = Tag()) const;
 };
 
 } // namespace GL