namespace GL {
Object::Object():
- meshes(1, static_cast<Mesh *>(0)),
- technique(0),
- main_texture(0),
- material(0)
+ meshes(1),
+ own_technique(false),
+ technique(0)
{ }
Object::~Object()
{
+ if(own_technique)
+ delete technique;
}
void Object::render(const Tag &tag) const
{
- if(!can_render(tag))
+ const RenderPass *pass=get_pass(tag);
+ if(!pass)
return;
- const ObjectPass *pass=get_pass(tag);
- setup_render(pass);
+ Bind bind(*pass);
meshes[0]->draw();
- finish_render(pass);
}
void Object::render(const ObjectInstance &inst, const Tag &tag) const
{
- if(!can_render(tag))
+ const RenderPass *pass=get_pass(tag);
+ if(!pass)
return;
- const ObjectPass *pass=get_pass(tag);
- setup_render(pass);
+ Bind bind(*pass);
render_instance(inst, tag);
meshes[0]->draw();
- finish_render(pass);
}
-bool Object::can_render(const Tag &tag) const
+const RenderPass *Object::get_pass(const Tag &tag) const
{
- if(technique)
- return technique->has_pass(tag);
- else
- return tag.id==0;
-}
-
-const ObjectPass *Object::get_pass(const Tag &tag) const
-{
- if(technique)
- return &technique->get_pass(tag);
- else if(tag.id==0)
+ if(!technique->has_pass(tag))
return 0;
- throw KeyError("Unknown pass");
-}
-
-void Object::setup_render(const ObjectPass *pass) const
-{
- if(!meshes[0])
- throw InvalidState("Trying to render Object without mesh");
-
- if(pass && pass->shprog)
- {
- pass->shprog->bind();
- pass->shdata->apply();
- for(unsigned i=0; i<textures.size(); ++i)
- {
- TexUnit::activate(i);
- textures[i]->bind();
- }
- }
- else if(main_texture && (!pass || pass->use_textures))
- main_texture->bind();
-
- if(material)
- material->bind();
-}
-
-void Object::finish_render(const ObjectPass *pass) const
-{
- if(pass && pass->shprog)
- {
- Program::unbind();
- for(unsigned i=textures.size(); i--;)
- {
- TexUnit::activate(i);
- Texture::unbind();
- }
- }
- else if(main_texture)
- Texture::unbind();
-
- if(material)
- Material::unbind();
+ return &technique->get_pass(tag);
}
void Object::render_instance(const ObjectInstance &inst, const Tag &tag) const
DataFile::CollectionObjectLoader<Object>(o, &c)
{
add("lod_mesh", &Loader::lod_mesh);
- add("material", &Object::material);
- add("material_inline", &Loader::material_inline);
add("mesh", &Loader::mesh);
- add("shader_texture", &Loader::shader_texture);
add("technique", &Loader::technique);
- add("texture", &Loader::texture);
-}
-
-void Object::Loader::finish()
-{
- if(obj.technique && !obj.main_texture)
- obj.main_texture=obj.technique->get_main_texture();
- for(unsigned i=0; i<obj.textures.size(); ++i)
- {
- if(!obj.textures[i])
- {
- obj.textures[i]=obj.technique->get_texture(i);
- if(!obj.textures[i])
- throw Exception("Object does not specify all textures required by Technique");
- }
- }
+ add("technique", &Object::technique);
}
void Object::Loader::lod_mesh(unsigned l, const string &n)
{
obj.meshes.resize(l+1, 0);
- obj.meshes[l]=coll->get<Mesh>(n);
-}
-
-void Object::Loader::material_inline()
-{
- RefPtr<Material> mat=new Material;
- load_sub(*mat);
- coll->add(format("_%p", mat.get()), mat.get());
- obj.material=mat.release();
+ obj.meshes[l]=get_collection().get<Mesh>(n);
}
void Object::Loader::mesh(const string &n)
{
- obj.meshes[0]=coll->get<Mesh>(n);
-}
-
-void Object::Loader::shader_texture(const string &n)
-{
- if(!obj.technique)
- throw InvalidState("Can't specify shader textures without a Technique");
-
- string::size_type eqsign=n.find('=');
- if(eqsign==string::npos)
- throw InvalidParameterValue("Must specify texture slot name");
-
- obj.textures[obj.technique->get_texture_index(n.substr(0, eqsign))]=coll->get<Texture>(n.substr(eqsign+1));
-}
-
-void Object::Loader::technique(const string &n)
-{
- obj.technique=coll->get<Technique>(n);
- obj.textures.resize(obj.technique->get_n_textures());
- obj.material=obj.technique->get_material();
+ obj.meshes[0]=get_collection().get<Mesh>(n);
}
-void Object::Loader::texture(const string &n)
+void Object::Loader::technique()
{
- if(obj.main_texture)
- throw Exception("Only one main texture may be specified");
-
- Texture *tex=coll->get<Texture>(n);
- if(obj.technique)
- obj.textures[obj.technique->get_texture_index("texture")]=tex;
- obj.main_texture=tex;
+ RefPtr<Technique> tch=new Technique;
+ load_sub(*tch, get_collection());
+ obj.technique=tch.release();
+ obj.own_technique=true;
}
} // namespace GL
#define MSP_GL_OBJECT_H_
#include <vector>
+#include "misc.h"
#include "objectpass.h"
#include "renderable.h"
class Texture;
/**
-Stores data for a complete 3D object. An Object must always have a Mesh, and
-may also have a Technique to determine its appearance. Textures and material
-specified by the Technique may be overridden. Simple textured objects are also
-possible without a Technique.
+Stores a Mesh together with a Technique to determine its appearance.
It is possible to use a single Object for rendering multiple identical or
similar objects. See class ObjectInstance.
{
private:
std::vector<const Mesh *> meshes;
+ bool own_technique;
const Technique *technique;
- std::vector<const Texture *> textures;
- const Texture *main_texture;
- const Material *material;
public:
class Loader: public DataFile::CollectionObjectLoader<Object>
Loader(Object &, Collection &);
private:
- virtual void finish();
void lod_mesh(unsigned, const std::string &);
- void material_inline();
void mesh(const std::string &);
- void shader_texture(const std::string &);
- void technique(const std::string &);
- void texture(const std::string &);
+ void technique();
};
Object();
template<typename Iter>
void render(Iter begin, Iter end, const Tag &tag=Tag()) const
{
- if(!can_render(tag))
+ const RenderPass *pass=get_pass(tag);
+ if(!pass)
return;
- const ObjectPass *pass=get_pass(tag);
- setup_render(pass);
+ Bind bind(*pass);
for(Iter i=begin; i!=end; ++i)
render_instance(**i, tag);
- finish_render(pass);
}
private:
- bool can_render(const Tag &) const;
- const ObjectPass *get_pass(const Tag &) const;
- void setup_render(const ObjectPass *) const;
- void finish_render(const ObjectPass *) const;
+ const RenderPass *get_pass(const Tag &) const;
void render_instance(const ObjectInstance &, const Tag &) const;
};
+++ /dev/null
-/* $Id$
-
-This file is part of libmspgl
-Copyright © 2007 Mikko Rasa, Mikkosoft Productions
-Distributed under the LGPL
-*/
-
-#include <msp/datafile/collection.h>
-#include "objectpass.h"
-#include "program.h"
-#include "programdata.h"
-
-using namespace std;
-
-namespace Msp {
-namespace GL {
-
-ObjectPass::ObjectPass():
- shprog(0),
- shdata(0),
- use_textures(true)
-{ }
-
-ObjectPass::~ObjectPass()
-{
-}
-
-
-ObjectPass::Loader::Loader(ObjectPass &p, Collection &c):
- DataFile::CollectionObjectLoader<ObjectPass>(p, &c)
-{
- add("shader", &Loader::shader);
- add("use_textures", &ObjectPass::use_textures);
-}
-
-void ObjectPass::Loader::shader(const string &n)
-{
- Program *shprog=coll->get<Program>(n);
- if(shprog) // Allow for unsupported shaders
- {
- RefPtr<ProgramData> shdata=new ProgramData;
- load_sub(*shdata, *shprog);
-
- obj.shprog=shprog;
- if(obj.shdata)
- delete obj.shdata;
- obj.shdata=shdata.release();
- }
-}
-
-} // namespace GL
-} // namespace Msp
+++ /dev/null
-/* $Id$
-
-This file is part of libmspgl
-Copyright © 2007 Mikko Rasa, Mikkosoft Productions
-Distributed under the LGPL
-*/
-
-#ifndef MSP_GL_OBJECTPASS_H_
-#define MSP_GL_OBJECTPASS_H_
-
-#include <msp/datafile/objectloader.h>
-
-namespace Msp {
-namespace GL {
-
-class Program;
-class ProgramData;
-
-struct ObjectPass
-{
- class Loader: public DataFile::CollectionObjectLoader<ObjectPass>
- {
- public:
- Loader(ObjectPass &, Collection &);
- private:
- void shader(const std::string &);
- };
-
- Program *shprog;
- ProgramData *shdata;
- bool use_textures;
-
- ObjectPass();
- ~ObjectPass();
-};
-
-} // namespace GL
-} // namespace Msp
-
-#endif
static RequireExtension _ext("GL_ARB_shader_objects");
}
+ProgramData::ProgramData(const ProgramData &other):
+ data(other.data)
+{
+ for(map<int, Uniform *>::iterator i=data.begin(); i!=data.end(); ++i)
+ i->second=i->second->clone();
+}
+
ProgramData::~ProgramData()
{
for(map<int, Uniform *>::iterator i=data.begin(); i!=data.end(); ++i)
private:
std::map<int, Uniform *> data;
- ProgramData(const ProgramData &);
ProgramData &operator=(const ProgramData &);
public:
ProgramData();
+ ProgramData(const ProgramData &);
~ProgramData();
void uniform(int, Uniform *);
--- /dev/null
+/* $Id$
+
+This file is part of libmspgl
+Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include <msp/core/refptr.h>
+#include <msp/datafile/collection.h>
+#include <msp/strings/formatter.h>
+#include "material.h"
+#include "renderpass.h"
+#include "program.h"
+#include "programdata.h"
+#include "texture.h"
+
+using namespace std;
+
+namespace Msp {
+namespace GL {
+
+const RenderPass *RenderPass::current=0;
+
+RenderPass::RenderPass():
+ shprog(0),
+ shdata(0),
+ own_material(false),
+ material(0)
+{ }
+
+RenderPass::RenderPass(const RenderPass &other):
+ shprog(other.shprog),
+ shdata(other.shdata ? new ProgramData(*other.shdata) : 0),
+ own_material(other.own_material),
+ material(own_material ? new Material(*other.material) : other.material),
+ textures(other.textures)
+{ }
+
+/*RenderPass &RenderPass::operator=(const RenderPass &other)
+{
+ shprog=other.shprog;
+ delete shdata;
+ shdata=(other.shdata ? new ProgramData(*other.shdata) : 0);
+ material=other.material;
+ use_material=other.use_material;
+ textures=other.textures;
+ use_textures=other.use_textures;
+
+ return *this;
+}*/
+
+RenderPass::~RenderPass()
+{
+ delete shdata;
+ if(own_material)
+ delete material;
+}
+
+void RenderPass::set_material(const Material *mat)
+{
+ material=mat;
+}
+
+unsigned RenderPass::get_texture_index(const string &slot) const
+{
+ for(unsigned i=0; i<textures.size(); ++i)
+ if(textures[i].name==slot)
+ return i;
+
+ throw KeyError("Unknown texture slot", slot);
+}
+
+void RenderPass::set_texture(const string &slot, const Texture *tex)
+{
+ textures[get_texture_index(slot)]=tex;
+}
+
+void RenderPass::bind() const
+{
+ if(this==current)
+ return;
+
+ const RenderPass *old=current;
+ current=this;
+
+ if(shprog)
+ {
+ shprog->bind();
+ shdata->apply();
+ }
+ else if(old && !old->shprog)
+ GL::Program::unbind();
+
+ if(material)
+ material->bind();
+ else if(old && !old->material)
+ GL::Material::unbind();
+
+ for(unsigned i=0; i<textures.size(); ++i)
+ if(textures[i].texture)
+ textures[i].texture->bind_to(i);
+ if(old)
+ {
+ for(unsigned i=textures.size(); i<old->textures.size(); ++i)
+ GL::Texture::unbind_from(i);
+ }
+}
+
+void RenderPass::unbind()
+{
+ if(current)
+ {
+ if(current->shprog)
+ GL::Program::unbind();
+
+ if(current->material)
+ GL::Material::unbind();
+
+ for(unsigned i=current->textures.size(); i--; )
+ GL::Texture::unbind_from(i);
+
+ current=0;
+ }
+}
+
+
+RenderPass::Loader::Loader(RenderPass &p, Collection &c):
+ DataFile::CollectionObjectLoader<RenderPass>(p, &c)
+{
+ add("shader", &RenderPass::shprog);
+ add("material", &Loader::material);
+ add("material", &RenderPass::material);
+ add("texture", &Loader::texture);
+ add("uniforms", &Loader::uniforms);
+}
+
+void RenderPass::Loader::finish()
+{
+ if(obj.shprog)
+ {
+ if(!obj.shdata)
+ obj.shdata=new ProgramData;
+
+ for(unsigned i=0; i<obj.textures.size(); ++i)
+ {
+ unsigned loc=obj.shprog->get_uniform_location(obj.textures[i].name);
+ obj.shdata->uniform(loc, static_cast<int>(i));
+ }
+ }
+}
+
+void RenderPass::Loader::material()
+{
+ // XXX Potential memory management trouble with multiple material statements
+ RefPtr<Material> mat=new Material;
+ load_sub(*mat);
+ obj.material=mat.release();
+ obj.own_material=true;
+}
+
+void RenderPass::Loader::texture(const string &n)
+{
+ const Texture *tex=(n.empty() ? 0 : get_collection().get<Texture>(n));
+ TextureSlot slot(tex);
+ slot.name=(obj.textures.empty() ? "texture" : format("texture%d", obj.textures.size()));
+ load_sub(slot);
+ obj.textures.push_back(slot);
+}
+
+void RenderPass::Loader::uniforms()
+{
+ if(!obj.shprog)
+ throw InvalidState("Can't load uniforms without a shader program");
+ if(!obj.shdata)
+ obj.shdata=new ProgramData;
+ load_sub(*obj.shdata, *obj.shprog);
+}
+
+
+RenderPass::TextureSlot::TextureSlot(const Texture *t):
+ texture(t)
+{ }
+
+
+RenderPass::TextureSlot::Loader::Loader(TextureSlot &s):
+ DataFile::ObjectLoader<TextureSlot>(s)
+{
+ add("name", &TextureSlot::name);
+}
+
+} // namespace GL
+} // namespace Msp
--- /dev/null
+/* $Id$
+
+This file is part of libmspgl
+Copyright © 2007-2008, 2010 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#ifndef MSP_GL_RENDERPASS_H_
+#define MSP_GL_RENDERPASS_H_
+
+#include <msp/datafile/objectloader.h>
+
+namespace Msp {
+namespace GL {
+
+class Material;
+class Program;
+class ProgramData;
+class Texture;
+
+/**
+Encapsulates the data that determines the appearance of a rendered surface.
+This includes shader and data for it, material and textures.
+*/
+class RenderPass
+{
+public:
+ class Loader: public DataFile::CollectionObjectLoader<RenderPass>
+ {
+ public:
+ Loader(RenderPass &, Collection &);
+
+ private:
+ virtual void finish();
+ void material();
+ void shader(const std::string &);
+ void texture(const std::string &);
+ void uniforms();
+ };
+
+private:
+ struct TextureSlot
+ {
+ class Loader: public DataFile::ObjectLoader<TextureSlot>
+ {
+ public:
+ Loader(TextureSlot &);
+ };
+
+ const Texture *texture;
+ std::string name;
+
+ TextureSlot(const Texture *);
+ };
+
+ Program *shprog;
+ ProgramData *shdata;
+ bool own_material;
+ const Material *material;
+ std::vector<TextureSlot> textures;
+
+ static const RenderPass *current;
+
+ RenderPass &operator=(const RenderPass &);
+public:
+ RenderPass();
+ RenderPass(const RenderPass &);
+ ~RenderPass();
+
+ void set_material(const Material *);
+ unsigned get_texture_index(const std::string &) const;
+ void set_texture(const std::string &, const Texture *);
+
+ void bind() const;
+
+ static void unbind();
+};
+
+} // namespace GL
+} // namespace Msp
+
+#endif
#include "objectinstance.h"
#include "scene.h"
-using namespace std;
-
namespace Msp {
namespace GL {
{
if(const ObjectInstance *oi=dynamic_cast<const ObjectInstance *>(&r))
{
- map<const Object *, set<const ObjectInstance *> >::iterator i=objects.find(&oi->get_object());
+ ObjectMap::iterator i=objects.find(&oi->get_object());
if(i!=objects.end())
{
i->second.erase(oi);
void Scene::render(const Tag &tag) const
{
- for(map<const Object *, set<const ObjectInstance *> >::const_iterator i=objects.begin(); i!=objects.end(); ++i)
+ for(ObjectMap::const_iterator i=objects.begin(); i!=objects.end(); ++i)
i->first->render(i->second.begin(), i->second.end(), tag);
- for(set<const Renderable *>::const_iterator i=renderables.begin(); i!=renderables.end(); ++i)
+ for(RenderableSet::const_iterator i=renderables.begin(); i!=renderables.end(); ++i)
(*i)->render(tag);
}
class Scene: public Renderable
{
private:
- std::map<const Object *, std::set<const ObjectInstance *> > objects;
- std::set<const Renderable *> renderables;
+ typedef std::set<const ObjectInstance *> InstanceSet;
+ typedef std::map<const Object *, InstanceSet> ObjectMap;
+ typedef std::set<const Renderable *> RenderableSet;
+
+ ObjectMap objects;
+ RenderableSet renderables;
public:
void add(const Renderable &);
namespace Msp {
namespace GL {
-Technique::Technique():
- main_texture(0),
- normal_pass(&passes[0]),
- material(0)
-{ }
-
-Technique::~Technique()
-{
- for(PassMap::iterator i=passes.begin(); i!=passes.end(); ++i)
- delete i->second.shdata;
-}
-
bool Technique::has_pass(const GL::Tag &tag) const
{
return passes.count(tag);
}
-const ObjectPass &Technique::get_pass(const GL::Tag &tag) const
+const RenderPass &Technique::get_pass(const GL::Tag &tag) const
{
PassMap::const_iterator i=passes.find(tag);
if(i==passes.end())
return i->second;
}
-unsigned Technique::get_texture_index(const std::string &n) const
-{
- for(unsigned i=0; i<textures.size(); ++i)
- if(textures[i].name==n)
- return i;
-
- throw KeyError("Unknown texture slot", n);
-}
-
-const Texture *Technique::get_texture(unsigned i) const
-{
- if(i>=textures.size())
- throw KeyError("Texture index out of range");
-
- return textures[i].texture;
-}
-
Technique::Loader::Loader(Technique &t, Collection &c):
DataFile::CollectionObjectLoader<Technique>(t, &c)
{
- add("material", &Technique::material);
- add("material_inline", &Loader::material_inline);
- add("pass", &Loader::pass);
- add("shader", &Loader::shader);
- add("shader_texture", &Loader::shader_texture);
- add("texture", &Loader::texture);
- add("texture_slot", &Loader::texture_slot);
-}
-
-void Technique::Loader::finish()
-{
- for(PassMap::iterator i=obj.passes.begin(); i!=obj.passes.end(); ++i)
- if(i->second.shdata)
- {
- for(unsigned j=0; j<obj.textures.size(); ++j)
- {
- unsigned loc=i->second.shprog->get_uniform_location(obj.textures[j].name);
- i->second.shdata->uniform(loc, static_cast<int>(j));
- }
- }
+ add("inherit", &Loader::inherit);
+ add("pass", &Loader::pass);
}
-void Technique::Loader::material_inline()
+void Technique::Loader::inherit(const string &n)
{
- RefPtr<Material> mat=new Material;
- load_sub(*mat);
- coll->add(format("_%p", mat.get()), mat.get());
- obj.material=mat.release();
+ obj.passes=get_collection().get<Technique>(n)->get_passes();
+ InheritLoader ldr(obj, get_collection());
+ load_sub_with(ldr);
}
void Technique::Loader::pass(const string &n)
Tag tag(n);
if(obj.passes.count(tag))
throw KeyError("Duplicate pass name", n);
- ObjectPass p;
+
+ RenderPass p;
load_sub(p, *coll);
- obj.passes[tag]=p;
+ obj.passes.insert(PassMap::value_type(tag, p));
}
-void Technique::Loader::shader(const string &n)
-{
- Program *shprog=coll->get<Program>(n);
- if(shprog) // Allow for unsupported shaders
- {
- RefPtr<ProgramData> shdata=new ProgramData;
- load_sub(*shdata, *shprog);
- obj.normal_pass->shprog=shprog;
- if(obj.normal_pass->shdata)
- delete obj.normal_pass->shdata;
- obj.normal_pass->shdata=shdata.release();
- }
+Technique::InheritLoader::InheritLoader(Technique &t, Collection &c):
+ DataFile::CollectionObjectLoader<Technique>(t, &c)
+{
+ add("texture", &InheritLoader::texture);
}
-void Technique::Loader::shader_texture(const string &n)
+void Technique::InheritLoader::texture(const string &slot, const string &name)
{
- string::size_type eqsign=n.find('=');
- TextureSlot tex;
- if(eqsign!=string::npos)
- {
- tex.name=n.substr(0, eqsign);
- tex.texture=coll->get<Texture>(n.substr(eqsign+1));
- }
- else
+ Texture *tex=get_collection().get<Texture>(name);
+ for(PassMap::iterator i=obj.passes.begin(); i!=obj.passes.end(); ++i)
{
- string::size_type dot=n.rfind('.');
- tex.name=n.substr(0, dot);
- tex.texture = coll->get<Texture>(n);
+ try
+ {
+ i->second.set_texture(slot, tex);
+ }
+ catch(const KeyError &)
+ { }
}
- for(string::iterator i=tex.name.begin(); i!=tex.name.end(); ++i)
- if(!isalnum(*i))
- *i='_';
- obj.textures.push_back(tex);
-}
-
-void Technique::Loader::texture(const string &n)
-{
- if(obj.main_texture)
- throw Exception("Only one main texture may be specified");
-
- obj.main_texture=coll->get<Texture>(n);
- TextureSlot tex;
- tex.name="texture";
- tex.texture=obj.main_texture;
- obj.textures.push_back(tex);
-}
-
-void Technique::Loader::texture_slot(const string &n)
-{
- TextureSlot tex;
- tex.name=n;
- obj.textures.push_back(tex);
}
} // namespace GL
class Texture;
/**
-Stores a complete multipass rendering technique for an Object. This includes
-shaders, textures and a material. A Technique can also specify empty texture
-slots which Objects must override.
*/
class Technique
{
Loader(Technique &, Collection &);
private:
- virtual void finish();
- void material_inline();
+ void inherit(const std::string &);
void pass(const std::string &);
- void shader(const std::string &);
- void shader_texture(const std::string &);
- void texture(const std::string &);
- void texture_slot(const std::string &);
};
private:
- struct TextureSlot
+ class InheritLoader: public Msp::DataFile::CollectionObjectLoader<Technique>
{
- std::string name;
- const Texture *texture;
-
- TextureSlot(): texture(0) { }
+ public:
+ InheritLoader(Technique &, Collection &);
+
+ private:
+ void texture(const std::string &, const std::string &);
};
- typedef std::map<Tag, ObjectPass> PassMap;
+ typedef std::map<Tag, RenderPass> PassMap;
- std::vector<TextureSlot> textures;
- const Texture *main_texture;
PassMap passes;
- ObjectPass *normal_pass;
- const Material *material;
public:
- Technique();
- ~Technique();
-
bool has_pass(const GL::Tag &) const;
- const ObjectPass &get_pass(const GL::Tag &) const;
- unsigned get_n_textures() const { return textures.size(); }
- unsigned get_texture_index(const std::string &) const;
- const Texture *get_texture(unsigned) const;
- const Texture *get_main_texture() const { return main_texture; }
- const Material *get_material() const { return material; }
+ const RenderPass &get_pass(const GL::Tag &) const;
+ const PassMap &get_passes() const { return passes; }
};
} // namespace GL
glUniform1iARB(index, v);
}
+Uniform1i *Uniform1i::clone() const
+{
+ return new Uniform1i(v);
+}
+
Uniform1f::Uniform1f(float v_):
v(v_)
glUniform1fARB(index, v);
}
+Uniform1f *Uniform1f::clone() const
+{
+ return new Uniform1f(v);
+}
+
Uniform2f::Uniform2f(float v0, float v1)
{
glUniform2fvARB(index, 1, v);
}
+Uniform2f *Uniform2f::clone() const
+{
+ return new Uniform2f(v[0], v[1]);
+}
+
Uniform3f::Uniform3f(float v0, float v1, float v2)
{
glUniform3fvARB(index, 1, v);
}
+Uniform3f *Uniform3f::clone() const
+{
+ return new Uniform3f(v[0], v[1], v[2]);
+}
+
Uniform4f::Uniform4f(float v0, float v1, float v2, float v3)
{
glUniform4fvARB(index, 1, v);
}
+Uniform4f *Uniform4f::clone() const
+{
+ return new Uniform4f(v[0], v[1], v[2], v[3]);
+}
+
} // namespace GL
} // namespace Msp
{
protected:
Uniform() { }
+private:
+ Uniform(const Uniform &);
+ Uniform &operator=(const Uniform &);
public:
virtual ~Uniform() { }
virtual void apply(int) const =0;
+ virtual Uniform *clone() const =0;
};
public:
Uniform1i(int v_);
+
virtual void apply(int index) const;
+ virtual Uniform1i *clone() const;
};
public:
Uniform1f(float v_);
+
virtual void apply(int index) const;
+ virtual Uniform1f *clone() const;
};
public:
Uniform2f(float v0, float v1);
+
virtual void apply(int index) const;
+ virtual Uniform2f *clone() const;
};
public:
Uniform3f(float v0, float v1, float v2);
+
virtual void apply(int index) const;
+ virtual Uniform3f *clone() const;
};
public:
Uniform4f(float v0, float v1, float v2, float v3);
+
virtual void apply(int index) const;
+ virtual Uniform4f *clone() const;
};
} // namespace GL