From: Mikko Rasa Date: Thu, 26 Apr 2018 16:34:55 +0000 (+0300) Subject: Support overriding uniforms in inherited Techniques X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=commitdiff_plain;h=72a13418cc19e750abf3f8d8a52aea5e1abe4983 Support overriding uniforms in inherited Techniques --- diff --git a/source/programdata.cpp b/source/programdata.cpp index 9a531be2..a0e0e8bc 100644 --- a/source/programdata.cpp +++ b/source/programdata.cpp @@ -1,3 +1,4 @@ +#include #include #include "buffer.h" #include "color.h" @@ -294,6 +295,19 @@ void ProgramData::remove_uniform(const string &name) } } +vector ProgramData::get_uniform_names() const +{ + vector 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; diff --git a/source/programdata.h b/source/programdata.h index 0851f5f6..743e3c0f 100644 --- a/source/programdata.h +++ b/source/programdata.h @@ -176,6 +176,9 @@ public: void uniform_matrix4_array(const std::string &, unsigned, const float *); void remove_uniform(const std::string &); + std::vector 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; diff --git a/source/renderpass.cpp b/source/renderpass.cpp index b588ff2d..3f63ec47 100644 --- a/source/renderpass.cpp +++ b/source/renderpass.cpp @@ -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::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(t, c), diff --git a/source/renderpass.h b/source/renderpass.h index c90108d1..34c315b3 100644 --- a/source/renderpass.h +++ b/source/renderpass.h @@ -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 uniform_slots; RefPtr 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; } diff --git a/source/technique.cpp b/source/technique.cpp index 928c4ff6..d6ec7115 100644 --- a/source/technique.cpp +++ b/source/technique.cpp @@ -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 &uniform_names = shdata.get_uniform_names(); + for(PassMap::iterator i=passes.begin(); i!=passes.end(); ++i) + { + RefPtr new_shdata; + for(vector::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 diff --git a/source/technique.h b/source/technique.h index 1078433f..f80e2f61 100644 --- a/source/technique.h +++ b/source/technique.h @@ -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; };