From: Mikko Rasa Date: Fri, 26 Oct 2007 12:58:54 +0000 (+0000) Subject: Add Uniform* classes to store uniform data of Programs X-Git-Tag: 0.9~26 X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=commitdiff_plain;h=85e83ace47e5a9a8ae7263886255dd81afc69278 Add Uniform* classes to store uniform data of Programs 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 --- diff --git a/source/except.h b/source/except.h index 4ba6f717..7bcf59f4 100644 --- a/source/except.h +++ b/source/except.h @@ -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 index 00000000..0469c31a --- /dev/null +++ b/source/object.cpp @@ -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 &insts) const +{ + setup_render(); + + for(list::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; ibind(); + } + } + else if(!textures.empty()) + textures.front()->bind(); + + if(material) + material->apply(); +} + +void Object::finish_render() const +{ + if(shprog) + Program::unbind(); + for(unsigned i=0; iuniform(obj.shprog->get_uniform_location(textures[i]), static_cast(i)); + } +} + +void Object::Loader::shader(const string &n) +{ + obj.shprog=&coll.get(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(n.substr(eqsign+1))); + textures.push_back(n.substr(0, eqsign)); + } + else + { + obj.textures.push_back(&coll.get(n)); + textures.push_back(n); + } +} + +} // namespace GL +} // namespace Msp diff --git a/source/object.h b/source/object.h new file mode 100644 index 00000000..7a40a40b --- /dev/null +++ b/source/object.h @@ -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 +#include + +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 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 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; +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 index 00000000..80f44cd4 --- /dev/null +++ b/source/objectinstance.cpp @@ -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 index 00000000..955ad1dd --- /dev/null +++ b/source/objectinstance.h @@ -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 diff --git a/source/program.cpp b/source/program.cpp index f0fffb1f..f057ea74 100644 --- a/source/program.cpp +++ b/source/program.cpp @@ -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::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 diff --git a/source/program.h b/source/program.h index af249ede..ed541007 100644 --- a/source/program.h +++ b/source/program.h @@ -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 &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 index 00000000..6d657d8a --- /dev/null +++ b/source/programdata.cpp @@ -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::iterator i=data.begin(); i!=data.end(); ++i) + delete i->second; +} + +void ProgramData::uniform(int index, Uniform *uni) +{ + if(index<0) + return; + + map::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::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 index 00000000..495ea22f --- /dev/null +++ b/source/programdata.h @@ -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 + +namespace Msp { +namespace GL { + +class Program; +class Uniform; + +class ProgramData +{ +private: + std::map 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 diff --git a/source/shader.cpp b/source/shader.cpp index 45d56a16..3c012426 100644 --- a/source/shader.cpp +++ b/source/shader.cpp @@ -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 diff --git a/source/shader.h b/source/shader.h index 43d03ce1..dfa5af3b 100644 --- a/source/shader.h +++ b/source/shader.h @@ -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 index 00000000..88c42d37 --- /dev/null +++ b/source/uniform.cpp @@ -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 index 00000000..33b80e93 --- /dev/null +++ b/source/uniform.h @@ -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