]> git.tdb.fi Git - libs/gl.git/blobdiff - source/material.h
Remove the deprecated ProgramBuilder class
[libs/gl.git] / source / material.h
index 17ea88391238ec31533261578c43ae244cf4e3a7..571f4cb027c4da3a41e8d317e1e4c042603a2706 100644 (file)
 #ifndef MSP_GL_MATERIAL_H_
 #define MSP_GL_MATERIAL_H_
 
+#include <msp/datafile/collection.h>
+#include <msp/datafile/loadabletyperegistry.h>
 #include <msp/datafile/objectloader.h>
-#include "bindable.h"
 #include "color.h"
 #include "programdata.h"
+#include "texture.h"
 
 namespace Msp {
 namespace GL {
 
-/**
-Stores basic material properties.  This includes color and reflection
-parameters, but does not include texturing.  Materials interact with light
-soucres and ambient lighting to produce the base color of a surface.  Textures
-can be used to add detail.
+class Texturing;
 
-Material provides a set of uniform variables for use with shaders.
-*/
 class Material
 {
-public:
+private:
        class Loader: public DataFile::CollectionObjectLoader<Material>
        {
-       private:
-               bool srgb;
-
-       public:
+       protected:
                Loader(Material &);
                Loader(Material &, Collection &);
+
+               virtual void init_actions();
+
        private:
-               void init();
-
-               Color make_color(float, float, float, float);
-               void ambient(float, float, float, float);
-               void diffuse(float, float, float, float);
-               void specular(float, float, float, float);
-               void emission(float, float, float, float);
-               void shininess(float);
-               void reflectivity(float);
+               void sampler(const std::string &);
        };
 
-private:
-       Color ambient;
-       Color diffuse;
-       Color specular;
-       Color emission;
-       float shininess;
-       float reflectivity;
-       ProgramData shdata;
+protected:
+       template<typename T>
+       struct Property
+       {
+               T value;
+               const Texture *texture;
+
+               Property(): value(T()), texture(0) { }
+       };
+
+       template<typename C>
+       class PropertyLoader: public DataFile::DerivedObjectLoader<Material, Loader>
+       {
+       protected:
+               PropertyLoader(C &m): DerivedObjectLoader<Material, Loader>(m) { }
+               PropertyLoader(C &m, Collection &c): DerivedObjectLoader<Material, Loader>(m, c) { }
+
+               void add_property(const std::string &, void (C::*)(float), void (C::*)(const Texture *));
+               void add_property(const std::string &, void (C::*)(const Color &), void (C::*)(const Texture *), bool);
+               void add_property(const std::string &, void (C::*)(const Texture *));
+
+               void property_value_scalar(void (C::*)(float), float);
+               void property_value_rgb(void (C::*)(const Color &), float, float, float);
+               void property_value_rgba(void (C::*)(const Color &), float, float, float, float);
+               void property_value_srgb(void (C::*)(const Color &), float, float, float);
+               void property_value_srgb_alpha(void (C::*)(const Color &), float, float, float, float);
+               void property_texture(void (C::*)(const Texture *), const std::string &);
+       };
 
 public:
-       Material();
+       class GenericLoader: public DataFile::Loader
+       {
+       private:
+               template<typename T>
+               struct AddType
+               {
+                       static void add(GenericLoader &ldr, const std::string &kw) { ldr.add(kw, &GenericLoader::typed_material<T>); }
+               };
+
+               DataFile::Collection *coll;
+               RefPtr<Material> material;
+
+               static ActionMap shared_actions;
+
+       public:
+               GenericLoader(DataFile::Collection * = 0);
 
-       /** Sets the ambient color of the material.  Provided to shaders with the
-       name material.ambient. */
-       void set_ambient(const Color &);
+               Material *get_material() { return material.release(); }
+       private:
+               virtual void init_actions();
 
-       /** Sets the diffuse (direction-independent) color of the material.
-       Provided to shaders with the name material.diffuse. */
-       void set_diffuse(const Color &);
+               template<typename T>
+               void typed_material();
 
-       /** Sets the specular (direction-dependent) color of the material.  Provided
-       to shaders with the name material.specular. */
-       void set_specular(const Color &);
-       void set_emission(const Color &);
+               friend class Material;
+       };
 
-       /** Sets the specular exponent of the material.  Provided to shaders with
-       the name material.shininess. */
-       void set_shininess(float);
+private:
+       typedef DataFile::LoadableTypeRegistry<GenericLoader, GenericLoader::AddType> MaterialRegistry;
 
-       /** Sets the reflectivity of the material.  Provided to shaders with the
-       name reflectivity.  Has no effect when shaders are not used. */
-       void set_reflectivity(float);
+protected:
+       const Sampler *sampler;
+       ProgramData shdata;
 
-       const Color &get_ambient() const { return ambient; }
-       const Color &get_diffuse() const { return diffuse; }
-       const Color &get_specular() const { return specular; }
-       const Color &get_emission() const { return emission; }
-       float get_shininess() const { return shininess; }
-       float get_reflectivity() const { return reflectivity; }
+       Material(): sampler(0) { }
+public:
+       virtual ~Material() { }
+
+       virtual Program *create_compatible_shader() const;
+       virtual const Program *create_compatible_shader(DataFile::Collection &) const;
+protected:
+       virtual std::string create_program_source() const = 0;
 
+public:
        /** Returns the uniforms for the material. */
        const ProgramData &get_shader_data() const { return shdata; }
+
+protected:
+       void attach_texture_to(const Texture *, Texturing &, ProgramData &, const std::string &) const;
+public:
+       virtual void attach_textures_to(Texturing &, ProgramData &) const = 0;
+
+       template<typename T>
+       static void register_type(const std::string &);
+private:
+       static MaterialRegistry &get_material_registry();
 };
 
+template<typename T>
+void Material::register_type(const std::string &kw)
+{
+       get_material_registry().register_type<T>(kw);
+}
+
+
+template<typename C>
+void Material::PropertyLoader<C>::add_property(const std::string &kw, void (C::*set_value)(float), void (C::*set_texture)(const Texture *))
+{
+       add(kw, &PropertyLoader<C>::property_value_scalar, set_value);
+       add(kw+"_map", &PropertyLoader<C>::property_texture, set_texture);
+}
+
+template<typename C>
+void Material::PropertyLoader<C>::add_property(const std::string &kw, void (C::*set_value)(const Color &), void (C::*set_texture)(const Texture *), bool allow_alpha)
+{
+       add(kw, &PropertyLoader<C>::property_value_rgb, set_value);
+       add(kw+"_srgb", &PropertyLoader<C>::property_value_srgb, set_value);
+       if(allow_alpha)
+       {
+               add(kw, &PropertyLoader<C>::property_value_rgba, set_value);
+               add(kw+"_srgb", &PropertyLoader<C>::property_value_srgb_alpha, set_value);
+       }
+       add(kw+"_map", &PropertyLoader<C>::property_texture, set_texture);
+}
+
+template<typename C>
+void Material::PropertyLoader<C>::add_property(const std::string &kw, void (C::*set_texture)(const Texture *))
+{
+       add(kw+"_map", &PropertyLoader<C>::property_texture, set_texture);
+}
+
+template<typename C>
+void Material::PropertyLoader<C>::property_value_scalar(void (C::*set_value)(float), float value)
+{
+       (static_cast<C &>(obj).*set_value)(value);
+}
+
+template<typename C>
+void Material::PropertyLoader<C>::property_value_rgb(void (C::*set_value)(const Color &), float r, float g, float b)
+{
+       (static_cast<C &>(obj).*set_value)(Color(r, g, b));
+}
+
+template<typename C>
+void Material::PropertyLoader<C>::property_value_rgba(void (C::*set_value)(const Color &), float r, float g, float b, float a)
+{
+       (static_cast<C &>(obj).*set_value)(Color(r, g, b, a));
+}
+
+template<typename C>
+void Material::PropertyLoader<C>::property_value_srgb(void (C::*set_value)(const Color &), float r, float g, float b)
+{
+       (static_cast<C &>(obj).*set_value)(Color(r, g, b).to_linear());
+}
+
+template<typename C>
+void Material::PropertyLoader<C>::property_value_srgb_alpha(void (C::*set_value)(const Color &), float r, float g, float b, float a)
+{
+       (static_cast<C &>(obj).*set_value)(Color(r, g, b, a).to_linear());
+}
+
+template<typename C>
+void Material::PropertyLoader<C>::property_texture(void (C::*set_texture)(const Texture *), const std::string &name)
+{
+       /* The static_cast around get_collection is needed because otherwise Android
+       SDK's g++ 4.9 fails to parse get<Texture> as a template function call */
+       (static_cast<C &>(obj).*set_texture)(&static_cast<Collection &>(get_collection()).get<Texture>(name));
+}
+
+
+template<typename T>
+void Material::GenericLoader::typed_material()
+{
+       if(material)
+               throw std::logic_error("Material was already loaded");
+       RefPtr<T> mat = new T;
+       if(coll)
+               load_sub(*mat, *coll);
+       else
+               load_sub(*mat);
+       material = mat;
+}
+
 } // namespace GL
 } // namespace Msp