Support overriding uniforms in inherited Techniques
authorMikko Rasa <tdb@tdb.fi>
Thu, 26 Apr 2018 16:34:55 +0000 (19:34 +0300)
committerMikko Rasa <tdb@tdb.fi>
Thu, 26 Apr 2018 16:34:55 +0000 (19:34 +0300)
source/programdata.cpp
source/programdata.h
source/renderpass.cpp
source/renderpass.h
source/technique.cpp
source/technique.h

index 9a531be2fecefb28dfb38de3375b8dc00c7f6249..a0e0e8bc61376b814f28af1439f01329d8e7e61e 100644 (file)
@@ -1,3 +1,4 @@
+#include <msp/core/maputils.h>
 #include <msp/gl/extensions/arb_direct_state_access.h>
 #include "buffer.h"
 #include "color.h"
@@ -294,6 +295,19 @@ void ProgramData::remove_uniform(const string &name)
        }
 }
 
+vector<string> ProgramData::get_uniform_names() const
+{
+       vector<string> names;
+       for(SlotMap::const_iterator i=uniform_slots.begin(); i!=uniform_slots.end(); ++i)
+               names.push_back(i->first);
+       return names;
+}
+
+const Uniform &ProgramData::get_uniform(const string &name) const
+{
+       return *uniforms[get_item(uniform_slots, name)];
+}
+
 unsigned ProgramData::compute_slot_mask(const Program::UniformBlockInfo &block) const
 {
        unsigned mask = 0;
index 0851f5f6a007396ab5a37a9c5968490ab31b5d10..743e3c0f0e2804461128f05f5314e20d326ade44 100644 (file)
@@ -176,6 +176,9 @@ public:
        void uniform_matrix4_array(const std::string &, unsigned, const float *);
        void remove_uniform(const std::string &);
 
+       std::vector<std::string> get_uniform_names() const;
+       const Uniform &get_uniform(const std::string &) const;
+
 private:
        unsigned compute_slot_mask(const Program::UniformBlockInfo &) const;
        void update_block(UniformBlock &, const Program::UniformBlockInfo &) const;
index b588ff2dc8a119624bcf5297ad5483f8fef972dc..3f63ec47a8c382b058bd3321df01161290e387f2 100644 (file)
@@ -26,6 +26,7 @@ RenderPass::RenderPass():
 RenderPass::RenderPass(const RenderPass &other):
        shprog(other.shprog),
        shdata(other.shdata ? new ProgramData(*other.shdata) : 0),
+       uniform_slots(other.uniform_slots),
        material(other.material),
        texturing(other.texturing ? new Texturing(*other.texturing) : 0),
        tex_names(other.tex_names),
@@ -36,6 +37,7 @@ RenderPass &RenderPass::operator=(const RenderPass &other)
 {
        shprog = other.shprog;
        shdata = other.shdata ? new ProgramData(*other.shdata) : 0;
+       uniform_slots = other.uniform_slots;
        material = other.material;
        texturing = other.texturing ? new Texturing(*other.texturing) : 0;
        tex_names = other.tex_names;
@@ -56,6 +58,17 @@ void RenderPass::set_shader_program(const Program *prog, const ProgramData *data
        shdata = new ProgramData(*data);
 }
 
+const string &RenderPass::get_slotted_uniform_name(const string &slot) const
+{
+       map<string, string>::const_iterator i = uniform_slots.find(slot);
+       if(i==uniform_slots.end())
+       {
+               static string empty;
+               return empty;
+       }
+       return i->second;
+}
+
 void RenderPass::set_material(const Material *mat)
 {
        material = mat;
@@ -109,6 +122,7 @@ void RenderPass::Loader::init()
        add("texunit",  &Loader::texunit);
        add("texunit",  &Loader::texunit_named);
        add("uniforms", &Loader::uniforms);
+       add("uniform_slot", &Loader::uniform_slot);
 }
 
 void RenderPass::Loader::material_inline()
@@ -150,6 +164,16 @@ void RenderPass::Loader::uniforms()
        obj.shdata = shd.release();
 }
 
+void RenderPass::Loader::uniform_slot(const string &name)
+{
+       uniform_slot2(name, name);
+}
+
+void RenderPass::Loader::uniform_slot2(const string &name, const string &slot)
+{
+       obj.uniform_slots[slot] = name;
+}
+
 
 RenderPass::TextureLoader::TextureLoader(Texturing &t, unsigned i, Collection *c):
        DataFile::CollectionObjectLoader<Texturing>(t, c),
index c90108d1c27be58632c313e77f491012dcfb8b79..34c315b3a2c0cc797031c024d2b1f315906bff7d 100644 (file)
@@ -37,6 +37,8 @@ public:
                void texunit(unsigned);
                void texunit_named(unsigned, const std::string &);
                void uniforms();
+               void uniform_slot(const std::string &);
+               void uniform_slot2(const std::string &, const std::string &);
        };
 
 private:
@@ -57,6 +59,7 @@ private:
 
        const Program *shprog;
        ProgramData *shdata;
+       std::map<std::string, std::string> uniform_slots;
        RefPtr<const Material> material;
        std::string material_slot;
        Texturing *texturing;
@@ -72,6 +75,7 @@ public:
        void set_shader_program(const Program *, const ProgramData *);
        const Program *get_shader_program() const { return shprog; }
        const ProgramData *get_shader_data() const { return shdata; }
+       const std::string &get_slotted_uniform_name(const std::string &) const;
        void set_material(const Material *);
        const Material *get_material() const { return material.get(); }
        const std::string &get_material_slot_name() const { return material_slot; }
index 928c4ff6ea8cb4f00d5c6d73af7c1c263e339678..d6ec7115f6e703a5b215803952a27716f934e468 100644 (file)
@@ -60,6 +60,33 @@ bool Technique::replace_material(const string &slot, const Material &mat)
        return replaced;
 }
 
+bool Technique::replace_uniforms(const ProgramData &shdata)
+{
+       bool replaced = false;
+       const vector<string> &uniform_names = shdata.get_uniform_names();
+       for(PassMap::iterator i=passes.begin(); i!=passes.end(); ++i)
+       {
+               RefPtr<ProgramData> new_shdata;
+               for(vector<string>::const_iterator j=uniform_names.begin(); j!=uniform_names.end(); ++j)
+               {
+                       const string &name = i->second.get_slotted_uniform_name(*j);
+                       if(name.empty())
+                               continue;
+
+                       if(!new_shdata)
+                               new_shdata = new ProgramData(*i->second.get_shader_data());
+
+                       new_shdata->uniform(name, shdata.get_uniform(*j));
+                       replaced = true;
+               }
+
+               if(new_shdata)
+                       i->second.set_shader_program(i->second.get_shader_program(), new_shdata.get());
+       }
+
+       return replaced;
+}
+
 bool Technique::has_shaders() const
 {
        for(PassMap::const_iterator i=passes.begin(); i!=passes.end(); ++i)
@@ -111,6 +138,7 @@ Technique::InheritLoader::InheritLoader(Technique &t, Collection &c):
 {
        add("material", &InheritLoader::material);
        add("texture", &InheritLoader::texture);
+       add("uniforms", &InheritLoader::uniforms);
 }
 
 void Technique::InheritLoader::material(const string &slot, const string &name)
@@ -137,5 +165,12 @@ void Technique::InheritLoader::texture(const string &slot, const string &name)
                throw key_error(slot);
 }
 
+void Technique::InheritLoader::uniforms()
+{
+       ProgramData shdata;
+       load_sub(shdata);
+       obj.replace_uniforms(shdata);
+}
+
 } // namespace GL
 } // namespace Msp
index 1078433f39f7d5c028b80ca622150882446ac3e4..f80e2f6144e0f59d32bade49829c721df5b15d27 100644 (file)
@@ -37,6 +37,7 @@ private:
        private:
                void material(const std::string &, const std::string &);
                void texture(const std::string &, const std::string &);
+               void uniforms();
        };
 
 public:
@@ -52,6 +53,7 @@ public:
        const PassMap &get_passes() const { return passes; }
        bool replace_texture(const std::string &, const Texture &);
        bool replace_material(const std::string &, const Material &);
+       bool replace_uniforms(const ProgramData &);
        bool has_shaders() const;
 };