From: Mikko Rasa Date: Fri, 12 Feb 2010 15:50:13 +0000 (+0000) Subject: Allow copying of Uniforms and ProgramData X-Git-Url: http://git.tdb.fi/?a=commitdiff_plain;h=97015ec7bddd26aa746f5227e4109b7d32438cca;p=libs%2Fgl.git Allow copying of Uniforms and ProgramData Use typedefs in Scene for shorter code and to avoid collisions with GL::set Major rework of Object and Technique --- diff --git a/source/object.cpp b/source/object.cpp index f2d1f8bf..edfe39e5 100644 --- a/source/object.cpp +++ b/source/object.cpp @@ -25,94 +25,43 @@ namespace Msp { namespace GL { Object::Object(): - meshes(1, static_cast(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; ibind(); - } - } - 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 @@ -128,76 +77,28 @@ Object::Loader::Loader(Object &o, Collection &c): DataFile::CollectionObjectLoader(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; iget_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(n); -} - -void Object::Loader::material_inline() -{ - RefPtr mat=new Material; - load_sub(*mat); - coll->add(format("_%p", mat.get()), mat.get()); - obj.material=mat.release(); + obj.meshes[l]=get_collection().get(n); } void Object::Loader::mesh(const string &n) { - obj.meshes[0]=coll->get(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(n.substr(eqsign+1)); -} - -void Object::Loader::technique(const string &n) -{ - obj.technique=coll->get(n); - obj.textures.resize(obj.technique->get_n_textures()); - obj.material=obj.technique->get_material(); + obj.meshes[0]=get_collection().get(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(n); - if(obj.technique) - obj.textures[obj.technique->get_texture_index("texture")]=tex; - obj.main_texture=tex; + RefPtr tch=new Technique; + load_sub(*tch, get_collection()); + obj.technique=tch.release(); + obj.own_technique=true; } } // namespace GL diff --git a/source/object.h b/source/object.h index bf4a0524..d81c4ade 100644 --- a/source/object.h +++ b/source/object.h @@ -9,6 +9,7 @@ Distributed under the LGPL #define MSP_GL_OBJECT_H_ #include +#include "misc.h" #include "objectpass.h" #include "renderable.h" @@ -22,10 +23,7 @@ class Technique; 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. @@ -34,10 +32,8 @@ class Object: public Renderable { private: std::vector meshes; + bool own_technique; const Technique *technique; - std::vector textures; - const Texture *main_texture; - const Material *material; public: class Loader: public DataFile::CollectionObjectLoader @@ -46,13 +42,9 @@ public: 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(); @@ -81,20 +73,16 @@ public: template 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; }; diff --git a/source/objectpass.cpp b/source/objectpass.cpp deleted file mode 100644 index 01a6c2eb..00000000 --- a/source/objectpass.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* $Id$ - -This file is part of libmspgl -Copyright © 2007 Mikko Rasa, Mikkosoft Productions -Distributed under the LGPL -*/ - -#include -#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(p, &c) -{ - add("shader", &Loader::shader); - add("use_textures", &ObjectPass::use_textures); -} - -void ObjectPass::Loader::shader(const string &n) -{ - Program *shprog=coll->get(n); - if(shprog) // Allow for unsupported shaders - { - RefPtr shdata=new ProgramData; - load_sub(*shdata, *shprog); - - obj.shprog=shprog; - if(obj.shdata) - delete obj.shdata; - obj.shdata=shdata.release(); - } -} - -} // namespace GL -} // namespace Msp diff --git a/source/objectpass.h b/source/objectpass.h deleted file mode 100644 index e3cac702..00000000 --- a/source/objectpass.h +++ /dev/null @@ -1,40 +0,0 @@ -/* $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 - -namespace Msp { -namespace GL { - -class Program; -class ProgramData; - -struct ObjectPass -{ - class Loader: public DataFile::CollectionObjectLoader - { - public: - Loader(ObjectPass &, Collection &); - private: - void shader(const std::string &); - }; - - Program *shprog; - ProgramData *shdata; - bool use_textures; - - ObjectPass(); - ~ObjectPass(); -}; - -} // namespace GL -} // namespace Msp - -#endif diff --git a/source/programdata.cpp b/source/programdata.cpp index 9acb93bc..cc75f28d 100644 --- a/source/programdata.cpp +++ b/source/programdata.cpp @@ -20,6 +20,13 @@ ProgramData::ProgramData() static RequireExtension _ext("GL_ARB_shader_objects"); } +ProgramData::ProgramData(const ProgramData &other): + data(other.data) +{ + for(map::iterator i=data.begin(); i!=data.end(); ++i) + i->second=i->second->clone(); +} + ProgramData::~ProgramData() { for(map::iterator i=data.begin(); i!=data.end(); ++i) diff --git a/source/programdata.h b/source/programdata.h index 591ffee3..51ecc579 100644 --- a/source/programdata.h +++ b/source/programdata.h @@ -41,10 +41,10 @@ public: private: std::map data; - ProgramData(const ProgramData &); ProgramData &operator=(const ProgramData &); public: ProgramData(); + ProgramData(const ProgramData &); ~ProgramData(); void uniform(int, Uniform *); diff --git a/source/renderpass.cpp b/source/renderpass.cpp new file mode 100644 index 00000000..d2fe6688 --- /dev/null +++ b/source/renderpass.cpp @@ -0,0 +1,192 @@ +/* $Id$ + +This file is part of libmspgl +Copyright © 2007 Mikko Rasa, Mikkosoft Productions +Distributed under the LGPL +*/ + +#include +#include +#include +#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; ibind(); + 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; ibind_to(i); + if(old) + { + for(unsigned i=textures.size(); itextures.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(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; iget_uniform_location(obj.textures[i].name); + obj.shdata->uniform(loc, static_cast(i)); + } + } +} + +void RenderPass::Loader::material() +{ + // XXX Potential memory management trouble with multiple material statements + RefPtr 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(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(s) +{ + add("name", &TextureSlot::name); +} + +} // namespace GL +} // namespace Msp diff --git a/source/renderpass.h b/source/renderpass.h new file mode 100644 index 00000000..223f57dc --- /dev/null +++ b/source/renderpass.h @@ -0,0 +1,82 @@ +/* $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 + +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 + { + 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 + { + public: + Loader(TextureSlot &); + }; + + const Texture *texture; + std::string name; + + TextureSlot(const Texture *); + }; + + Program *shprog; + ProgramData *shdata; + bool own_material; + const Material *material; + std::vector 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 diff --git a/source/scene.cpp b/source/scene.cpp index c28192d4..28b794b0 100644 --- a/source/scene.cpp +++ b/source/scene.cpp @@ -9,8 +9,6 @@ Distributed under the LGPL #include "objectinstance.h" #include "scene.h" -using namespace std; - namespace Msp { namespace GL { @@ -26,7 +24,7 @@ void Scene::remove(const Renderable &r) { if(const ObjectInstance *oi=dynamic_cast(&r)) { - map >::iterator i=objects.find(&oi->get_object()); + ObjectMap::iterator i=objects.find(&oi->get_object()); if(i!=objects.end()) { i->second.erase(oi); @@ -40,10 +38,10 @@ void Scene::remove(const Renderable &r) void Scene::render(const Tag &tag) const { - for(map >::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_iterator i=renderables.begin(); i!=renderables.end(); ++i) + for(RenderableSet::const_iterator i=renderables.begin(); i!=renderables.end(); ++i) (*i)->render(tag); } diff --git a/source/scene.h b/source/scene.h index 05c5b678..6a4be91d 100644 --- a/source/scene.h +++ b/source/scene.h @@ -21,8 +21,12 @@ class ObjectInstance; class Scene: public Renderable { private: - std::map > objects; - std::set renderables; + typedef std::set InstanceSet; + typedef std::map ObjectMap; + typedef std::set RenderableSet; + + ObjectMap objects; + RenderableSet renderables; public: void add(const Renderable &); diff --git a/source/technique.cpp b/source/technique.cpp index 26837b61..78060e01 100644 --- a/source/technique.cpp +++ b/source/technique.cpp @@ -20,24 +20,12 @@ using namespace std; 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()) @@ -45,55 +33,19 @@ const ObjectPass &Technique::get_pass(const GL::Tag &tag) const return i->second; } -unsigned Technique::get_texture_index(const std::string &n) const -{ - for(unsigned i=0; i=textures.size()) - throw KeyError("Texture index out of range"); - - return textures[i].texture; -} - Technique::Loader::Loader(Technique &t, Collection &c): DataFile::CollectionObjectLoader(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; jsecond.shprog->get_uniform_location(obj.textures[j].name); - i->second.shdata->uniform(loc, static_cast(j)); - } - } + add("inherit", &Loader::inherit); + add("pass", &Loader::pass); } -void Technique::Loader::material_inline() +void Technique::Loader::inherit(const string &n) { - RefPtr mat=new Material; - load_sub(*mat); - coll->add(format("_%p", mat.get()), mat.get()); - obj.material=mat.release(); + obj.passes=get_collection().get(n)->get_passes(); + InheritLoader ldr(obj, get_collection()); + load_sub_with(ldr); } void Technique::Loader::pass(const string &n) @@ -101,64 +53,31 @@ 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(n); - if(shprog) // Allow for unsupported shaders - { - RefPtr 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(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(n.substr(eqsign+1)); - } - else + Texture *tex=get_collection().get(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(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(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 diff --git a/source/technique.h b/source/technique.h index 3bb347ea..cc81b531 100644 --- a/source/technique.h +++ b/source/technique.h @@ -18,9 +18,6 @@ class Tag; 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 { @@ -31,43 +28,28 @@ public: 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 { - 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 PassMap; + typedef std::map PassMap; - std::vector 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 diff --git a/source/uniform.cpp b/source/uniform.cpp index 88c42d37..8ed1336e 100644 --- a/source/uniform.cpp +++ b/source/uniform.cpp @@ -20,6 +20,11 @@ void Uniform1i::apply(int index) const glUniform1iARB(index, v); } +Uniform1i *Uniform1i::clone() const +{ + return new Uniform1i(v); +} + Uniform1f::Uniform1f(float v_): v(v_) @@ -30,6 +35,11 @@ void Uniform1f::apply(int index) const glUniform1fARB(index, v); } +Uniform1f *Uniform1f::clone() const +{ + return new Uniform1f(v); +} + Uniform2f::Uniform2f(float v0, float v1) { @@ -42,6 +52,11 @@ void Uniform2f::apply(int index) const glUniform2fvARB(index, 1, v); } +Uniform2f *Uniform2f::clone() const +{ + return new Uniform2f(v[0], v[1]); +} + Uniform3f::Uniform3f(float v0, float v1, float v2) { @@ -55,6 +70,11 @@ void Uniform3f::apply(int index) const 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) { @@ -69,5 +89,10 @@ void Uniform4f::apply(int index) const glUniform4fvARB(index, 1, v); } +Uniform4f *Uniform4f::clone() const +{ + return new Uniform4f(v[0], v[1], v[2], v[3]); +} + } // namespace GL } // namespace Msp diff --git a/source/uniform.h b/source/uniform.h index e6b4ca3a..ac73e99d 100644 --- a/source/uniform.h +++ b/source/uniform.h @@ -17,10 +17,14 @@ class Uniform { protected: Uniform() { } +private: + Uniform(const Uniform &); + Uniform &operator=(const Uniform &); public: virtual ~Uniform() { } virtual void apply(int) const =0; + virtual Uniform *clone() const =0; }; @@ -31,7 +35,9 @@ private: public: Uniform1i(int v_); + virtual void apply(int index) const; + virtual Uniform1i *clone() const; }; @@ -42,7 +48,9 @@ private: public: Uniform1f(float v_); + virtual void apply(int index) const; + virtual Uniform1f *clone() const; }; @@ -53,7 +61,9 @@ private: public: Uniform2f(float v0, float v1); + virtual void apply(int index) const; + virtual Uniform2f *clone() const; }; @@ -64,7 +74,9 @@ private: public: Uniform3f(float v0, float v1, float v2); + virtual void apply(int index) const; + virtual Uniform3f *clone() const; }; @@ -75,7 +87,9 @@ private: public: Uniform4f(float v0, float v1, float v2, float v3); + virtual void apply(int index) const; + virtual Uniform4f *clone() const; }; } // namespace GL