#ifndef MSP_GL_MATERIAL_H_
#define MSP_GL_MATERIAL_H_
-#include <msp/core/typeregistry.h>
#include <msp/datafile/collection.h>
+#include <msp/datafile/dynamicobjectloader.h>
#include <msp/datafile/objectloader.h>
#include "color.h"
#include "programdata.h"
namespace Msp {
namespace GL {
+class Sampler;
+
+/**
+Base class for materials. Subclasses provide different shading models.
+*/
class Material
{
private:
class Loader: public DataFile::CollectionObjectLoader<Material>
{
protected:
- Loader(Material &);
Loader(Material &, Collection &);
virtual void init_actions();
private:
+ void alpha_cutoff(float);
void sampler(const std::string &);
};
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 *));
};
public:
- class GenericLoader: public DataFile::Loader
+ class GenericLoader: public DataFile::DynamicObjectLoader<Material>
{
- private:
- template<typename T>
- struct CreateMaterial
- {
- void operator()(const std::string &, GenericLoader &) const;
- };
-
- DataFile::Collection *coll;
- Material *material;
- Loader *mat_loader;
-
- static ActionMap shared_actions;
+ friend class Material;
public:
- GenericLoader(DataFile::Collection * = 0);
- ~GenericLoader();
+ GenericLoader(Collection &c): DynamicObjectLoader<Material>(&c) { }
- Material *get_material() { Material *m = material; material = 0; return m; }
- private:
- virtual void init_actions();
-
- void type(const DataFile::Symbol &);
-
- friend class Material;
+ protected:
+ virtual const TypeRegistry &get_type_registry() const { return get_material_registry(); }
};
-private:
- typedef TypeRegistry<GenericLoader::CreateMaterial, GenericLoader &> MaterialRegistry;
-
protected:
- const Sampler *sampler;
+ const Sampler *sampler = 0;
+ float alpha_cutoff = 0.0f;
ProgramData shdata;
- Material(): sampler(0) { }
+ Material();
public:
- virtual ~Material() { }
+ virtual ~Material() = default;
+ /** Returns a shader appropriate for this material. The same shader is
+ returned for materials with the same set of features. Additional
+ specialization values can be passed in to customize the shader. */
virtual const Program *create_compatible_shader(const std::map<std::string, int> & = std::map<std::string, int>()) const;
protected:
virtual void fill_program_info(std::string &, std::map<std::string, int> &) const = 0;
public:
- /** Returns the uniforms for the material. */
+ /** Returns the uniform values for the material. */
const ProgramData &get_shader_data() const { return shdata; }
+ /** Returns texture tags used by the material. The returned array is
+ terminated by an empty tag. */
virtual const Tag *get_texture_tags() const = 0;
+
virtual const Texture *get_texture(Tag) const = 0;
- const Sampler *get_sampler() const { return sampler; }
+ virtual const Sampler *get_sampler(Tag) const { return sampler; }
+
+ void set_alpha_cutoff(float a);
+ float get_alpha_cutoff() const { return alpha_cutoff; }
void set_debug_name(const std::string &);
template<typename T>
static void register_type(const std::string &);
private:
- static MaterialRegistry &get_material_registry();
+ static GenericLoader::TypeRegistry &get_material_registry();
};
template<typename T>
(static_cast<C &>(obj).*set_texture)(&static_cast<Collection &>(get_collection()).get<Texture>(name));
}
-
-template<typename T>
-void Material::GenericLoader::CreateMaterial<T>::operator()(const std::string &, GenericLoader &ldr) const
-{
- if(ldr.material)
- throw std::logic_error("Material type was already specified");
-
- T *mat = new T;
- ldr.material = mat;
- if(ldr.coll)
- ldr.mat_loader = new typename T::Loader(*mat, *ldr.coll);
- else
- ldr.mat_loader = new typename T::Loader(*mat);
- ldr.add_auxiliary_loader(*ldr.mat_loader);
-}
-
} // namespace GL
} // namespace Msp