//////////////////////////////////////////////////////////////////////////////// // Copyright (c) 2011, Computer Graphics Group RWTH Aachen University // // All rights reserved. // //////////////////////////////////////////////////////////////////////////////// #ifndef ACGL_OPENGL_OBJECTS_SHADERPROGRAM_HH #define ACGL_OPENGL_OBJECTS_SHADERPROGRAM_HH #include #include #include #include #include #include #include namespace ACGL{ namespace OpenGL{ class ShaderProgram { // ======================================================================================================== \/ // ============================================================================================ GPU CONTEXT \/ // ======================================================================================================== \/ private: static GLuint sShaderProgramContext; // ===================================================================================================== \/ // ============================================================================================ TYPEDEFS \/ // ===================================================================================================== \/ public: typedef std::vector< SharedShader > SharedShaderVec; // ========================================================================================================= \/ // ============================================================================================ CONSTRUCTORS \/ // ========================================================================================================= \/ public: ShaderProgram(void) : mContext(0), mShaders() { mContext = glCreateProgram(); } virtual ~ShaderProgram(void) { for(SharedShaderVec::size_type i = 0; i < mShaders.size(); ++i) { if(mShaders[i]) { // we have to detach all shaders, otherwise the attached shaders will get deleted by // OpenGL: "When a program object is deleted, all shader objects attached to it are detached" // - GL Spec glDetachShader(mContext, mShaders[i]->getContext()); } } // "DeleteProgram will silently ignore the value zero." - GL Spec glDeleteProgram(mContext); } // ==================================================================================================== \/ // ============================================================================================ GETTERS \/ // ==================================================================================================== \/ public: inline GLuint getContext (void) const { return mContext; } inline const SharedShaderVec& getShaders (void) const { return mShaders; } // ===================================================================================================== \/ // ============================================================================================ WRAPPERS \/ // ===================================================================================================== \/ public: inline GLint getUniformLocation (const std::string& _nameInShader) const { return glGetUniformLocation(mContext, _nameInShader.c_str()); } inline GLint getAttribLocation (const std::string& _nameInShader) const { return glGetAttribLocation (mContext, _nameInShader.c_str()); } inline void attachShader(const SharedShader& _shader) { mShaders.push_back(_shader); glAttachShader(mContext, _shader->getContext()); } bool link (void) const; inline void setUniform (GLint _location, GLint _v) const { glUniform1i (_location, _v); } inline void setUniform (GLint _location, GLfloat _v) const { glUniform1f (_location, _v); } inline void setUniform (GLint _location, const glm::vec2& _v) const { glUniform2fv(_location, 1, glm::value_ptr(_v)); } inline void setUniform (GLint _location, const glm::vec3& _v) const { glUniform3fv(_location, 1, glm::value_ptr(_v)); } inline void setUniform (GLint _location, const glm::vec4& _v) const { glUniform4fv(_location, 1, glm::value_ptr(_v)); } inline void setUniform (GLint _location, const glm::mat2& _v) const { glUniformMatrix2fv(_location, 1, GL_FALSE, glm::value_ptr(_v)); } inline void setUniform (GLint _location, const glm::mat3& _v) const { glUniformMatrix3fv(_location, 1, GL_FALSE, glm::value_ptr(_v)); } inline void setUniform (GLint _location, const glm::mat4& _v) const { glUniformMatrix4fv(_location, 1, GL_FALSE, glm::value_ptr(_v)); } inline void setTexture (GLint _location, const SharedTexture& _texture, GLenum _unit = 0) const { glUniform1i(_location, _unit); _texture->bind(_unit); } inline void use (void) const { if(sShaderProgramContext == mContext) return; glUseProgram(mContext); sShaderProgramContext = mContext; } inline GLint getUniformLocation( const char *_name ) const { return glGetUniformLocation( mContext, _name ); } // =================================================================================================== \/ // ============================================================================== HIGH LEVEL FUNCTIONS \/ // =================================================================================================== \/ inline void setUniform (const std::string& _nameInShader, GLint _v) const { glUniform1i (getUniformLocation(_nameInShader), _v); } inline void setUniform (const std::string& _nameInShader, GLfloat _v) const { glUniform1f (getUniformLocation(_nameInShader), _v); } inline void setUniform (const std::string& _nameInShader, const glm::vec2& _v) const { glUniform2fv(getUniformLocation(_nameInShader), 1, glm::value_ptr(_v)); } inline void setUniform (const std::string& _nameInShader, const glm::vec3& _v) const { glUniform3fv(getUniformLocation(_nameInShader), 1, glm::value_ptr(_v)); } inline void setUniform (const std::string& _nameInShader, const glm::vec4& _v) const { glUniform4fv(getUniformLocation(_nameInShader), 1, glm::value_ptr(_v)); } inline void setUniform (const std::string& _nameInShader, const glm::mat2& _v) const { glUniformMatrix2fv(getUniformLocation(_nameInShader), 1, GL_FALSE, glm::value_ptr(_v)); } inline void setUniform (const std::string& _nameInShader, const glm::mat3& _v) const { glUniformMatrix3fv(getUniformLocation(_nameInShader), 1, GL_FALSE, glm::value_ptr(_v)); } inline void setUniform (const std::string& _nameInShader, const glm::mat4& _v) const { glUniformMatrix4fv(getUniformLocation(_nameInShader), 1, GL_FALSE, glm::value_ptr(_v)); } inline void setTexture (const std::string& _nameInShader, const SharedTexture& _texture, GLenum _unit = 0) const { glUniform1i(getUniformLocation(_nameInShader), _unit); _texture->bind(_unit); } // =================================================================================================== \/ // ============================================================================================ FIELDS \/ // =================================================================================================== \/ protected: void bindAttributeLocations() const; GLuint mContext; SharedShaderVec mShaders; }; typedef std::tr1::shared_ptr SharedShaderProgram; } // OpenGL } // ACGL #endif // ACGL_OPENGL_OBJECTS_SHADERPROGRAM_HH