]> git.tdb.fi Git - libs/gl.git/commitdiff
Redesign the material system
authorMikko Rasa <tdb@tdb.fi>
Wed, 3 Jun 2020 18:56:00 +0000 (21:56 +0300)
committerMikko Rasa <tdb@tdb.fi>
Thu, 11 Jun 2020 15:38:43 +0000 (18:38 +0300)
Now that legacy OpenGL support is removed and all lighting calculations
are done in shaders, there's no reason to stick to the old material model
anymore.  The new model is closer to that used by many 3D modeling
programs, with textures applied to material properties.  It also allows
different types of materials with different shading models.

This change breaks source compatibility, but the new BasicMaterial class
is mostly compatible with the old Material class, with only minor changes
needed in code and datafiles.

shaderlib/msp_interface.glsl
shaderlib/singlepass.glsl
source/basicmaterial.cpp [new file with mode: 0644]
source/basicmaterial.h [new file with mode: 0644]
source/material.cpp
source/material.h
source/renderpass.cpp
source/renderpass.h
source/resources.cpp
source/resources.h

index 5f391bb5fa882ca39897509974aba622c2b587c2..6a8ee8d8f63713260ff05b98879b8e7f30644505 100644 (file)
@@ -5,12 +5,13 @@ struct LightSourceParameters
        vec4 specular;
 };
 
-struct MaterialParameters
+struct BasicMaterialParameters
 {
-       vec4 ambient;
        vec4 diffuse;
        vec4 specular;
+       vec4 emission;
        float shininess;
+       float reflectivity;
 };
 
 struct ClipPlane
@@ -26,10 +27,9 @@ uniform Transform
        mat4 projection_matrix;
 };
 
-uniform Material
+uniform BasicMaterial
 {
-       MaterialParameters material;
-       float reflectivity;
+       BasicMaterialParameters basic_material;
 };
 
 uniform Lighting
@@ -45,6 +45,9 @@ uniform Lighting
 };
 
 uniform sampler2D diffuse_map;
+uniform sampler2D specular_map;
+uniform sampler2D shininess_map;
+uniform sampler2D emission_map;
 uniform sampler2D normal_map;
 
 uniform sampler2DShadow shadow;
index f782f3dad543ead82db5c583d3ebfbcfe955132e..ff421ea0287ccfabeacdf651eae590b719c573ac 100644 (file)
@@ -101,23 +101,23 @@ vec3 singlepass_lighting()
        vec3 diffuse_light = diffuse_intensity*light_sources[0].diffuse.rgb;
 
        vec3 half_vec = normalize(light_dir-incident_dir);
-       float specular_intensity = pow(max(dot(half_vec, normal), 0.0), material.shininess);
+       float specular_intensity = pow(max(dot(half_vec, normal), 0.0), basic_material.shininess);
        if(use_shadow_map)
                specular_intensity *= shadow_intensity;
        vec3 specular_light = specular_intensity*light_sources[0].specular.rgb;
 
-       vec3 result = material.ambient.rgb*ambient_light+material.diffuse.rgb*diffuse_light;
+       vec3 result = basic_material.diffuse.rgb*ambient_light+basic_material.diffuse.rgb*diffuse_light;
        if(use_diffuse_map)
                result *= diffuse_sample.rgb;
        if(use_specular)
-               result += material.specular.rgb*specular_light;
+               result += basic_material.specular.rgb*specular_light;
 
        return result;
 }
 
 float singlepass_transparency()
 {
-       float alpha = material.diffuse.a;
+       float alpha = basic_material.diffuse.a;
        if(use_diffuse_map)
                alpha *= diffuse_sample.a;
        return alpha;
diff --git a/source/basicmaterial.cpp b/source/basicmaterial.cpp
new file mode 100644 (file)
index 0000000..7ba8380
--- /dev/null
@@ -0,0 +1,113 @@
+#include "basicmaterial.h"
+
+using namespace std;
+
+namespace Msp {
+namespace GL {
+
+BasicMaterial::BasicMaterial()
+{
+       set_diffuse(Color(1.0f));
+       set_specular(Color(0.0f));
+       set_emission(Color(0.0f));
+       set_shininess(50.0f);
+       set_reflectivity(0.0f);
+}
+
+void BasicMaterial::attach_textures_to(Texturing &texturing, ProgramData &tex_shdata) const
+{
+       attach_texture_to(diffuse.texture, texturing, tex_shdata, "diffuse_map");
+       attach_texture_to(specular.texture, texturing, tex_shdata, "specular_map");
+       attach_texture_to(normal.texture, texturing, tex_shdata, "normal_map");
+       attach_texture_to(emission.texture, texturing, tex_shdata, "emission_map");
+       attach_texture_to(shininess.texture, texturing, tex_shdata, "shininess_map");
+       attach_texture_to(reflectivity.texture, texturing, tex_shdata, "reflectivity_map");
+}
+
+void BasicMaterial::set_diffuse(const Color &color)
+{
+       diffuse.value = color;
+       shdata.uniform("basic_material.diffuse", color);
+}
+
+void BasicMaterial::set_diffuse_map(const Texture *tex)
+{
+       diffuse.texture = tex;
+}
+
+void BasicMaterial::set_specular(const Color &color)
+{
+       specular.value = color;
+       shdata.uniform("basic_material.specular", color);
+}
+
+void BasicMaterial::set_specular_map(const Texture *tex)
+{
+       specular.texture = tex;
+}
+
+void BasicMaterial::set_normal_map(const Texture *tex)
+{
+       normal.texture = tex;
+}
+
+void BasicMaterial::set_emission(const Color &color)
+{
+       emission.value = color;
+       shdata.uniform("basic_material.emission", color);
+}
+
+void BasicMaterial::set_emission_map(const Texture *tex)
+{
+       emission.texture = tex;
+}
+
+void BasicMaterial::set_shininess(float value)
+{
+       shininess.value = value;
+       shdata.uniform("basic_material.shininess", value);
+}
+
+void BasicMaterial::set_shininess_map(const Texture *tex)
+{
+       shininess.texture = tex;
+}
+
+void BasicMaterial::set_reflectivity(float value)
+{
+       reflectivity.value = value;
+       shdata.uniform("basic_material.reflectivity", value);
+}
+
+void BasicMaterial::set_reflectivity_map(const Texture *tex)
+{
+       reflectivity.texture = tex;
+}
+
+
+DataFile::Loader::ActionMap BasicMaterial::Loader::shared_actions;
+
+BasicMaterial::Loader::Loader(BasicMaterial &m):
+       DerivedObjectLoader<BasicMaterial, Material::LoaderBase<BasicMaterial> >(m)
+{
+       set_actions(shared_actions);
+}
+
+BasicMaterial::Loader::Loader(BasicMaterial &m, Collection &c):
+       DerivedObjectLoader<BasicMaterial, Material::LoaderBase<BasicMaterial> >(m, c)
+{
+       set_actions(shared_actions);
+}
+
+void BasicMaterial::Loader::init_actions()
+{
+       add_property("diffuse", &BasicMaterial::set_diffuse, &BasicMaterial::set_diffuse_map, true);
+       add_property("specular", &BasicMaterial::set_specular, &BasicMaterial::set_specular_map, false);
+       add_property("normal", &BasicMaterial::set_normal_map);
+       add_property("emission", &BasicMaterial::set_emission, &BasicMaterial::set_emission_map, false);
+       add_property("shininess", &BasicMaterial::set_shininess, &BasicMaterial::set_shininess_map);
+       add_property("reflectivity", &BasicMaterial::set_reflectivity, &BasicMaterial::set_reflectivity_map);
+}
+
+} // namespace GL
+} // namespace Msp
diff --git a/source/basicmaterial.h b/source/basicmaterial.h
new file mode 100644 (file)
index 0000000..9b7eab0
--- /dev/null
@@ -0,0 +1,54 @@
+#ifndef MSP_GL_BASICMATERIAL_H_
+#define MSP_GL_BASICMATERIAL_H_
+
+#include "material.h"
+
+namespace Msp {
+namespace GL {
+
+class BasicMaterial: public Material
+{
+public:
+       class Loader: public DataFile::DerivedObjectLoader<BasicMaterial, Material::LoaderBase<BasicMaterial> >
+       {
+       private:
+               static ActionMap shared_actions;
+
+       public:
+               Loader(BasicMaterial &);
+               Loader(BasicMaterial &, Collection &);
+
+       private:
+               virtual void init_actions();
+       };
+
+private:
+       Property<Color> diffuse;
+       Property<Color> specular;
+       Property<float> shininess;
+       Property<Vector3> normal;
+       Property<Color> emission;
+       Property<float> reflectivity;
+
+public:
+       BasicMaterial();
+
+       void attach_textures_to(Texturing &, ProgramData &) const;
+
+       void set_diffuse(const Color &);
+       void set_diffuse_map(const Texture *);
+       void set_specular(const Color &);
+       void set_specular_map(const Texture *);
+       void set_normal_map(const Texture *);
+       void set_emission(const Color &);
+       void set_emission_map(const Texture *);
+       void set_shininess(float);
+       void set_shininess_map(const Texture *);
+       void set_reflectivity(float);
+       void set_reflectivity_map(const Texture *);
+};
+
+} // namespace GL
+} // namespace Msp
+
+#endif
index 1d5a4087af2b3b8f6c9db232792c7eff45732a1c..8bd6e54ca51b4bf1a48d5b86c07da3fe075d76c5 100644 (file)
+#include "basicmaterial.h"
 #include "gl.h"
-#include "material.h"
 #include "resources.h"
+#include "texturing.h"
+
+using namespace std;
 
 namespace Msp {
 namespace GL {
 
-Material::Material()
-{
-       set_ambient(0.2);
-       set_diffuse(0.8);
-       set_specular(0);
-       set_emission(0);
-       set_shininess(0);
-       set_reflectivity(0);
-}
-
-void Material::set_ambient(const Color &a)
-{
-       ambient = a;
-       shdata.uniform("material.ambient", ambient);
-}
-
-void Material::set_diffuse(const Color &d)
-{
-       diffuse = d;
-       shdata.uniform("material.diffuse", diffuse);
-}
-
-void Material::set_specular(const Color &s)
+void Material::attach_texture_to(const Texture *tex, Texturing &texturing, ProgramData &tex_shdata, const string &name) const
 {
-       specular = s;
-       shdata.uniform("material.specular", specular);
-}
+       if(!tex)
+               return;
 
-void Material::set_emission(const Color &e)
-{
-       emission = e;
-       shdata.uniform("material.emission", emission);
-}
-
-void Material::set_shininess(float s)
-{
-       shininess = s;
-       shdata.uniform("material.shininess", shininess);
+       int unit = texturing.find_free_unit(name);
+       if(unit<0)
+               throw runtime_error("no free texunit");
+       texturing.attach(unit, *tex);
+       tex_shdata.uniform(name, unit);
 }
 
-void Material::set_reflectivity(float r)
+Material::MaterialRegistry &Material::get_material_registry()
 {
-       reflectivity = r;
-       shdata.uniform("reflectivity", reflectivity);
+       static MaterialRegistry registry;
+       static bool initialized = false;
+       if(!initialized)
+       {
+               registry.register_type<BasicMaterial>("basic");
+       }
+       return registry;
 }
 
 
-Material::Loader::Loader(Material &m):
-       DataFile::CollectionObjectLoader<Material>(m, 0)
-{
-       init();
-}
-
-Material::Loader::Loader(Material &m, Collection &c):
-       DataFile::CollectionObjectLoader<Material>(m, &c)
-{
-       init();
-}
-
-void Material::Loader::init()
-{
-       if(Resources *res = dynamic_cast<Resources *>(coll))
-               srgb = res->get_srgb_conversion();
-       else
-               srgb = false;
-
-       add("ambient",   &Loader::ambient);
-       add("diffuse",   &Loader::diffuse);
-       add("specular",  &Loader::specular);
-       add("emission",  &Loader::emission);
-       add("shininess", &Loader::shininess);
-       add("reflectivity", &Loader::reflectivity);
-}
-
-Color Material::Loader::make_color(float r, float g, float b, float a)
-{
-       Color c(r, g, b, a);
-       if(srgb)
-               c = c.to_linear();
-       return c;
-}
-
-void Material::Loader::ambient(float r, float g, float b, float a)
-{
-       obj.set_ambient(make_color(r, g, b, a));
-}
-
-void Material::Loader::diffuse(float r, float g, float b, float a)
-{
-       obj.set_diffuse(make_color(r, g, b, a));
-}
-
-void Material::Loader::specular(float r, float g, float b, float a)
-{
-       obj.set_specular(make_color(r, g, b, a));
-}
-
-void Material::Loader::emission(float r, float g, float b, float a)
-{
-       obj.set_emission(make_color(r, g, b, a));
-}
+DataFile::Loader::ActionMap Material::GenericLoader::shared_actions;
 
-void Material::Loader::shininess(float s)
+Material::GenericLoader::GenericLoader(DataFile::Collection *c):
+       coll(c)
 {
-       obj.set_shininess(s);
+       set_actions(shared_actions);
 }
 
-void Material::Loader::reflectivity(float r)
+void Material::GenericLoader::init_actions()
 {
-       obj.set_reflectivity(r);
+       get_material_registry().add_all(*this);
 }
 
 } // namespace GL
index ead11618c2c9abdf8d82ca29b63d7e241bfd7beb..df55a56767c6318ad9f6f3effed314520604fcd7 100644 (file)
@@ -1,6 +1,8 @@
 #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 "color.h"
 #include "programdata.h"
 namespace Msp {
 namespace GL {
 
-/**
-Stores basic material properties.  This includes color and reflection
-parameters, but does not include texturing.  Materials interact with light
-sources and ambient lighting to produce the base color of a surface.  Textures
-can be used to add detail.
+class Texture;
+class Texturing;
 
-Material provides a set of uniform variables for use with shaders.
-*/
 class Material
 {
+protected:
+       template<typename T>
+       struct Property
+       {
+               T value;
+               const Texture *texture;
+
+               Property(): value(T()), texture(0) { }
+       };
+
+       template<typename C>
+       class LoaderBase: public DataFile::CollectionObjectLoader<Material>
+       {
+       protected:
+               LoaderBase(C &m): CollectionObjectLoader<Material>(m, 0) { }
+               LoaderBase(C &m, Collection &c): CollectionObjectLoader<Material>(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:
-       class Loader: public DataFile::CollectionObjectLoader<Material>
+       class GenericLoader: public DataFile::Loader
        {
        private:
-               bool srgb;
+               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:
-               Loader(Material &);
-               Loader(Material &, Collection &);
+               GenericLoader(DataFile::Collection * = 0);
+
+               Material *get_material() { return material.release(); }
        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);
+               virtual void init_actions();
+
+               template<typename T>
+               void typed_material();
+
+               friend class Material;
        };
 
 private:
-       Color ambient;
-       Color diffuse;
-       Color specular;
-       Color emission;
-       float shininess;
-       float reflectivity;
+       typedef DataFile::LoadableTypeRegistry<GenericLoader, GenericLoader::AddType> MaterialRegistry;
+
+protected:
        ProgramData shdata;
 
+       Material() { }
+public:
+       virtual ~Material() { }
+
+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:
-       Material();
+       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();
+};
 
-       /** Sets the ambient color of the material.  Provided to shaders with the
-       name material.ambient. */
-       void set_ambient(const Color &);
+template<typename T>
+void Material::register_type(const std::string &kw)
+{
+       get_material_registry().register_type<T>(kw);
+}
 
-       /** Sets the diffuse (direction-independent) color of the material.
-       Provided to shaders with the name material.diffuse. */
-       void set_diffuse(const Color &);
 
-       /** 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 &);
+template<typename C>
+void Material::LoaderBase<C>::add_property(const std::string &kw, void (C::*set_value)(float), void (C::*set_texture)(const Texture *))
+{
+       add(kw, &LoaderBase<C>::property_value_scalar, set_value);
+       add(kw+"_map", &LoaderBase<C>::property_texture, set_texture);
+}
 
-       /** Sets the specular exponent of the material.  Provided to shaders with
-       the name material.shininess. */
-       void set_shininess(float);
+template<typename C>
+void Material::LoaderBase<C>::add_property(const std::string &kw, void (C::*set_value)(const Color &), void (C::*set_texture)(const Texture *), bool allow_alpha)
+{
+       add(kw, &LoaderBase<C>::property_value_rgb, set_value);
+       add(kw+"_srgb", &LoaderBase<C>::property_value_srgb, set_value);
+       if(allow_alpha)
+       {
+               add(kw, &LoaderBase<C>::property_value_rgba, set_value);
+               add(kw+"_srgb", &LoaderBase<C>::property_value_srgb_alpha, set_value);
+       }
+       add(kw+"_map", &LoaderBase<C>::property_texture, set_texture);
+}
+
+template<typename C>
+void Material::LoaderBase<C>::add_property(const std::string &kw, void (C::*set_texture)(const Texture *))
+{
+       add(kw+"_map", &LoaderBase<C>::property_texture, set_texture);
+}
 
-       /** 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);
+template<typename C>
+void Material::LoaderBase<C>::property_value_scalar(void (C::*set_value)(float), float value)
+{
+       (static_cast<C &>(obj).*set_value)(value);
+}
 
-       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; }
+template<typename C>
+void Material::LoaderBase<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));
+}
 
-       /** Returns the uniforms for the material. */
-       const ProgramData &get_shader_data() const { return shdata; }
-};
+template<typename C>
+void Material::LoaderBase<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::LoaderBase<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::LoaderBase<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::LoaderBase<C>::property_texture(void (C::*set_texture)(const Texture *), const std::string &name)
+{
+       (static_cast<C &>(obj).*set_texture)(&get_collection().get<GL::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
index 0d76913bb3a409248dbbd232b3f5db598bee38b1..34a311e79ece2f7e4df91d382010dca39137be1f 100644 (file)
@@ -52,6 +52,15 @@ RenderPass::~RenderPass()
        delete texturing;
 }
 
+void RenderPass::finalize_material()
+{
+       ensure_private_shader_data();
+
+       if(!texturing)
+               texturing = new Texturing;
+       material->attach_textures_to(*texturing, *shdata);
+}
+
 void RenderPass::ensure_private_shader_data()
 {
        if(!shprog)
@@ -84,6 +93,7 @@ void RenderPass::set_material(const Material *mat)
 {
        material = mat;
        material.keep();
+       finalize_material();
 }
 
 void RenderPass::set_texture(unsigned index, const Texture *tex)
@@ -139,18 +149,17 @@ void RenderPass::Loader::init()
 
 void RenderPass::Loader::material_inline()
 {
-       RefPtr<Material> mat = new Material;
-       if(coll)
-               load_sub(*mat, get_collection());
-       else
-               load_sub(*mat);
-       obj.material = mat;
+       Material::GenericLoader ldr(coll);
+       load_sub_with(ldr);
+       obj.material = ldr.get_material();
+       obj.finalize_material();
 }
 
 void RenderPass::Loader::material(const string &name)
 {
        obj.material = &get_collection().get<Material>(name);
        obj.material.keep();
+       obj.finalize_material();
 }
 
 void RenderPass::Loader::texunit(unsigned i)
index d4f7a34d1a5887b12edb8af57bb81b8e2a5db462..3570151258beb225f84ecd6ef43dd269f8579c7b 100644 (file)
@@ -74,6 +74,7 @@ public:
        ~RenderPass();
 
 private:
+       void finalize_material();
        void ensure_private_shader_data();
 
 public:
index 22814cb820525809836226b2a455afd844d668cd..8aecb933cadc3ce2585799b31c9ce14bca5ae70a 100644 (file)
@@ -40,7 +40,7 @@ Resources::Resources():
        add_type<Font>().keyword("font");
        add_type<KeyFrame>().suffix(".kframe").keyword("keyframe");
        add_type<Lighting>().suffix(".lightn").keyword("lighting");
-       add_type<Material>().suffix(".mat").keyword("material");
+       add_type<Material>().suffix(".mat").creator(&Resources::create_material);
        add_type<Mesh>().keyword("mesh").creator(&Resources::create_mesh);
        add_type<Object>().keyword("object");
        add_type<PipelineTemplate>().suffix(".pipe").keyword("pipeline");
@@ -90,6 +90,19 @@ void Resources::set_resource_manager(ResourceManager *m)
        resource_manager = m;
 }
 
+Material *Resources::create_material(const string &name)
+{
+       if(RefPtr<IO::Seekable> io = open_raw(name))
+       {
+               DataFile::Parser parser(*io, name);
+               Material::GenericLoader ldr(this);
+               ldr.load(parser);
+               return ldr.get_material();
+       }
+
+       return 0;
+}
+
 Mesh *Resources::create_mesh(const string &name)
 {
        if(!resource_manager)
index 238d6c544c373c4fdde4848784600a6246e8a1b1..0b37449978761e4e963889623e0af15c0a848b03 100644 (file)
@@ -7,6 +7,7 @@
 namespace Msp {
 namespace GL {
 
+class Material;
 class Mesh;
 class Program;
 class ResourceManager;
@@ -41,6 +42,7 @@ public:
        void set_resource_manager(ResourceManager *);
 
 protected:
+       Material *create_material(const std::string &);
        Mesh *create_mesh(const std::string &);
        Texture2D *create_texture2d(const std::string &);
        Program *create_program(const std::string &);