nuclear@0: #ifndef SHADER_H_ nuclear@0: #define SHADER_H_ nuclear@0: nuclear@0: #include nuclear@0: #include "vmath/vmath.h" nuclear@0: #include "opengl.h" nuclear@0: #include "dataset.h" nuclear@0: nuclear@0: class Shader { nuclear@0: private: nuclear@0: unsigned int sdr; nuclear@0: unsigned int type; nuclear@0: char *name; nuclear@0: nuclear@0: public: nuclear@0: Shader(); nuclear@0: ~Shader(); nuclear@0: nuclear@0: unsigned int get_id() const; nuclear@0: nuclear@0: void set_name(const char *name); nuclear@0: const char *get_name() const; nuclear@0: nuclear@0: bool create(const char *src, unsigned int type); nuclear@0: void destroy(); nuclear@0: nuclear@0: bool load(const char *fname, unsigned int type); nuclear@0: }; nuclear@0: nuclear@0: #define VSDR(s) s, GL_VERTEX_SHADER nuclear@0: #define FSDR(s) s, GL_FRAGMENT_SHADER nuclear@0: #define PSDR(s) FSDR(s) nuclear@0: #define GSDR(s) s, GL_GEOMETRY_SHADER nuclear@0: #define TCSDR(s) s, GL_TESS_CONTROL_SHADER nuclear@0: #define TESDR(s) s, GL_TESS_EVALUATION_SHADER nuclear@0: nuclear@0: class ShaderProg { nuclear@0: private: nuclear@0: unsigned int prog; nuclear@0: mutable bool must_link; nuclear@0: std::vector shaders; nuclear@0: nuclear@0: struct StateLocCache { int sidx, loc; }; nuclear@0: /** a cache of all st_ prefixed uniform locations and their corresponding nuclear@0: * index in the global uniform state vector (see unistate.h) nuclear@0: */ nuclear@0: mutable std::vector stloc_cache; nuclear@0: nuclear@0: void cache_state_uniforms() const; nuclear@0: void setup_state_uniforms() const; nuclear@0: nuclear@0: public: nuclear@0: static ShaderProg *current; nuclear@0: nuclear@0: ShaderProg(); nuclear@0: ~ShaderProg(); nuclear@0: nuclear@0: /// returns the OpenGL object id for this shader program nuclear@0: unsigned int get_id() const; nuclear@0: nuclear@0: /** takes a series of shaders, and constructs a program object by linking nuclear@0: * them together. Terminate with a null pointer (don't use 0!) */ nuclear@0: bool create(Shader *sdr, ...); nuclear@0: /// same as above, but with a va_list instead of variable arguments. nuclear@0: bool create(Shader *sdr, va_list ap); nuclear@0: /** takes two shaders (vertex and pixel) and constructs a program object by nuclear@0: * linking them together. Either one can be null. */ nuclear@0: bool create(Shader *vsdr, Shader *psdr); nuclear@0: nuclear@0: /** takes a series of shader source/shader type pairs and constructs a program nuclear@0: * object by linking them together. Terminate with a null pointer (don't use 0!) nuclear@0: * You can use the VSDR, PSDR, GSDR, TCSDR, TESDR convenience macros for passing nuclear@0: * the pairs. nuclear@0: * Example: create(VSDR(vsrc0), VSDR(vsrc1), PSDR(psrc), NULL); nuclear@0: */ nuclear@0: bool create(const char *src, unsigned int type, ...); nuclear@0: /// same as above, but with a va_list instead of variable arguments. nuclear@0: bool create(const char *src, unsigned int type, va_list ap); nuclear@0: /** takes two shaders source strings (vertex and pixel) and constructs nuclear@0: * a program object by linking them together. Either one can be null. */ nuclear@0: bool create(const char *vsrc, const char *psrc); nuclear@0: nuclear@0: void destroy(); nuclear@0: nuclear@0: /** takes a series of shader filename/shader type pairs, loads the shaders and nuclear@0: * constructs a program object by linking them together. Terminate with a null nuclear@0: * pointer (don't use 0!). You can use the VSDR, PSDR, GSDR, TCSDR, TESDR convenience nuclear@0: * macros for passing the pairs. nuclear@0: * Example: load(VSDR("vsdr1.glsl"), VSDR("vsdr2.glsl"), PSDR("pixel.glsl"), NULL); nuclear@0: */ nuclear@0: bool load(const char *fname, unsigned int type, ...); nuclear@0: /// same as above, but with a va_list instead of variable arguments. nuclear@0: bool load(const char *fname, unsigned int type, va_list ap); nuclear@0: /** takes the filenames of two shader files (vertex and pixel), loads them and nuclear@0: * constructs a program object by linking them together. Either one can be null */ nuclear@0: bool load(const char *vsrc, const char *psrc); nuclear@0: nuclear@0: void add_shader(Shader *sdr); nuclear@0: bool link() const; nuclear@0: nuclear@0: void bind() const; nuclear@0: nuclear@0: int get_attrib_location(const char *name) const; nuclear@0: void set_attrib_location(const char *name, int loc) const; nuclear@0: nuclear@0: int get_uniform_location(const char *name) const; nuclear@0: nuclear@0: bool set_uniform(int loc, int val) const; nuclear@0: bool set_uniform(int loc, float val) const; nuclear@0: bool set_uniform(int loc, const Vector2 &v) const; nuclear@0: bool set_uniform(int loc, const Vector3 &v) const; nuclear@0: bool set_uniform(int loc, const Vector4 &v) const; nuclear@0: bool set_uniform(int loc, const Matrix3x3 &m) const; nuclear@0: bool set_uniform(int loc, const Matrix4x4 &m) const; nuclear@0: nuclear@0: bool set_uniform(const char *name, int val) const; nuclear@0: bool set_uniform(const char *name, float val) const; nuclear@0: bool set_uniform(const char *name, const Vector2 &v) const; nuclear@0: bool set_uniform(const char *name, const Vector3 &v) const; nuclear@0: bool set_uniform(const char *name, const Vector4 &v) const; nuclear@0: bool set_uniform(const char *name, const Matrix3x3 &m) const; nuclear@0: bool set_uniform(const char *name, const Matrix4x4 &m) const; nuclear@0: nuclear@0: friend void setup_unistate(const ShaderProg*); nuclear@0: }; nuclear@0: nuclear@0: class ShaderSet : public DataSet { nuclear@0: private: nuclear@0: unsigned int type; nuclear@0: nuclear@0: public: nuclear@0: ShaderSet(unsigned int type); nuclear@0: }; nuclear@0: nuclear@0: #endif // SHADER_H_