/******************************************************************************** * OpenGL-Framework * * Copyright (c) 2013 Daniel Chappuis * ********************************************************************************* * * * This software is provided 'as-is', without any express or implied warranty. * * In no event will the authors be held liable for any damages arising from the * * use of this software. * * * * Permission is granted to anyone to use this software for any purpose, * * including commercial applications, and to alter it and redistribute it * * freely, subject to the following restrictions: * * * * 1. The origin of this software must not be misrepresented; you must not claim * * that you wrote the original software. If you use this software in a * * product, an acknowledgment in the product documentation would be * * appreciated but is not required. * * * * 2. Altered source versions must be plainly marked as such, and must not be * * misrepresented as being the original software. * * * * 3. This notice may not be removed or altered from any source distribution. * * * ********************************************************************************/ #ifndef SHADER_H #define SHADER_H // Libraries #include #include #include #include #include #include #include #include #include #include namespace openglframework { // Class Shader class Shader { private : // -------------------- Attributes -------------------- // // Shader object program ID GLuint32_t mProgramObjectID; // Filenames of the vertex and fragment shaders etk::String mFilenameVertexShader, mFilenameFragmentShader; public : // -------------------- Methods -------------------- // // Constructor Shader(); // Constructor with arguments Shader(const etk::String vertexShaderFilename, const etk::String fragmentShaderFilename); // Destructor ~Shader(); // Create the shader bool create(const etk::String vertexShaderFilename, const etk::String fragmentShaderFilename); // Clear the shader void destroy(); // Bind the shader void bind() const; // Unbind the shader void unbind() const; // Return the location of a uniform variable inside a shader program GLint32_t getUniformLocation(const etk::String& variableName, bool errorIfMissing = true) const; // Return the location of an attribute variable inside a shader program GLint32_t getAttribLocation(const etk::String& variableName, bool errorIfMissing = true) const; // Set a float uniform value to this shader (be careful if the uniform is not // used in the shader, the compiler will remove it, then when you will try // to set it, an assert will occur) void setFloatUniform(const etk::String& variableName, float value, bool errorIfMissing = true) const; // Set an int32_t uniform value to this shader (be careful if the uniform is not // used in the shader, the compiler will remove it, then when you will try // to set it, an assert will occur) void setIntUniform(const etk::String& variableName, int32_t value, bool errorIfMissing = true) const; // Set a vector 2 uniform value to this shader (be careful if the uniform is not // used in the shader, the compiler will remove it, then when you will try // to set it, an assert will occur) void setvec2Uniform(const etk::String& variableName, const vec2& v, bool errorIfMissing = true) const; // Set a vector 3 uniform value to this shader (be careful if the uniform is not // used in the shader, the compiler will remove it, then when you will try // to set it, an assert will occur) void setvec3Uniform(const etk::String& variableName, const vec3& v, bool errorIfMissing = true) const; // Set a vector 4 uniform value to this shader (be careful if the uniform is not // used in the shader, the compiler will remove it, then when you will try // to set it, an assert will occur) void setVector4Uniform(const etk::String& variableName, const Vector4 &v, bool errorIfMissing = true) const; // Set a 3x3 matrix uniform value to this shader (be careful if the uniform is not // used in the shader, the compiler will remove it, then when you will try // to set it, an assert will occur) void setetk::Matrix3x3Uniform(const etk::String& variableName, const float* matrix, bool transpose = false, bool errorIfMissing = true) const; // Set a 3x3 matrix uniform value to this shader (be careful if the uniform is not // used in the shader, the compiler will remove it, then when you will try // to set it, an assert will occur) void setetk::Matrix3x3Uniform(const etk::String& variableName, const Matrix3& matrix, bool errorIfMissing = true) const; // Set a 4x4 matrix uniform value to this shader (be careful if the uniform is not // used in the shader, the compiler will remove it, then when you will try // to set it, an assert will occur) void setMatrix4x4Uniform(const etk::String& variableName, const float* matrix, bool transpose = false, bool errorIfMissing = true) const; // Set a 4x4 matrix uniform value to this shader (be careful if the uniform is not // used in the shader, the compiler will remove it, then when you will try // to set it, an assert will occur) void setMatrix4x4Uniform(const etk::String& variableName, const Matrix4& matrix, bool errorIfMissing = true) const; // Return the shader object program ID GLuint32_t getProgramObjectId() const; // Return true if the needed OpenGL extensions are available static bool checkOpenGLExtensions(); }; // Bind the shader inline void Shader::bind() const { assert(mProgramObjectID != 0); glUseProgram(mProgramObjectID); } // Unbind the shader inline void Shader::unbind() const { assert(mProgramObjectID != 0); glUseProgram(0); } // Return the location of a uniform variable inside a shader program inline GLint32_t Shader::getUniformLocation(const etk::String& variableName, bool errorIfMissing) const { assert(mProgramObjectID != 0); GLint32_t location = glGetUniformLocation(mProgramObjectID, variableName.c_str()); if (location == -1 && errorIfMissing) { std::cerr << "Error in vertex shader " << mFilenameVertexShader << " or in fragment shader" << mFilenameFragmentShader << " : No Uniform variable : " << variableName << std::endl; throw std::logic_error("Error in Shader"); } return location; } // Return the location of an attribute variable inside a shader program inline GLint32_t Shader::getAttribLocation(const etk::String& variableName, bool errorIfMissing) const { assert(mProgramObjectID != 0); GLint32_t location = glGetAttribLocation(mProgramObjectID, variableName.c_str()); if (location == -1 && errorIfMissing) { std::cerr << "Error in vertex shader " << mFilenameVertexShader << " or in fragment shader" << mFilenameFragmentShader << " : No Uniform variable : " << variableName << std::endl; throw std::logic_error("Error in Shader"); } return location; } // Clear the shader inline void Shader::destroy() { if (mProgramObjectID != 0) { glDeleteProgram(mProgramObjectID); mProgramObjectID = 0; } } // Set a float uniform value to this shader (be careful if the uniform is not // used in the shader, the compiler will remove it, then when you will try // to set it, an assert will occur) inline void Shader::setFloatUniform(const etk::String& variableName, float value, bool errorIfMissing) const { assert(mProgramObjectID != 0); GLint32_t location = getUniformLocation(variableName, errorIfMissing); if (location != -1) { glUniform1f(location, value); } } // Set an int32_t uniform value to this shader (be careful if the uniform is not // used in the shader, the compiler will remove it, then when you will try // to set it, an assert will occur) inline void Shader::setIntUniform(const etk::String& variableName, int32_t value, bool errorIfMissing) const { assert(mProgramObjectID != 0); GLint32_t location = getUniformLocation(variableName, errorIfMissing); if (location != -1) { glUniform1i(location, value); } } // Set a vector 2 uniform value to this shader (be careful if the uniform is not // used in the shader, the compiler will remove it, then when you will try // to set it, an assert will occur) inline void Shader::setvec2Uniform(const etk::String& variableName, const vec2& v, bool errorIfMissing) const { assert(mProgramObjectID != 0); GLint32_t location = getUniformLocation(variableName, errorIfMissing); if (location != -1) { glUniform2f(location, v.x(), v.y()); } } // Set a vector 3 uniform value to this shader (be careful if the uniform is not // used in the shader, the compiler will remove it, then when you will try // to set it, an assert will occur) inline void Shader::setvec3Uniform(const etk::String& variableName, const vec3 &v, bool errorIfMissing) const { assert(mProgramObjectID != 0); GLint32_t location = getUniformLocation(variableName, errorIfMissing); if (location != -1) { glUniform3f(location, v.x(), v.y(), v.z()); } } // Set a vector 4 uniform value to this shader (be careful if the uniform is not // used in the shader, the compiler will remove it, then when you will try // to set it, an assert will occur) inline void Shader::setVector4Uniform(const etk::String& variableName, const Vector4& v, bool errorIfMissing) const { assert(mProgramObjectID != 0); GLint32_t location = getUniformLocation(variableName, errorIfMissing); if (location != -1) { glUniform4f(location, v.x(), v.y(), v.z(), v.w); } } // Set a 4x4 matrix uniform value to this shader (be careful if the uniform is not // used in the shader, the compiler will remove it, then when you will try // to set it, an assert will occur) inline void Shader::setetk::Matrix3x3Uniform(const etk::String& variableName, const float* matrix, bool transpose, bool errorIfMissing) const { assert(mProgramObjectID != 0); GLint32_t location = getUniformLocation(variableName, errorIfMissing); if (location != -1) { glUniformMatrix3fv(location, 1, transpose, matrix); } } // Set a 3x3 matrix uniform value to this shader (be careful if the uniform is not // used in the shader, the compiler will remove it, then when you will try // to set it, an assert will occur) inline void Shader::setetk::Matrix3x3Uniform(const etk::String& variableName, const Matrix3& matrix, bool errorIfMissing) const { assert(mProgramObjectID != 0); GLfloat mat[9]; for (int32_t i=0; i<3; i++) { for (int32_t j=0; j<3; j++) { mat[i*3 + j] = matrix.getValue(i, j); } } GLint32_t location = getUniformLocation(variableName, errorIfMissing); if (location != -1) { glUniformMatrix3fv(location, 1, true, mat); } } // Set a 4x4 matrix uniform value to this shader (be careful if the uniform is not // used in the shader, the compiler will remove it, then when you will try // to set it, an assert will occur) inline void Shader::setMatrix4x4Uniform(const etk::String& variableName, const float* matrix, bool transpose, bool errorIfMissing) const { assert(mProgramObjectID != 0); GLint32_t location = getUniformLocation(variableName, errorIfMissing); if (location != -1) { glUniformMatrix4fv(location, 1, transpose, matrix); } } // Set a 4x4 matrix uniform value to this shader (be careful if the uniform is not // used in the shader, the compiler will remove it, then when you will try // to set it, an assert will occur) inline void Shader::setMatrix4x4Uniform(const etk::String& variableName, const Matrix4& matrix, bool errorIfMissing) const { assert(mProgramObjectID != 0); GLfloat mat[16]; for (int32_t i=0; i<4; i++) { for (int32_t j=0; j<4; j++) { mat[i*4 + j] = matrix.m[i][j]; } } GLint32_t location = getUniformLocation(variableName, errorIfMissing); if (location != -1) { glUniformMatrix4fv(location, 1, true, mat); } } // Return the shader object program ID inline GLuint32_t Shader::getProgramObjectId() const { return mProgramObjectID; } // Return true if the needed OpenGL extensions are available for shaders inline bool Shader::checkOpenGLExtensions() { // Check that GLSL vertex and fragment shaders are available on the platform //return (GLEW_VERSION_2_0 || (GLEW_ARB_vertex_shader && GLEW_ARB_fragment_shader)); return true; } } #endif