]> git.tdb.fi Git - libs/gl.git/commitdiff
Use texture unit numbers instead of slot names in RenderPass
authorMikko Rasa <tdb@tdb.fi>
Sat, 9 Oct 2010 06:58:23 +0000 (06:58 +0000)
committerMikko Rasa <tdb@tdb.fi>
Sat, 9 Oct 2010 06:58:23 +0000 (06:58 +0000)
Change the datafile syntax for defining textures
Allow inline textures
Use RefPtr for storing possibly-inline data

source/renderpass.cpp
source/renderpass.h
source/technique.cpp
source/technique.h

index 70fa546afcddc0a0f2bcafb04da1313ddbd2b85b..18c318b53b8d2ccddb81481411350e24beb9a0ac 100644 (file)
@@ -13,6 +13,7 @@ Distributed under the LGPL
 #include "program.h"
 #include "programdata.h"
 #include "texture.h"
+#include "texture2d.h"
 
 using namespace std;
 
@@ -22,23 +23,19 @@ namespace GL {
 RenderPass::RenderPass():
        shprog(0),
        shdata(0),
-       own_material(false),
        material(0)
 { }
 
 RenderPass::RenderPass(const RenderPass &other):
        shprog(other.shprog),
        shdata(other.shdata ? new ProgramData(*other.shdata) : 0),
-       own_material(other.own_material),
-       material(own_material ? new Material(*other.material) : other.material),
+       material(other.material),
        textures(other.textures)
 { }
 
 RenderPass::~RenderPass()
 {
        delete shdata;
-       if(own_material)
-               delete material;
 }
 
 void RenderPass::set_material(const Material *mat)
@@ -46,18 +43,17 @@ void RenderPass::set_material(const Material *mat)
        material = mat;
 }
 
-unsigned RenderPass::get_texture_index(const string &slot) const
+void RenderPass::set_texture(unsigned index, const Texture *tex)
 {
-       for(unsigned i=0; i<textures.size(); ++i)
-               if(textures[i].name==slot)
-                       return i;
-
-       throw KeyError("Unknown texture slot", slot);
-}
+       for(vector<TextureSlot>::iterator i=textures.begin(); i!=textures.end(); ++i)
+               if(i->index==index)
+               {
+                       i->texture = tex;
+                       i->texture.keep();
+                       return;
+               }
 
-void RenderPass::set_texture(const string &slot, const Texture *tex)
-{
-       textures[get_texture_index(slot)] = tex;
+       throw KeyError("No texture slot for that unit", lexical_cast(index));
 }
 
 void RenderPass::bind() const
@@ -79,13 +75,17 @@ void RenderPass::bind() const
        else if(old && old->material)
                GL::Material::unbind();
 
-       for(unsigned i=0; i<textures.size(); ++i)
-               if(textures[i].texture)
-                       textures[i].texture->bind_to(i);
+       unsigned used_tex_units = 0;
+       for(vector<TextureSlot>::const_iterator i=textures.begin(); i!=textures.end(); ++i)
+       {
+               i->texture->bind_to(i->index);
+               used_tex_units |= 1<<i->index;
+       }
        if(old)
        {
-               for(unsigned i=textures.size(); i<old->textures.size(); ++i)
-                       GL::Texture::unbind_from(i);
+               for(vector<TextureSlot>::const_iterator i=old->textures.begin(); i!=old->textures.end(); ++i)
+                       if(!used_tex_units&(1<<i->index))
+                               Texture::unbind_from(i->index);
        }
 }
 
@@ -106,6 +106,12 @@ void RenderPass::unbind()
 }
 
 
+RenderPass::TextureSlot::TextureSlot(unsigned i):
+       index(i),
+       texture(0)
+{ }
+
+
 RenderPass::Loader::Loader(RenderPass &p):
        DataFile::CollectionObjectLoader<RenderPass>(p, 0)
 {
@@ -123,43 +129,35 @@ void RenderPass::Loader::init()
        allow_pointer_reload = false;
 
        add("shader",   &RenderPass::shprog);
-       add("material", &Loader::material);
-       add("material", &RenderPass::material);
-       add("texture",  &Loader::texture);
+       add("material", static_cast<void (Loader::*)()>(&Loader::material));
+       add("material", static_cast<void (Loader::*)(const string &)>(&Loader::material));
+       add("texunit",  &Loader::texunit);
        add("uniforms", &Loader::uniforms);
 }
 
 void RenderPass::Loader::finish()
 {
-       if(obj.shprog)
-       {
-               if(!obj.shdata)
-                       obj.shdata = new ProgramData;
-
-               for(unsigned i=0; i<obj.textures.size(); ++i)
-               {
-                       unsigned loc = obj.shprog->get_uniform_location(obj.textures[i].name);
-                       obj.shdata->uniform(loc, static_cast<int>(i));
-               }
-       }
+       // XXX Make shdata optional
+       if(obj.shprog && !obj.shdata)
+               obj.shdata = new ProgramData;
 }
 
 void RenderPass::Loader::material()
 {
-       if(obj.material)
-               throw InvalidState("A material is already loaded");
-
        RefPtr<Material> mat = new Material;
        load_sub(*mat);
-       obj.material = mat.release();
-       obj.own_material = true;
+       obj.material = mat;
 }
 
-void RenderPass::Loader::texture(const string &n)
+void RenderPass::Loader::material(const string &name)
 {
-       const Texture *tex = (n.empty() ? 0 : get_collection().get<Texture>(n));
-       TextureSlot slot(tex);
-       slot.name = (obj.textures.empty() ? "texture" : format("texture%d", obj.textures.size()));
+       obj.material = get_collection().get<Material>(name);
+       obj.material.keep();
+}
+
+void RenderPass::Loader::texunit(unsigned i)
+{
+       TextureSlot slot(i);
        load_sub(slot);
        obj.textures.push_back(slot);
 }
@@ -174,15 +172,35 @@ void RenderPass::Loader::uniforms()
 }
 
 
-RenderPass::TextureSlot::TextureSlot(const Texture *t):
-       texture(t)
-{ }
+RenderPass::TextureSlot::Loader::Loader(TextureSlot &s):
+       DataFile::CollectionObjectLoader<TextureSlot>(s, 0)
+{
+       init();
+}
 
+RenderPass::TextureSlot::Loader::Loader(TextureSlot &s, Collection &c):
+       DataFile::CollectionObjectLoader<TextureSlot>(s, &c)
+{
+       init();
+}
 
-RenderPass::TextureSlot::Loader::Loader(TextureSlot &s):
-       DataFile::ObjectLoader<TextureSlot>(s)
+void RenderPass::TextureSlot::Loader::init()
+{
+       add("texture",   &Loader::texture);
+       add("texture2d", &Loader::texture2d);
+}
+
+void RenderPass::TextureSlot::Loader::texture(const string &name)
+{
+       obj.texture = get_collection().get<Texture>(name);
+       obj.texture.keep();
+}
+
+void RenderPass::TextureSlot::Loader::texture2d()
 {
-       add("name", &TextureSlot::name);
+       RefPtr<Texture2D> tex = new Texture2D;
+       load_sub(*tex);
+       obj.texture = tex;
 }
 
 } // namespace GL
index e2ea4c97175eb6a62e14bfa6ec636a4c63b12b1d..10960b3f37cb1b082d0cf26d20404514297982b8 100644 (file)
@@ -8,6 +8,7 @@ Distributed under the LGPL
 #ifndef MSP_GL_RENDERPASS_H_
 #define MSP_GL_RENDERPASS_H_
 
+#include <msp/core/refptr.h>
 #include <msp/datafile/objectloader.h>
 #include "bindable.h"
 
@@ -36,30 +37,35 @@ public:
                void init();
                virtual void finish();
                void material();
-               void shader(const std::string &);
-               void texture(const std::string &);
+               void material(const std::string &);
+               void texunit(unsigned);
                void uniforms();
        };
 
 private:
        struct TextureSlot
        {
-               class Loader: public DataFile::ObjectLoader<TextureSlot>
+               class Loader: public DataFile::CollectionObjectLoader<TextureSlot>
                {
                public:
                        Loader(TextureSlot &);
+                       Loader(TextureSlot &, Collection &);
+
+               private:
+                       void init();
+                       void texture(const std::string &);
+                       void texture2d();
                };
 
-               const Texture *texture;
-               std::string name;
+               unsigned index;
+               RefPtr<const Texture> texture;
 
-               TextureSlot(const Texture *);
+               TextureSlot(unsigned);
        };
 
        Program *shprog;
        ProgramData *shdata;
-       bool own_material;
-       const Material *material;
+       RefPtr<const Material> material;
        std::vector<TextureSlot> textures;
 
        RenderPass &operator=(const RenderPass &);
@@ -69,8 +75,7 @@ public:
        ~RenderPass();
 
        void set_material(const Material *);
-       unsigned get_texture_index(const std::string &) const;
-       void set_texture(const std::string &, const Texture *);
+       void set_texture(unsigned, const Texture *);
 
        void bind() const;
 
index 74505c8e0b15ce6d457cf08369592c2e8084bfa8..9cbb005a54b8272bd36ab9e6c2c4f493411fb4cb 100644 (file)
@@ -80,14 +80,14 @@ Technique::InheritLoader::InheritLoader(Technique &t, Collection &c):
        add("texture", &InheritLoader::texture);
 }
 
-void Technique::InheritLoader::texture(const string &slot, const string &name)
+void Technique::InheritLoader::texture(unsigned index, const string &name)
 {
        Texture *tex = get_collection().get<Texture>(name);
        for(PassMap::iterator i=obj.passes.begin(); i!=obj.passes.end(); ++i)
        {
                try
                {
-                       i->second.set_texture(slot, tex);
+                       i->second.set_texture(index, tex);
                }
                catch(const KeyError &)
                { }
index 6633ad7d6e80abe370aba33838f8ff1062892833..80da88f7d2ac7e46cda0c6588f2a5d7055c19767 100644 (file)
@@ -41,7 +41,7 @@ private:
                InheritLoader(Technique &, Collection &);
        
        private:
-               void texture(const std::string &, const std::string &);
+               void texture(unsigned, const std::string &);
        };
 
        typedef std::map<Tag, RenderPass> PassMap;