~UnsupportedExtension() throw() { }
};
+class CompileError: public Exception
+{
+public:
+ CompileError(const std::string &w_): Exception(w_) { }
+ ~CompileError() throw() { }
+};
+
} // namespace GL
} // namespace Msp
--- /dev/null
+/* $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
--- /dev/null
+/* $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
--- /dev/null
+/* $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
--- /dev/null
+/* $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
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
return glGetUniformLocationARB(id, n.c_str());
}
-void Program::uniform(int i, int v)
+/*void Program::uniform(int i, int v)
{
glUniform1iARB(i, v);
}
void Program::uniform_matrix4(int i, const float *v)
{
glUniformMatrix4fvARB(i, 1, false, v);
-}
+}*/
void Program::unbind()
{
add("vertex_shader", &Loader::vertex_shader);
add("fragment_shader", &Loader::fragment_shader);
+ add("attribute", &Loader::attribute);
}
Program::Loader::~Loader()
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
private:
void vertex_shader(const std::string &);
void fragment_shader(const std::string &);
+ void attribute(uint, const std::string &);
};
Program();
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();
--- /dev/null
+/* $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
--- /dev/null
+/* $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
*/
#include "arb_shader_objects.h"
+#include "except.h"
#include "extension.h"
#include "shader.h"
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
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;
--- /dev/null
+/* $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
--- /dev/null
+/* $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