]> git.tdb.fi Git - libs/gl.git/commitdiff
Add Uniform* classes to store uniform data of Programs
authorMikko Rasa <tdb@tdb.fi>
Fri, 26 Oct 2007 12:58:54 +0000 (12:58 +0000)
committerMikko Rasa <tdb@tdb.fi>
Fri, 26 Oct 2007 12:58:54 +0000 (12:58 +0000)
Add ProgramData class to manage said data
Remove uniform* functions from Program
Make Shader::compile and Program::link throw on failure
Support binding attributes of Programs in datafiles
Add Object and ObjectInstance classes

13 files changed:
source/except.h
source/object.cpp [new file with mode: 0644]
source/object.h [new file with mode: 0644]
source/objectinstance.cpp [new file with mode: 0644]
source/objectinstance.h [new file with mode: 0644]
source/program.cpp
source/program.h
source/programdata.cpp [new file with mode: 0644]
source/programdata.h [new file with mode: 0644]
source/shader.cpp
source/shader.h
source/uniform.cpp [new file with mode: 0644]
source/uniform.h [new file with mode: 0644]

index 4ba6f717ef30d24eb1098db22767f60aa33f8cca..7bcf59f4336cd3bda9ffb4669a939be73972d6dd 100644 (file)
@@ -27,6 +27,13 @@ public:
        ~UnsupportedExtension() throw() { }
 };
 
+class CompileError: public Exception
+{
+public:
+       CompileError(const std::string &w_): Exception(w_) { }
+       ~CompileError() throw() { }
+};
+
 } // namespace GL
 } // namespace Msp
 
diff --git a/source/object.cpp b/source/object.cpp
new file mode 100644 (file)
index 0000000..0469c31
--- /dev/null
@@ -0,0 +1,142 @@
+/* $Id$
+
+This file is part of libmspgl
+Copyright © 2007  Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include "except.h"
+#include "material.h"
+#include "mesh.h"
+#include "object.h"
+#include "objectinstance.h"
+#include "program.h"
+#include "programdata.h"
+#include "texture.h"
+#include "texunit.h"
+
+using namespace std;
+
+namespace Msp {
+namespace GL {
+
+Object::Object():
+       mesh(0),
+       shprog(0),
+       shdata(0),
+       material(0)
+{ }
+
+Object::~Object()
+{
+       delete shdata;
+}
+
+void Object::render(const ObjectInstance *inst) const
+{
+       setup_render();
+
+       if(inst)
+               inst->setup_render();
+
+       mesh->draw();
+
+       if(inst)
+               inst->finish_render();
+
+       finish_render();
+}
+
+void Object::render(const list<const ObjectInstance *> &insts) const
+{
+       setup_render();
+
+       for(list<const ObjectInstance *>::const_iterator i=insts.begin(); i!=insts.end(); ++i)
+       {
+               (*i)->setup_render();
+
+               mesh->draw();
+
+               (*i)->finish_render();
+       }
+
+       finish_render();
+}
+
+void Object::setup_render() const
+{
+       if(!mesh)
+               throw InvalidState("Trying to render Object without mesh");
+
+       if(shprog)
+       {
+               shprog->bind();
+               shdata->apply();
+               for(unsigned i=0; i<textures.size(); ++i)
+               {
+                       TexUnit::activate(i);
+                       textures[i]->bind();
+               }
+       }
+       else if(!textures.empty())
+               textures.front()->bind();
+
+       if(material)
+               material->apply();
+}
+
+void Object::finish_render() const
+{
+       if(shprog)
+               Program::unbind();
+       for(unsigned i=0; i<textures.size(); ++i)
+       {
+               TexUnit::activate(i);
+               Texture::unbind();
+       }
+}
+
+
+Object::Loader::Loader(Object &o, Collection &c):
+       obj(o),
+       coll(c)
+{
+       add("material", &Object::material);
+       add("mesh",     &Object::mesh);
+       add("shader",   &Loader::shader);
+       add("texture",  &Loader::texture);
+}
+
+Object::Loader::~Loader()
+{
+       if(obj.shdata)
+       {
+               for(unsigned i=0; i<textures.size(); ++i)
+                       obj.shdata->uniform(obj.shprog->get_uniform_location(textures[i]), static_cast<int>(i));
+       }
+}
+
+void Object::Loader::shader(const string &n)
+{
+       obj.shprog=&coll.get<Program>(n);
+       if(!obj.shdata)
+               obj.shdata=new ProgramData;
+}
+
+void Object::Loader::texture(const string &n)
+{
+       unsigned eqsign=n.find('=');
+       if(eqsign!=string::npos)
+       {
+               obj.textures.push_back(&coll.get<Texture>(n.substr(eqsign+1)));
+               textures.push_back(n.substr(0, eqsign));
+       }
+       else
+       {
+               obj.textures.push_back(&coll.get<Texture>(n));
+               textures.push_back(n);
+       }
+}
+
+} // namespace GL
+} // namespace Msp
diff --git a/source/object.h b/source/object.h
new file mode 100644 (file)
index 0000000..7a40a40
--- /dev/null
@@ -0,0 +1,88 @@
+/* $Id$
+
+This file is part of libmspgl
+Copyright © 2007  Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#ifndef MSP_GL_OBJECT_H_
+#define MSP_GL_OBJECT_H_
+
+#include <vector>
+#include <msp/datafile/collection.h>
+
+namespace Msp {
+namespace GL {
+
+class Material;
+class Mesh;
+class ObjectInstance;
+class Program;
+class ProgramData;
+class Texture;
+
+/**
+Stores data for a complete 3D object.  This includes a mesh, a shader and data
+for it and a number of textures.  Only the mesh is mandatory, other components
+are optional.
+
+See also class ObjectInstance.
+*/
+class Object
+{
+private:
+       Mesh *mesh;
+       std::vector<Texture *> textures;
+       Program *shprog;
+       ProgramData *shdata;
+       Material *material;
+
+public:
+       class Loader: public DataFile::Loader
+       {
+       public:
+               typedef DataFile::Collection Collection;
+
+       protected:
+               Object &obj;
+               Collection &coll;
+       private:
+               std::vector<std::string> textures;
+       
+       public:
+               Loader(Object &, Collection &);
+               ~Loader();
+
+               Object &get_object() const { return obj; }
+               Collection &get_collection() const { return coll; }
+       private:
+               void shader(const std::string &);
+               void texture(const std::string &);
+       };
+
+       Object();
+       ~Object();
+
+       Program *get_shader() const { return shprog; }
+
+       /**
+       Renders the object.  If an ObjectInstance is provided, its hook functions
+       are called.
+       */
+       void render(const ObjectInstance * =0) const;
+
+       /**
+       Renders multiple instances of the object in one go.  This may be a
+       performance improvement, as the object-specific render setup only has to be
+       done once.
+       */
+       void render(const std::list<const ObjectInstance *> &) const;
+private:
+       void setup_render() const;
+       void finish_render() const;
+};
+
+} // namespace GL
+} // namespace Msp
+
+#endif
diff --git a/source/objectinstance.cpp b/source/objectinstance.cpp
new file mode 100644 (file)
index 0000000..80f44cd
--- /dev/null
@@ -0,0 +1,25 @@
+/* $Id$
+
+This file is part of libmspgl
+Copyright © 2007  Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include "object.h"
+#include "objectinstance.h"
+#include "programdata.h"
+
+namespace Msp {
+namespace GL {
+
+ObjectInstance::ObjectInstance(const Object &obj):
+       object(obj)
+{ }
+
+void ObjectInstance::render() const
+{
+       object.render(this);
+}
+
+} // namespace GL
+} // namespaec Msp
diff --git a/source/objectinstance.h b/source/objectinstance.h
new file mode 100644 (file)
index 0000000..955ad1d
--- /dev/null
@@ -0,0 +1,47 @@
+/* $Id$
+
+This file is part of libmspgl
+Copyright © 2007  Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#ifndef MSP_GL_OBJETCINSTANCE_H_
+#define MSP_GL_OBJETCINSTANCE_H_
+
+namespace Msp {
+namespace GL {
+
+class Object;
+class ProgramData;
+
+/**
+Represents a single instance of an Object.  An application can derive another
+class from this and overload the hook functions to specify location and other
+instance-specific parameters for the rendered objects.
+*/
+class ObjectInstance
+{
+protected:
+       const Object &object;
+
+public:
+       ObjectInstance(const Object &);
+       void render() const;
+
+       /**
+       Hook function, called from Object just before rendering the mesh.
+       */
+       virtual void setup_render() const { }
+
+       /**
+       Hook function, called from Object right after rendering the mesh.
+       */
+       virtual void finish_render() const { }
+
+       virtual unsigned get_detail_level() const { return 0; }
+};
+
+} // namespace GL
+} // namespaec Msp
+
+#endif
index f0fffb1f3a82dc98f28d7dd24dfd53adb496cbb0..f057ea74aefbfe75d4aa447866d6a57a4cf05288 100644 (file)
@@ -74,20 +74,20 @@ void Program::set_del_shaders(bool ds)
        del_shaders=ds;
 }
 
-void Program::bind_attribute(int index, const string &name)
+void Program::bind_attribute(uint index, const string &name)
 {
        glBindAttribLocationARB(id, index, name.c_str());
 }
 
-bool Program::link()
+void Program::link()
 {
        for(list<Shader *>::iterator i=shaders.begin(); i!=shaders.end(); ++i)
-               if(!(*i)->get_compiled() && !(*i)->compile())
-                       return false;
+               if(!(*i)->get_compiled())
+                       (*i)->compile();
 
        glLinkProgramARB(id);
-       linked=get_param(GL_LINK_STATUS);
-       return linked;
+       if(!(linked=get_param(GL_LINK_STATUS)))
+               throw CompileError(get_info_log());
 }
 
 int Program::get_param(GLenum param) const
@@ -119,7 +119,7 @@ int Program::get_uniform_location(const string &n) const
        return glGetUniformLocationARB(id, n.c_str());
 }
 
-void Program::uniform(int i, int v)
+/*void Program::uniform(int i, int v)
 {
        glUniform1iARB(i, v);
 }
@@ -152,7 +152,7 @@ void Program::uniform4(int i, const float *v)
 void Program::uniform_matrix4(int i, const float *v)
 {
        glUniformMatrix4fvARB(i, 1, false, v);
-}
+}*/
 
 void Program::unbind()
 {
@@ -179,6 +179,7 @@ Program::Loader::Loader(Program &p):
 
        add("vertex_shader",   &Loader::vertex_shader);
        add("fragment_shader", &Loader::fragment_shader);
+       add("attribute",       &Loader::attribute);
 }
 
 Program::Loader::~Loader()
@@ -196,5 +197,10 @@ void Program::Loader::fragment_shader(const string &src)
        prog.attach_shader(*new Shader(FRAGMENT_SHADER, src));
 }
 
+void Program::Loader::attribute(uint i, const string &n)
+{
+       prog.bind_attribute(i, n);
+}
+
 } // namespace GL
 } // namespace Msp
index af249edefa2066c29bcf23e7c6f643ddd7d6c95c..ed5410076244bcb0f4c8d16e08482354a3d26ba7 100644 (file)
@@ -42,6 +42,7 @@ public:
        private:
                void vertex_shader(const std::string &);
                void fragment_shader(const std::string &);
+               void attribute(uint, const std::string &);
        };
 
        Program();
@@ -52,20 +53,13 @@ public:
        void detach_shader(Shader &shader);
        const std::list<Shader *> &get_shaders() const { return shaders; }
        void set_del_shaders(bool);
-       void bind_attribute(int, const std::string &);
-       bool link();
+       void bind_attribute(uint, const std::string &);
+       void link();
        int get_param(GLenum param) const;
        bool get_linked() const { return linked; }
        std::string get_info_log() const;
        void bind();
        int get_uniform_location(const std::string &) const;
-       void uniform(int, int);
-       void uniform(int, float);
-       void uniform(int, float, float);
-       void uniform(int, float, float, float);
-       void uniform(int, float, float, float, float);
-       void uniform4(int, const float *);
-       void uniform_matrix4(int, const float *);
 
        static void unbind();
 
diff --git a/source/programdata.cpp b/source/programdata.cpp
new file mode 100644 (file)
index 0000000..6d657d8
--- /dev/null
@@ -0,0 +1,90 @@
+/* $Id$
+
+This file is part of libmspgl
+Copyright © 2007  Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include "extension.h"
+#include "programdata.h"
+#include "uniform.h"
+
+using namespace std;
+
+namespace Msp {
+namespace GL {
+
+ProgramData::ProgramData()
+{
+       require_extension("GL_ARB_shader_objects");
+}
+
+ProgramData::~ProgramData()
+{
+       for(map<int, Uniform *>::iterator i=data.begin(); i!=data.end(); ++i)
+               delete i->second;
+}
+
+void ProgramData::uniform(int index, Uniform *uni)
+{
+       if(index<0)
+               return;
+
+       map<int, Uniform *>::iterator i=data.find(index);
+       if(i!=data.end())
+       {
+               delete i->second;
+               i->second=uni;
+       }
+       else
+               data[index]=uni;
+}
+
+void ProgramData::uniform(int index, int v)
+{
+       uniform(index, new Uniform1i(v));
+}
+
+void ProgramData::uniform(int index, float v)
+{
+       uniform(index, new Uniform1f(v));
+}
+
+void ProgramData::uniform(int index, float v0, float v1)
+{
+       uniform(index, new Uniform2f(v0, v1));
+}
+
+void ProgramData::uniform2(int index, const float *v)
+{
+       uniform(index, v[0], v[1]);
+}
+
+void ProgramData::uniform(int index, float v0, float v1, float v2)
+{
+       uniform(index, new Uniform3f(v0, v1, v2));
+}
+
+void ProgramData::uniform3(int index, const float *v)
+{
+       uniform(index, v[0], v[1], v[2]);
+}
+
+void ProgramData::uniform(int index, float v0, float v1, float v2, float v3)
+{
+       uniform(index, new Uniform4f(v0, v1, v2, v3));
+}
+
+void ProgramData::uniform4(int index, const float *v)
+{
+       uniform(index, v[0], v[1], v[2], v[3]);
+}
+
+void ProgramData::apply() const
+{
+       for(map<int, Uniform *>::const_iterator i=data.begin(); i!=data.end(); ++i)
+               i->second->apply(i->first);
+}
+
+} // namespace GL
+} // namespace Msp
diff --git a/source/programdata.h b/source/programdata.h
new file mode 100644 (file)
index 0000000..495ea22
--- /dev/null
@@ -0,0 +1,46 @@
+/* $Id$
+
+This file is part of libmspgl
+Copyright © 2007  Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#ifndef MSP_GL_PROGRAMDATA_H_
+#define MSP_GL_PROGRAMDATA_H_
+
+#include <map>
+
+namespace Msp {
+namespace GL {
+
+class Program;
+class Uniform;
+
+class ProgramData
+{
+private:
+       std::map<int, Uniform *> data;
+
+       ProgramData(const ProgramData &);
+       ProgramData &operator=(const ProgramData &);
+public:
+       ProgramData();
+       ~ProgramData();
+
+       void uniform(int, Uniform *);
+       void uniform(int, int);
+       void uniform(int, float);
+       void uniform(int, float, float);
+       void uniform2(int, const float *);
+       void uniform(int, float, float, float);
+       void uniform3(int, const float *);
+       void uniform(int, float, float, float, float);
+       void uniform4(int, const float *);
+       void uniform_matrix4(int, const float *);
+       void apply() const;
+};
+
+} // namespace GL
+} // namespace Msp
+
+#endif
index 45d56a16070c9fb9f50d892b3b6f17188877f8c5..3c01242650d3bd26009a0a57711e34dc4a0779f7 100644 (file)
@@ -6,6 +6,7 @@ Distributed under the LGPL
 */
 
 #include "arb_shader_objects.h"
+#include "except.h"
 #include "extension.h"
 #include "shader.h"
 
@@ -59,11 +60,11 @@ void Shader::source(const char *str, int len)
        source(1, &str, &len);
 }
 
-bool Shader::compile()
+void Shader::compile()
 {
        glCompileShaderARB(id);
-       compiled=get_param(GL_COMPILE_STATUS);
-       return compiled;
+       if(!(compiled=get_param(GL_COMPILE_STATUS)))
+               throw CompileError(get_info_log());
 }
 
 int Shader::get_param(GLenum param) const
index 43d03ce109cd61343099db8c5b9a11df6c27d398..dfa5af3b5c18da91ed15fd062b32f7d5f8568ff0 100644 (file)
@@ -31,7 +31,7 @@ public:
        void source(sizei count, const char **str, const int *len);
        void source(const std::string &str);
        void source(const char *str, int len);
-       bool compile();
+       void compile();
        uint get_id() const { return id; }
        bool get_compiled() const { return compiled; }
        int get_param(GLenum param) const;
diff --git a/source/uniform.cpp b/source/uniform.cpp
new file mode 100644 (file)
index 0000000..88c42d3
--- /dev/null
@@ -0,0 +1,73 @@
+/* $Id$
+
+This file is part of libmspgl
+Copyright © 2007  Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include "arb_shader_objects.h"
+#include "uniform.h"
+
+namespace Msp {
+namespace GL {
+
+Uniform1i::Uniform1i(int v_):
+       v(v_)
+{ }
+
+void Uniform1i::apply(int index) const
+{
+       glUniform1iARB(index, v);
+}
+
+
+Uniform1f::Uniform1f(float v_):
+       v(v_)
+{ }
+
+void Uniform1f::apply(int index) const
+{
+       glUniform1fARB(index, v);
+}
+
+
+Uniform2f::Uniform2f(float v0, float v1)
+{
+       v[0]=v0;
+       v[1]=v1;
+}
+
+void Uniform2f::apply(int index) const
+{
+       glUniform2fvARB(index, 1, v);
+}
+
+
+Uniform3f::Uniform3f(float v0, float v1, float v2)
+{
+       v[0]=v0;
+       v[1]=v1;
+       v[2]=v2;
+}
+
+void Uniform3f::apply(int index) const
+{
+       glUniform3fvARB(index, 1, v);
+}
+
+
+Uniform4f::Uniform4f(float v0, float v1, float v2, float v3)
+{
+       v[0]=v0;
+       v[1]=v1;
+       v[2]=v2;
+       v[3]=v3;
+}
+
+void Uniform4f::apply(int index) const
+{
+       glUniform4fvARB(index, 1, v);
+}
+
+} // namespace GL
+} // namespace Msp
diff --git a/source/uniform.h b/source/uniform.h
new file mode 100644 (file)
index 0000000..33b80e9
--- /dev/null
@@ -0,0 +1,82 @@
+/* $Id$
+
+This file is part of libmspgl
+Copyright © 2007  Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#ifndef MSP_GL_UNIFORM_H_
+#define MSP_GL_UNIFORM_H_
+
+namespace Msp {
+namespace GL {
+
+class Program;
+
+class Uniform
+{
+protected:
+       Uniform() { }
+public:
+       virtual void apply(int) const =0;
+};
+
+
+class Uniform1i: public Uniform
+{
+private:
+       int v;
+
+public:
+       Uniform1i(int v_);
+       virtual void apply(int index) const;
+};
+
+
+class Uniform1f: public Uniform
+{
+private:
+       float v;
+
+public:
+       Uniform1f(float v_);
+       virtual void apply(int index) const;
+};
+
+
+class Uniform2f: public Uniform
+{
+private:
+       float v[2];
+
+public:
+       Uniform2f(float v0, float v1);
+       virtual void apply(int index) const;
+};
+
+
+class Uniform3f: public Uniform
+{
+private:
+       float v[3];
+
+public:
+       Uniform3f(float v0, float v1, float v2);
+       virtual void apply(int index) const;
+};
+
+
+class Uniform4f: public Uniform
+{
+private:
+       float v[4];
+
+public:
+       Uniform4f(float v0, float v1, float v2, float v3);
+       virtual void apply(int index) const;
+};
+
+} // namespace GL
+} // namespace Msp
+
+#endif