]> git.tdb.fi Git - libs/gl.git/commitdiff
Overhaul texture management in rendering classes
authorMikko Rasa <tdb@tdb.fi>
Sun, 11 Apr 2021 20:25:18 +0000 (23:25 +0300)
committerMikko Rasa <tdb@tdb.fi>
Sun, 11 Apr 2021 20:32:57 +0000 (23:32 +0300)
Textures are now set based on the uniform name (tag) rather than texture
unit.  The Texturing class has been deprecated because it was making
things difficult when textures come from multiple sources, such as with
effects or decals.  RenderPass and Renderer now handle multiple textures
directly.

There's some compatibility code but things are likely to break.

27 files changed:
source/core/datatype.h
source/core/program.cpp
source/core/program.h
source/effects/ambientocclusion.cpp
source/effects/ambientocclusion.h
source/effects/bloom.cpp
source/effects/bloom.h
source/effects/colorcurve.cpp
source/effects/colorcurve.h
source/effects/environmentmap.cpp
source/effects/shadowmap.cpp
source/materials/basicmaterial.cpp
source/materials/basicmaterial.h
source/materials/material.cpp
source/materials/material.h
source/materials/pbrmaterial.cpp
source/materials/pbrmaterial.h
source/materials/renderpass.cpp
source/materials/renderpass.h
source/materials/technique.cpp
source/materials/unlitmaterial.cpp
source/materials/unlitmaterial.h
source/render/programdata.cpp
source/render/renderer.cpp
source/render/renderer.h
source/render/texturing.cpp
source/render/texturing.h

index c7ee2841bded09cd4e23e5c1414c6695db25dc67..ccd288c9ebc75f2f13c3fc8b8098e5968d9805f6 100644 (file)
@@ -93,6 +93,7 @@ enum DataType
 inline unsigned get_type_size(DataType t) { return t&0xFF; }
 inline bool is_matrix(DataType t) { return t&0xC000; }
 inline bool is_vector(DataType t) { return !is_matrix(t) && (t&0x3000); }
+inline bool is_image(DataType t) { return t&0x70000; }
 
 GLenum get_gl_type(DataType);
 DataType from_gl_type(GLenum);
index 0d8e6bd1e2ae09bfbe509c8b07e9bfd42d145219..22626c6543674118737df4e1272785f1db6f9a12 100644 (file)
@@ -400,6 +400,9 @@ void Program::query_uniforms()
                        i->location = glGetUniformLocation(id, i->name.c_str());
                        i->block = &default_block;
                        default_block.uniforms.push_back(&*i);
+
+                       if(is_image(i->type) && i->location>=0)
+                               glGetUniformiv(id, i->location, &i->binding);
                }
 
        default_block.layout_hash = compute_layout_hash(default_block.uniforms);
@@ -681,6 +684,12 @@ int Program::get_uniform_location(Tag tag) const
        return i!=uniforms.end() && i->tag==tag && i->block->bind_point<0 ? i->location : -1;
 }
 
+int Program::get_uniform_binding(Tag tag) const
+{
+       vector<UniformInfo>::const_iterator i = lower_bound_member(uniforms, tag, &UniformInfo::tag);
+       return i!=uniforms.end() && i->tag==tag ? i->binding : -1;
+}
+
 const Program::AttributeInfo &Program::get_attribute_info(const string &name) const
 {
        vector<AttributeInfo>::const_iterator i = lower_bound_member(attributes, name, &AttributeInfo::name);
@@ -724,7 +733,8 @@ Program::UniformInfo::UniformInfo():
        array_size(0),
        array_stride(0),
        matrix_stride(0),
-       type(VOID)
+       type(VOID),
+       binding(-1)
 { }
 
 
index 377c3eee0f1fcfa3349af8efd4754a0aaa43b042..666cfd3eeda8f6a00449b9ab4d899ff64aa0af78 100644 (file)
@@ -74,6 +74,7 @@ public:
                unsigned matrix_stride;
                DataType type;
                Tag tag;
+               int binding;
 
                UniformInfo();
        };
@@ -174,6 +175,7 @@ public:
        const UniformInfo &get_uniform_info(Tag) const;
        int get_uniform_location(const std::string &) const;
        int get_uniform_location(Tag) const;
+       int get_uniform_binding(Tag) const;
        const std::vector<AttributeInfo> &get_attributes() const { return attributes; }
        const AttributeInfo &get_attribute_info(const std::string &) const;
        int get_attribute_location(const std::string &) const;
index bae5e780d1b08c64ea538aa3cd991310044b4277..d47d18aaa8a6f6992ffb800f29463ee70b87aea2 100644 (file)
@@ -20,8 +20,6 @@ AmbientOcclusion::AmbientOcclusion(Resources &resources, unsigned w, unsigned h,
        linear_sampler(resources.get<Sampler>("_linear_clamp.samp")),
        nearest_sampler(resources.get<Sampler>("_nearest_clamp.samp"))
 {
-       texturing.attach(2, occlude_target.get_target_texture(RENDER_COLOR), &linear_sampler);
-
        unsigned seed = 1;
        rotate_lookup.storage(RGBA8, 4, 4, 1);
        unsigned char data[64];
@@ -37,12 +35,6 @@ AmbientOcclusion::AmbientOcclusion(Resources &resources, unsigned w, unsigned h,
        }
        rotate_lookup.image(0, data);
 
-       texturing.attach(3, rotate_lookup, &nearest_sampler);
-
-       shdata.uniform("source", 0);
-       shdata.uniform("depth", 1);
-       shdata.uniform("occlusion", 2);
-       shdata.uniform("rotate", 3);
        shdata.uniform("inverse_projection", Matrix());
 
        set_n_samples(16);
@@ -92,14 +84,14 @@ void AmbientOcclusion::set_edge_depth_threshold(float edt)
 
 void AmbientOcclusion::render(Renderer &renderer, const Texture2D &color, const Texture2D &depth)
 {
-       texturing.attach(0, color, &nearest_sampler);
-       texturing.attach(1, depth, &nearest_sampler);
-
        if(renderer.get_camera())
                shdata.uniform("inverse_projection", invert(renderer.get_camera()->get_projection_matrix()));
 
        Renderer::Push push(renderer);
-       renderer.set_texturing(&texturing);
+       renderer.set_texture("source", &color, &nearest_sampler);
+       renderer.set_texture("depth", &depth, &nearest_sampler);
+       renderer.set_texture("occlusion", &occlude_target.get_target_texture(RENDER_COLOR), &linear_sampler);
+       renderer.set_texture("rotate", &rotate_lookup, &nearest_sampler);
        renderer.set_shader_program(&occlude_shader, &shdata);
 
        {
index 25fab5c9f23952df4ce0516d77ac2a6993e3b0ab..2497d5b7fb4f2d2d150144a67062cdee72a558b0 100644 (file)
@@ -8,7 +8,6 @@
 #include "programdata.h"
 #include "rendertarget.h"
 #include "texture2d.h"
-#include "texturing.h"
 
 namespace Msp {
 namespace GL {
@@ -42,7 +41,6 @@ public:
 private:
        Texture2D rotate_lookup;
        RenderTarget occlude_target;
-       Texturing texturing;
        const Program &occlude_shader;
        const Program &combine_shader;
        mutable ProgramData shdata;
index 1e39c68632002b29718be21a4949f8f2b8d812d9..98afedfc17c924e1e1b1048488dd0e72497ce4dc 100644 (file)
@@ -27,11 +27,6 @@ Bloom::Bloom(Resources &resources, unsigned w, unsigned h):
        for(unsigned i=0; i<2; ++i)
                target[i] = new RenderTarget(w, h, (RENDER_COLOR,RGB16F));
 
-       common_shdata.uniform("source", 0);
-       common_shdata.uniform("blurred", 1);
-
-       combine_texturing.attach(1, target[1]->get_target_texture(RENDER_COLOR), &linear_sampler);
-
        set_radius(2.0f);
        set_strength(0.2f);
 }
@@ -76,13 +71,13 @@ void Bloom::render(Renderer &renderer, const Texture2D &src, const Texture2D &)
        {
                BindRestore bind_fbo(target[i]->get_framebuffer());
                Renderer::Push push2(renderer);
-               renderer.set_texture(i ? &target[0]->get_target_texture(RENDER_COLOR) : &src, &nearest_sampler);
+               renderer.set_texture("source", (i ? &target[0]->get_target_texture(RENDER_COLOR) : &src), &nearest_sampler);
                renderer.add_shader_data(blur_shdata[i]);
                quad.draw(renderer);
        }
 
-       combine_texturing.attach(0, src, &nearest_sampler);
-       renderer.set_texturing(&combine_texturing);
+       renderer.set_texture("source", &src, &nearest_sampler);
+       renderer.set_texture("blurred", &target[1]->get_target_texture(RENDER_COLOR), &linear_sampler);
        renderer.set_shader_program(&combine_shader);
        quad.draw(renderer);
 }
index 27584886824ae3dc7ed8a255eee9c9fa0cf625ca..f2d9db7f01a99363da50219728a2d239b91fee76 100644 (file)
@@ -5,7 +5,6 @@
 #include "mesh.h"
 #include "postprocessor.h"
 #include "texture2d.h"
-#include "texturing.h"
 #include "program.h"
 #include "programdata.h"
 #include "rendertarget.h"
@@ -49,7 +48,6 @@ private:
        const Mesh &quad;
        const Sampler &nearest_sampler;
        const Sampler &linear_sampler;
-       Texturing combine_texturing;
 
 public:
        Bloom(Resources &, unsigned, unsigned);
index 7b8c63b053ffe48681e09a2aa2f7293e3073df75..130fa8df2a45f6b7be2fe711186273a8da26a5b1 100644 (file)
@@ -18,11 +18,7 @@ ColorCurve::ColorCurve(Resources &resources):
        linear_sampler(resources.get<Sampler>("_linear_clamp.samp")),
        nearest_sampler(resources.get<Sampler>("_nearest_clamp.samp"))
 {
-       shdata.uniform("source", 0);
-       shdata.uniform("curve", 1);
-
        curve.storage(LUMINANCE8, 256, 1);
-       texturing.attach(1, curve, &linear_sampler);
 
        set_exposure_adjust(0.0f);
        set_brightness_response(0.4f);
@@ -72,11 +68,10 @@ void ColorCurve::set_linear()
 
 void ColorCurve::render(Renderer &renderer, const Texture2D &color_buf, const Texture2D &)
 {
-       texturing.attach(0, color_buf, &nearest_sampler);
-
        Renderer::Push push(renderer);
        renderer.set_shader_program(&shprog, &shdata);
-       renderer.set_texturing(&texturing);
+       renderer.set_texture("source", &color_buf, &nearest_sampler);
+       renderer.set_texture("curve", &curve, &linear_sampler);
        quad.draw(renderer);
 }
 
index b99bb14e2bac432e89cc78abae5b8e1f7ceab059..e34834aa4e72bf83311b8b9bc41fd657c1d2ba83 100644 (file)
@@ -5,7 +5,6 @@
 #include "program.h"
 #include "programdata.h"
 #include "texture1d.h"
-#include "texturing.h"
 
 namespace Msp {
 namespace GL {
@@ -48,7 +47,6 @@ private:
        const Program &shprog;
        ProgramData shdata;
        Texture1D curve;
-       Texturing texturing;
        const Mesh &quad;
        const Sampler &linear_sampler;
        const Sampler &nearest_sampler;
index 977822ac710601f6b1333ec82238ae1c05424df5..1448c49cfd844165770b5c330b2091f1b437ef49 100644 (file)
@@ -106,14 +106,10 @@ void EnvironmentMap::render(Renderer &renderer, Tag tag) const
 
        Renderer::Push _push_rend(renderer);
 
-       unsigned unit = renderer.allocate_effect_texunit();
-       shdata.uniform("environment_map", static_cast<int>(unit));
-       Bind _bind_sampler(sampler, unit);
-       Bind _bind_env(env_tex, unit);
-
        const Matrix &camera_matrix = renderer.get_camera()->get_object_matrix();
        shdata.uniform("env_eye_matrix", camera_matrix.block<3, 3>(0, 0));
 
+       renderer.set_texture("environment_map", &env_tex, &sampler);
        renderer.add_shader_data(shdata);
        renderer.render(renderable, tag);
 }
index e43e9bdeb97392f8439e22c2351b3fa8bc7fa787..41a97f806b1da20480374f98fe99ac2e1071ed7a 100644 (file)
@@ -93,15 +93,6 @@ void ShadowMap::render(Renderer &renderer, Tag tag) const
        if(!enabled_passes.count(tag))
                return renderer.render(renderable, tag);
 
-       Renderer::Push _push_rend(renderer);
-
-       unsigned unit = renderer.allocate_effect_texunit();
-       int iunit = unit;
-       shdata.uniform("shadow_map", iunit);
-
-       Bind _bind_sampler(sampler, unit);
-       Bind _bind_depth(depth_buf, unit);
-
        if(const Camera *camera = renderer.get_camera())
                /* Multiply by camera's object matrix to form a matrix that transforms
                from eye space to shadow space. */
@@ -109,6 +100,9 @@ void ShadowMap::render(Renderer &renderer, Tag tag) const
        else
                shdata.uniform("shd_eye_matrix", shadow_matrix);
 
+       Renderer::Push _push_rend(renderer);
+
+       renderer.set_texture("shadow_map", &depth_buf, &sampler);
        renderer.add_shader_data(shdata);
        renderer.render(renderable, tag);
 }
index 33dced53d7fb65c68fce1251893f14b202c144c3..5ad694b685803e892032b24a0d199cda86befca7 100644 (file)
@@ -5,6 +5,17 @@ using namespace std;
 namespace Msp {
 namespace GL {
 
+const Tag BasicMaterial::texture_tags[] =
+{
+       Tag("diffuse_map"),
+       Tag("specular_map"),
+       Tag("shininess_map"),
+       Tag("normal_map"),
+       Tag("emission_map"),
+       Tag("reflectivity_map"),
+       Tag()
+};
+
 BasicMaterial::BasicMaterial():
        receive_shadows(false)
 {
@@ -32,6 +43,8 @@ void BasicMaterial::fill_program_info(string &module_name, map<string, int> &spe
        spec_values["use_shadow_map"] = receive_shadows;
 }
 
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
 void BasicMaterial::attach_textures_to(Texturing &texturing, ProgramData &tex_shdata) const
 {
        attach_texture_to(diffuse.texture, texturing, tex_shdata, "diffuse_map");
@@ -41,6 +54,25 @@ void BasicMaterial::attach_textures_to(Texturing &texturing, ProgramData &tex_sh
        attach_texture_to(shininess.texture, texturing, tex_shdata, "shininess_map");
        attach_texture_to(reflectivity.texture, texturing, tex_shdata, "reflectivity_map");
 }
+#pragma GCC diagnostic pop
+
+const Texture *BasicMaterial::get_texture(Tag tag) const
+{
+       if(tag==texture_tags[0])
+               return diffuse.texture;
+       else if(tag==texture_tags[1])
+               return specular.texture;
+       else if(tag==texture_tags[2])
+               return shininess.texture;
+       else if(tag==texture_tags[3])
+               return normal.texture;
+       else if(tag==texture_tags[4])
+               return emission.texture;
+       else if(tag==texture_tags[5])
+               return reflectivity.texture;
+       else
+               return 0;
+}
 
 void BasicMaterial::set_diffuse(const Color &color)
 {
index ef7d1526726c48d101e8ca8c232d63b903794521..2b27b212b6e6f8430dc6e54202fd1a34803bef34 100644 (file)
@@ -31,6 +31,8 @@ private:
        Property<float> reflectivity;
        bool receive_shadows;
 
+       static const Tag texture_tags[];
+
 public:
        BasicMaterial();
 
@@ -38,7 +40,10 @@ protected:
        virtual void fill_program_info(std::string &, std::map<std::string, int> &) const;
 
 public:
-       virtual void attach_textures_to(Texturing &, ProgramData &) const;
+       DEPRECATED virtual void attach_textures_to(Texturing &, ProgramData &) const;
+
+       virtual const Tag *get_texture_tags() const { return texture_tags; }
+       virtual const Texture *get_texture(Tag) const;
 
        void set_diffuse(const Color &);
        void set_diffuse_map(const Texture *);
index eaabad157002b793f64a9d1575238618856e9223..3eaf83ab9b59728b1f21c1800acb2ecc2f1c4f33 100644 (file)
@@ -43,6 +43,8 @@ const Program *Material::create_compatible_shader(DataFile::Collection &coll) co
        return shprog;
 }
 
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
 void Material::attach_texture_to(const Texture *tex, Texturing &texturing, ProgramData &tex_shdata, const string &name) const
 {
        if(!tex)
@@ -62,6 +64,7 @@ void Material::attach_texture_to(const Texture *tex, Texturing &texturing, Progr
        texturing.attach(unit, *tex, sampler);
        tex_shdata.uniform(name, unit);
 }
+#pragma GCC diagnostic pop
 
 Material::MaterialRegistry &Material::get_material_registry()
 {
index 727c61b7303c7faa230241d875c21605b6de598c..a04e74585e56c9fbfc9088b27bc9eb4f1ff96c81 100644 (file)
@@ -105,9 +105,13 @@ public:
        const ProgramData &get_shader_data() const { return shdata; }
 
 protected:
-       void attach_texture_to(const Texture *, Texturing &, ProgramData &, const std::string &) const;
+       DEPRECATED void attach_texture_to(const Texture *, Texturing &, ProgramData &, const std::string &) const;
 public:
-       virtual void attach_textures_to(Texturing &, ProgramData &) const = 0;
+       DEPRECATED virtual void attach_textures_to(Texturing &, ProgramData &) const = 0;
+
+       virtual const Tag *get_texture_tags() const = 0;
+       virtual const Texture *get_texture(Tag) const = 0;
+       const Sampler *get_sampler() const { return sampler; }
 
        template<typename T>
        static void register_type(const std::string &);
index 16c287b4e40f6ad97987ac517ba57315646dc711..92801204ee0ddb7764e543c271a916363591741a 100644 (file)
@@ -5,6 +5,17 @@ using namespace std;
 namespace Msp {
 namespace GL {
 
+const Tag PbrMaterial::texture_tags[] =
+{
+       Tag("base_color_map"),
+       Tag("normal_map"),
+       Tag("metalness_map"),
+       Tag("roughness_map"),
+       Tag("occlusion_map"),
+       Tag("emission_map"),
+       Tag()
+};
+
 PbrMaterial::PbrMaterial():
        receive_shadows(false)
 {
@@ -28,6 +39,8 @@ void PbrMaterial::fill_program_info(string &module_name, map<string, int> &spec_
        spec_values["use_shadow_map"] = receive_shadows;
 }
 
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
 void PbrMaterial::attach_textures_to(Texturing &texturing, ProgramData &tex_shdata) const
 {
        attach_texture_to(base_color.texture, texturing, tex_shdata, "base_color_map");
@@ -37,6 +50,25 @@ void PbrMaterial::attach_textures_to(Texturing &texturing, ProgramData &tex_shda
        attach_texture_to(occlusion.texture, texturing, tex_shdata, "occlusion_map");
        attach_texture_to(emission.texture, texturing, tex_shdata, "emission_map");
 }
+#pragma GCC diagnostic pop
+
+const Texture *PbrMaterial::get_texture(Tag tag) const
+{
+       if(tag==texture_tags[0])
+               return base_color.texture;
+       else if(tag==texture_tags[1])
+               return normal.texture;
+       else if(tag==texture_tags[2])
+               return metalness.texture;
+       else if(tag==texture_tags[3])
+               return roughness.texture;
+       else if(tag==texture_tags[4])
+               return occlusion.texture;
+       else if(tag==texture_tags[5])
+               return emission.texture;
+       else
+               return 0;
+}
 
 void PbrMaterial::set_base_color(const Color &color)
 {
index a1f736f4bf3af657f938be004de70e621e4c9570..00e5e1babc64ded6c83b1ff894f0f5a78a0e672b 100644 (file)
@@ -31,6 +31,8 @@ private:
        Property<Color> emission;
        bool receive_shadows;
 
+       static const Tag texture_tags[];
+
 public:
        PbrMaterial();
 
@@ -38,7 +40,10 @@ protected:
        virtual void fill_program_info(std::string &, std::map<std::string, int> &) const;
 
 public:
-       virtual void attach_textures_to(Texturing &, ProgramData &) const;
+       DEPRECATED virtual void attach_textures_to(Texturing &, ProgramData &) const;
+
+       virtual const Tag *get_texture_tags() const { return texture_tags; }
+       virtual const Texture *get_texture(Tag) const;
 
        void set_base_color(const Color &);
        void set_base_color_map(const Texture *);
index 7431a4461d9977fe6ef601019a12a5705bc63d98..702bddeaab393034521ccfb93a78f1152218b697 100644 (file)
@@ -1,8 +1,8 @@
+#include <msp/core/algorithm.h>
 #include <msp/datafile/collection.h>
 #include <msp/io/print.h>
 #include <msp/strings/format.h>
 #include "error.h"
-#include "material.h"
 #include "renderpass.h"
 #include "program.h"
 #include "programdata.h"
@@ -10,6 +10,7 @@
 #include "texture.h"
 #include "texture2d.h"
 #include "texturing.h"
+#include "uniform.h"
 
 using namespace std;
 
@@ -21,49 +22,17 @@ RenderPass::RenderPass():
        shprog_from_material(false),
        shdata(0),
        material(0),
-       texturing(0),
        back_faces(false)
 { }
 
-RenderPass::RenderPass(const RenderPass &other):
-       shprog(other.shprog),
-       shprog_from_material(other.shprog_from_material),
-       shdata(other.shdata),
-       uniform_slots(other.uniform_slots),
-       material(other.material),
-       material_slot(other.material_slot),
-       texturing(other.texturing ? new Texturing(*other.texturing) : 0),
-       tex_names(other.tex_names),
-       back_faces(other.back_faces)
-{ }
-
-RenderPass &RenderPass::operator=(const RenderPass &other)
-{
-       shprog = other.shprog;
-       shprog_from_material = other.shprog_from_material;
-       shdata = other.shdata;
-       uniform_slots = other.uniform_slots;
-       material = other.material;
-       material_slot = other.material_slot;
-       texturing = other.texturing ? new Texturing(*other.texturing) : 0;
-       tex_names = other.tex_names;
-       back_faces = other.back_faces;
-       return *this;
-}
-
-RenderPass::~RenderPass()
-{
-       delete texturing;
-}
-
 void RenderPass::finalize_material(DataFile::Collection *coll)
 {
        maybe_create_material_shader(coll);
        ensure_private_shader_data();
 
-       if(!texturing)
-               texturing = new Texturing;
-       material->attach_textures_to(*texturing, *shdata);
+       const Tag *material_texture_tags = material->get_texture_tags();
+       for(const Tag *tag=material_texture_tags; tag->id; ++tag)
+               set_texture(*tag, material->get_texture(*tag), material->get_sampler());
 }
 
 void RenderPass::maybe_create_material_shader(DataFile::Collection *coll)
@@ -121,25 +90,60 @@ void RenderPass::set_material(const Material *mat, DataFile::Collection *coll)
        finalize_material(coll);
 }
 
+void RenderPass::set_texture(Tag tag, const Texture *tex, const Sampler *samp)
+{
+       vector<TextureSlot>::iterator i = find_member(textures, tag, &TextureSlot::tag);
+       if(i==textures.end())
+       {
+               textures.push_back(TextureSlot(tag));
+               i = textures.end()-1;
+       }
+       i->texture = tex;
+       if(samp)
+               i->sampler = samp;
+}
+
+Tag RenderPass::get_texture_tag(const string &slot) const
+{
+       vector<TextureSlot>::const_iterator i = find_member(textures, slot, &TextureSlot::slot_name);
+       return (i!=textures.end() ? i->tag : Tag());
+}
+
 void RenderPass::set_texture(unsigned index, const Texture *tex, const Sampler *samp)
 {
-       if(!texturing)
-               texturing = new Texturing;
+       if(!shprog)
+               throw invalid_operation("RenderPass::set_texture");
+
+       const vector<Program::UniformInfo> &uniforms = shprog->get_uniforms();
+       for(vector<Program::UniformInfo>::const_iterator i=uniforms.begin(); i!=uniforms.end(); ++i)
+               if(is_image(i->type) && i->binding==static_cast<int>(index))
+                       return set_texture(i->tag, tex, samp);
 
-       texturing->attach(index, *tex, (samp ? samp : texturing->get_attached_sampler(index)));
+       if(shdata)
+       {
+               const vector<Tag> &tags = shdata->get_uniform_tags();
+               for(vector<Tag>::const_iterator i=tags.begin(); i!=tags.end(); ++i)
+               {
+                       vector<Program::UniformInfo>::const_iterator j = find_member(uniforms, *i, &Program::UniformInfo::tag);
+                       if(j==uniforms.end() || !is_image(j->type))
+                               continue;
+                       if(const Uniform1i *uni1i = dynamic_cast<const Uniform1i *>(shdata->find_uniform(*i)))
+                               if(uni1i->get()==static_cast<int>(index))
+                                       return set_texture(*i, tex, samp);
+               }
+       }
 }
 
 int RenderPass::get_texture_index(const string &n) const
 {
-       map<string, unsigned>::const_iterator i = tex_names.find(n);
-       if(i==tex_names.end())
-               return -1;
-       return i->second;
+       vector<TextureSlot>::const_iterator i = find_member(textures, n, &TextureSlot::slot_name);
+       return (shprog && i!=textures.end() ? shprog->get_uniform_binding(i->tag) : -1);
 }
 
 void RenderPass::apply(Renderer &renderer) const
 {
-       renderer.set_texturing(texturing);
+       for(vector<TextureSlot>::const_iterator i=textures.begin(); i!=textures.end(); ++i)
+               renderer.set_texture(i->tag, i->texture, i->sampler);
        renderer.set_material(material.get());
        renderer.set_shader_program(shprog.get(), shdata.get());
        renderer.set_reverse_winding(back_faces);
@@ -165,12 +169,15 @@ void RenderPass::Loader::init()
        add("material", &Loader::material);
        add("material_slot", &RenderPass::material_slot);
        add("back_faces",&RenderPass::back_faces);
-       add("texunit",  &Loader::texunit);
-       add("texunit",  &Loader::texunit_auto);
-       add("texunit",  &Loader::texunit_named);
+       add("texture", &Loader::texture);
        add("uniforms", &Loader::uniforms);
        add("uniform_slot", &Loader::uniform_slot);
        add("uniform_slot", &Loader::uniform_slot2);
+
+       // Deprecated
+       add("texunit",  &Loader::texunit);
+       add("texunit",  &Loader::texture);
+       add("texunit",  &Loader::texunit_named);
 }
 
 // Temporary compatibility feature
@@ -210,30 +217,46 @@ void RenderPass::Loader::shader(const string &n)
                obj.finalize_material(coll);
 }
 
-void RenderPass::Loader::texunit(unsigned i)
+void RenderPass::Loader::texture(const string &n)
 {
-       if(!obj.texturing)
-               obj.texturing = new Texturing;
-       TextureLoader ldr(*obj.texturing, i, coll);
+       vector<TextureSlot>::iterator i = find_member(obj.textures, Tag(n), &TextureSlot::tag);
+       if(i==obj.textures.end())
+       {
+               obj.textures.push_back(TextureSlot(n));
+               i = obj.textures.end()-1;
+       }
+       TextureSlot::Loader ldr(*i, n, coll);
        load_sub_with(ldr);
 }
 
-void RenderPass::Loader::texunit_auto(const string &n)
+void RenderPass::Loader::texunit(unsigned)
 {
-       if(!obj.texturing)
-               obj.texturing = new Texturing;
-       int i = obj.texturing->find_free_unit(n);
-       if(i<0)
-               throw runtime_error("no free texunit");
-       texunit_named(i, n);
+       IO::print(IO::cerr, "Warning: specifying textures by unit number is deprecated and may not produce expected results");
+       string name;
+       if(obj.shprog)
+       {
+               const vector<Program::UniformInfo> &uniforms = obj.shprog->get_uniforms();
+               for(vector<Program::UniformInfo>::const_iterator i=uniforms.begin(); i!=uniforms.end(); ++i)
+                       if(is_image(i->type) && i->binding>=0)
+                       {
+                               if(!name.empty())
+                               {
+                                       name.clear();
+                                       break;
+                               }
+                               name = i->name;
+                       }
+       }
+
+       if(name.empty())
+               throw runtime_error("Could not determine name for texture");
+
+       texture(name);
 }
 
-void RenderPass::Loader::texunit_named(unsigned i, const string &n)
+void RenderPass::Loader::texunit_named(unsigned, const string &n)
 {
-       texunit(i);
-       obj.tex_names[n] = i;
-       obj.ensure_private_shader_data();
-       obj.shdata->uniform(n, static_cast<int>(i));
+       texture(n);
 }
 
 void RenderPass::Loader::uniforms()
@@ -253,32 +276,19 @@ void RenderPass::Loader::uniform_slot2(const string &name, const string &slot)
 }
 
 
-RenderPass::TextureLoader::TextureLoader(Texturing &t, unsigned i, Collection *c):
-       DataFile::CollectionObjectLoader<Texturing>(t, c),
-       index(i),
-       tex(0),
-       samp(0)
-{
-       add("sampler",   &TextureLoader::sampler);
-       add("texture",   &TextureLoader::texture);
-}
-
-void RenderPass::TextureLoader::finish()
-{
-       if(tex)
-               obj.attach(index, *tex, samp);
-       else if(samp)
-               obj.attach(index, *samp);
-}
-
-void RenderPass::TextureLoader::sampler(const string &name)
+RenderPass::TextureSlot::Loader::Loader(TextureSlot &ts, const string &an, Collection *c):
+       CollectionObjectLoader<TextureSlot>(ts, c),
+       auto_slot_name(an)
 {
-       samp = &get_collection().get<Sampler>(name);
+       add("sampler", &TextureSlot::sampler);
+       add("slot", &Loader::slot_auto);
+       add("slot", &TextureSlot::slot_name);
+       add("texture", &TextureSlot::texture);
 }
 
-void RenderPass::TextureLoader::texture(const string &name)
+void RenderPass::TextureSlot::Loader::slot_auto()
 {
-       tex = &get_collection().get<Texture>(name);
+       obj.slot_name = auto_slot_name;
 }
 
 } // namespace GL
index 0e8ccdf236e68b88c75d9d7ba8095f569bd37d6c..8a69ad12afcc5397739781e91242a8f79cfecc59 100644 (file)
@@ -3,11 +3,11 @@
 
 #include <msp/core/refptr.h>
 #include <msp/datafile/objectloader.h>
+#include "material.h"
 
 namespace Msp {
 namespace GL {
 
-class Material;
 class Program;
 class ProgramData;
 class Renderer;
@@ -36,8 +36,8 @@ public:
                void material_inline();
                void material(const std::string &);
                void shader(const std::string &);
+               void texture(const std::string &);
                void texunit(unsigned);
-               void texunit_auto(const std::string &);
                void texunit_named(unsigned, const std::string &);
                void uniforms();
                void uniform_slot(const std::string &);
@@ -45,20 +45,26 @@ public:
        };
 
 private:
-       struct TextureLoader: public DataFile::CollectionObjectLoader<Texturing>
+       struct TextureSlot
        {
-       private:
-               unsigned index;
-               const Texture *tex;
-               const Sampler *samp;
+               class Loader: public DataFile::CollectionObjectLoader<TextureSlot>
+               {
+               private:
+                       std::string auto_slot_name;
 
-       public:
-               TextureLoader(Texturing &, unsigned, Collection *);
-       private:
-               virtual void finish();
+               public:
+                       Loader(TextureSlot &, const std::string &, Collection *);
 
-               void sampler(const std::string &);
-               void texture(const std::string &);
+               private:
+                       void slot_auto();
+               };
+
+               Tag tag;
+               std::string slot_name;
+               const Texture *texture;
+               const Sampler *sampler;
+
+               TextureSlot(Tag t): tag(t), texture(0), sampler(0) { }
        };
 
        RefPtr<const Program> shprog;
@@ -67,15 +73,11 @@ private:
        std::map<Tag, Tag> uniform_slots;
        RefPtr<const Material> material;
        std::string material_slot;
-       Texturing *texturing;
-       std::map<std::string, unsigned> tex_names;
+       std::vector<TextureSlot> textures;
        bool back_faces;
 
 public:
        RenderPass();
-       RenderPass(const RenderPass &);
-       RenderPass &operator=(const RenderPass &);
-       ~RenderPass();
 
 private:
        void finalize_material(DataFile::Collection *);
@@ -90,9 +92,11 @@ public:
        void set_material(const Material *, DataFile::Collection * = 0);
        const Material *get_material() const { return material.get(); }
        const std::string &get_material_slot_name() const { return material_slot; }
-       void set_texture(unsigned, const Texture *, const Sampler * = 0);
-       const Texturing *get_texturing() const { return texturing; }
-       int get_texture_index(const std::string &) const;
+       void set_texture(Tag, const Texture *, const Sampler * = 0);
+       Tag get_texture_tag(const std::string &) const;
+       DEPRECATED void set_texture(unsigned, const Texture *, const Sampler * = 0);
+       DEPRECATED const Texturing *get_texturing() const { return 0; }
+       DEPRECATED int get_texture_index(const std::string &) const;
        void set_back_faces(bool);
        bool get_back_faces() const { return back_faces; }
 
index a382376eb13351e2fe03d59c29eadb55bee62289..12111e5e675305aa98859bf1ba58f2c332bb544e 100644 (file)
@@ -39,10 +39,10 @@ bool Technique::replace_texture(const string &slot, const Texture &tex)
        bool replaced = false;
        for(PassMap::iterator i=passes.begin(); i!=passes.end(); ++i)
        {
-               int index = i->second.get_texture_index(slot);
-               if(index>=0)
+               Tag tag = i->second.get_texture_tag(slot);
+               if(tag.id)
                {
-                       i->second.set_texture(index, &tex);
+                       i->second.set_texture(tag, &tex);
                        replaced = true;
                }
        }
index e81be8ae136c3b8a915ef3b440b4c6946ffd5cb0..38dbd3a3bdfc9104295fb87983839b9d19cdff29 100644 (file)
@@ -5,6 +5,12 @@ using namespace std;
 namespace Msp {
 namespace GL {
 
+const Tag UnlitMaterial::texture_tags[] =
+{
+       Tag("color_tex"),
+       Tag()
+};
+
 UnlitMaterial::UnlitMaterial():
        texture(0),
        vertex_color(false)
@@ -19,10 +25,21 @@ void UnlitMaterial::fill_program_info(string &module_name, map<string, int> &spe
        spec_values["use_vertex_color"] = vertex_color;
 }
 
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
 void UnlitMaterial::attach_textures_to(Texturing &texturing, ProgramData &tex_shdata) const
 {
        attach_texture_to(texture, texturing, tex_shdata, "color_tex");
 }
+#pragma GCC diagnostic pop
+
+const Texture *UnlitMaterial::get_texture(Tag tag) const
+{
+       if(tag==texture_tags[0])
+               return texture;
+       else
+               return 0;
+}
 
 void UnlitMaterial::set_texture(const Texture *tex)
 {
index a98b12844c5ae1fa1bfa3653cf89953117620026..442348dad4da4400b1ad6456633b0b8e15f1ffde 100644 (file)
@@ -29,6 +29,8 @@ private:
        Color color;
        bool vertex_color;
 
+       static const Tag texture_tags[];
+
 public:
        UnlitMaterial();
 
@@ -36,7 +38,13 @@ protected:
        virtual void fill_program_info(std::string &, std::map<std::string, int> &) const;
 
 public:
-       virtual void attach_textures_to(Texturing &, ProgramData &) const;
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+       DEPRECATED virtual void attach_textures_to(Texturing &, ProgramData &) const;
+#pragma GCC diagnostic pop
+
+       virtual const Tag *get_texture_tags() const { return texture_tags; }
+       virtual const Texture *get_texture(Tag) const;
 
        void set_texture(const Texture *);
        void set_color(const Color &);
index ec273c2277532c9f8a985341663ce9c4ea5836c6..0f641a4afbdf1f75dde9bb5803f5458f90abcc55 100644 (file)
@@ -154,7 +154,11 @@ bool ProgramData::validate_tag(Tag tag) const
 #endif
        {
                if(tied_program)
-                       tied_program->get_uniform_info(tag);
+               {
+                       const Program::UniformInfo &info = tied_program->get_uniform_info(tag);
+                       if(is_image(info.type))
+                               throw invalid_operation("ProgramData::uniform");
+               }
                return true;
        }
 #ifdef DEBUG
@@ -608,8 +612,12 @@ void ProgramData::update_block(SharedBlock &block, const Program::UniformBlockIn
 {
        const UInt8 *indices = block.get_uniform_indices();
        for(unsigned i=0; i<info.uniforms.size(); ++i)
-               if(indices[i]!=0xFF)
+       {
+               if(is_image(info.uniforms[i]->type))
+                       ;  // Temporarily ignore deprecated use of sampler uniforms in ProgramData
+               else if(indices[i]!=0xFF)
                        block.block->attach(*info.uniforms[i], *uniforms[indices[i]].value);
+       }
 }
 
 void ProgramData::apply() const
index ad7ba5a78e173bbfe7d13a62cfa87d3b66e01a42..03653edc1078583aa3378fec60b9ca730599c14d 100644 (file)
@@ -74,19 +74,76 @@ void Renderer::transform(const Matrix &matrix)
        changed |= MATRIX;
 }
 
+void Renderer::set_texture(Tag tag, const Texture *tex, const Sampler *samp)
+{
+       set_texture(tag, -1, tex, samp);
+}
+
+void Renderer::set_texture(Tag tag, int unit, const Texture *tex, const Sampler *samp)
+{
+       if(texture_stack.size()>state->texture_count)
+       {
+               BoundTexture &bt = texture_stack[state->texture_count];
+               if((!tag.id || bt.tag==tag) && (unit<0 || bt.unit==unit) && bt.texture==tex && bt.sampler==samp)
+               {
+                       ++state->texture_count;
+                       return;
+               }
+               else
+                       flush_textures();
+       }
+
+       for(vector<BoundTexture>::iterator i=texture_stack.end(); i!=texture_stack.begin(); )
+               if((--i)->tag==tag && i->unit==unit)
+               {
+                       i->replaced = texture_stack.size();
+                       break;
+               }
+
+       texture_stack.push_back(BoundTexture());
+       BoundTexture &bound_tex = texture_stack.back();
+       bound_tex.tag = tag;
+       bound_tex.unit = unit;
+       bound_tex.texture = tex;
+       bound_tex.sampler = samp;
+       state->texture_count = texture_stack.size();
+}
+
 void Renderer::set_texture(const Texture *t, const Sampler *s)
 {
-       state->texture = t;
-       state->sampler = s;
-       state->texturing = 0;
+       set_texture(Tag(), 0, t, s);
 }
 
+void Renderer::flush_textures()
+{
+       for(unsigned i=0; i<texture_stack.size(); ++i)
+       {
+               BoundTexture &bt = texture_stack[i];
+               if(i>=state->texture_count && bt.unit>=0)
+               {
+                       Texture::unbind_from(bt.unit);
+                       Sampler::unbind_from(bt.unit);
+               }
+               else if(bt.replaced>=static_cast<int>(state->texture_count))
+                       bt.replaced = -1;
+       }
+
+       texture_stack.erase(texture_stack.begin()+state->texture_count, texture_stack.end());
+}
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
 void Renderer::set_texturing(const Texturing *t)
 {
-       state->texturing = t;
-       state->texture = 0;
-       state->sampler = 0;
+       if(t)
+       {
+               unsigned n_units = TexUnit::get_n_units();
+               for(unsigned i=0; i<n_units; ++i)
+                       if(const Texture *tex = t->get_attached_texture(i))
+                               set_texture(Tag(), i, tex, t->get_attached_sampler(i));
+       }
 }
+#pragma GCC diagnostic pop
 
 unsigned Renderer::allocate_effect_texunit()
 {
@@ -233,8 +290,12 @@ void Renderer::end()
        shdata_stack.clear();
        excluded.clear();
 
-       Texturing::unbind();
-       Texture::unbind_from(0);
+       for(vector<BoundTexture>::iterator i=texture_stack.begin(); i!=texture_stack.end(); ++i)
+               if(i->unit>=0)
+               {
+                       Texture::unbind_from(i->unit);
+                       Sampler::unbind_from(i->unit);
+               }
        Clipping::unbind();
        Program::unbind();
        VertexSetup::unbind();
@@ -280,21 +341,20 @@ void Renderer::apply_state()
        /* We (mostly) let the objects themselves figure out if the binding has
        changed */
 
-       if(state->texturing)
-               state->texturing->bind();
-       else
+       if(state->texture_count<texture_stack.size())
+               flush_textures();
+
+       for(vector<BoundTexture>::const_iterator i=texture_stack.begin(); i!=texture_stack.end(); ++i)
        {
-               Texturing::unbind();
-               if(state->texture)
+               int unit = (i->tag.id ? state->shprog->get_uniform_binding(i->tag) : i->unit);
+               if(unit>=0)
                {
-                       if(state->sampler)
-                               state->sampler->bind_to(0);
-                       else
-                               Sampler::unbind_from(0);
-                       state->texture->bind_to(0);
+                       if(i->texture)
+                               i->texture->bind_to(unit);
+                       if(i->sampler)
+                               i->sampler->bind_to(unit);
+                       i->unit = unit;
                }
-               else
-                       Texture::unbind_from(0);
        }
 
        if(state->clipping)
@@ -354,10 +414,17 @@ void Renderer::apply_state()
 }
 
 
+Renderer::BoundTexture::BoundTexture():
+       unit(-1),
+       texture(0),
+       sampler(0),
+       replaced(-1)
+{ }
+
+
 Renderer::State::State():
        camera(0),
-       texture(0),
-       texturing(0),
+       texture_count(0),
        lowest_effect_texunit(TexUnit::get_n_units()),
        material(0),
        lighting(0),
index f8d297289085557c31cfc866ed1e1b2b2d5d952d..603866073c7e81f6edac092d6db169d7c7a98051 100644 (file)
@@ -64,13 +64,22 @@ public:
        };
 
 private:
+       struct BoundTexture
+       {
+               Tag tag;
+               mutable int unit;
+               const Texture *texture;
+               const Sampler *sampler;
+               int replaced;
+
+               BoundTexture();
+       };
+
        struct State
        {
                const Camera *camera;
                Matrix modelview_matrix;
-               const Texture *texture;
-               const Sampler *sampler;
-               const Texturing *texturing;
+               unsigned texture_count;
                unsigned lowest_effect_texunit;
                const Material *material;
                const Lighting *lighting;
@@ -99,6 +108,7 @@ private:
        unsigned char changed;
        std::vector<State> state_stack;
        State *state;
+       std::vector<BoundTexture> texture_stack;
        ProgramData standard_shdata;
        std::vector<const ProgramData *> shdata_stack;
        std::set<const Renderable *> excluded;
@@ -126,9 +136,17 @@ public:
        /** Returns the current modelview matrix. */
        const Matrix &get_matrix() const { return state->modelview_matrix; }
 
-       void set_texture(const Texture *, const Sampler * = 0);
-       void set_texturing(const Texturing *);
-       unsigned allocate_effect_texunit();
+       void set_texture(Tag, const Texture *, const Sampler * = 0);
+private:
+       void set_texture(Tag, int, const Texture *, const Sampler *);
+       void flush_textures();
+public:
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+       DEPRECATED void set_texture(const Texture *, const Sampler * = 0);
+       DEPRECATED void set_texturing(const Texturing *);
+       DEPRECATED unsigned allocate_effect_texunit();
+#pragma GCC diagnostic pop
        void set_material(const Material *);
 
        void set_lighting(const Lighting *);
index be24d5d72b3a6e4fe2075e30af6f5772113b23a3..341cdb79712f6c739ffed027d4ac069f7e04b234 100644 (file)
@@ -5,6 +5,8 @@
 
 using namespace std;
 
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+
 namespace Msp {
 namespace GL {
 
index 0da3eae41794d167d5ee9421943cdac29c9cc74f..44189c903c8a2dd55994788750a7fbd2786a8032 100644 (file)
@@ -9,7 +9,7 @@ namespace GL {
 
 class Texture;
 
-class Texturing: public Bindable<Texturing>
+class DEPRECATED Texturing: public Bindable<Texturing>
 {
 private:
        struct Attachment