ShaderProgram.hh 12 KB
Newer Older
Robert Menzel's avatar
Robert Menzel committed
1 2 3 4 5
////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2011, Computer Graphics Group RWTH Aachen University         //
// All rights reserved.                                                       //
////////////////////////////////////////////////////////////////////////////////

6 7
#ifndef ACGL_OPENGL_OBJECTS_SHADERPROGRAM_HH
#define ACGL_OPENGL_OBJECTS_SHADERPROGRAM_HH
Robert Menzel's avatar
Robert Menzel committed
8

Robert Menzel's avatar
Robert Menzel committed
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
/*
 * A ShaderProgram is a wrapper around an OpenGL Program: A combination of Shaders
 * that are linked together to controll the programmable pipeline stages.
 *
 * A ShaderProgram is still quite low-level and just wraps the OpenGL object itself.
 *
 * One note on uniforms:
 * There are basically four ways to set uniform values here:
 *
 * setUniform(        GLint       _location, VALUE );
 * setUniform(        std::string _location, VALUE );
 * setProgramUniform( GLint       _location, VALUE );
 * setProgramUniform( std::string _location, VALUE );
 *
 * The versions with a std::string as a location are easy to use, just provide the name
 * the uniform is called in the shaderfile. But it will have to query the uniform location
 * each call and thus is inefficient! It would be faster to query the location once using
 * getUniformLocation( std::string ); and use the returned value in combination with the
 * set*Uniform( GLint, ...) versions.
 *
 * Both are provided as setUniform and setProgramUniform:
 * In order for setUniform(...) to work as intendet the ShaderProgram has to be active ( use() ),
 * setProgramUniform(...) does not have this limitation and is based on direct state access
 * (via an extension or a basic simulation of the extension).
 * Use setProgramUniform if you can't know which program is in use right now, setUniform should
 * be prefered for performance critical parts of your app.
 *
 * In short: setProgramUniform( std::string _location, VALUE ); is the most error proof option
 *           and good for testing out new stuff
 *           setUniform( GLint _location, VALUE ); is best for performance critical code thats
 *           well tested
 *
 */

Robert Menzel's avatar
Robert Menzel committed
43 44
#include <ACGL/ACGL.hh>

45
#include <ACGL/Base/Macros.hh>
Robert Menzel's avatar
Robert Menzel committed
46 47 48
#include <ACGL/OpenGL/GL.hh>
#include <ACGL/OpenGL/Objects/Shader.hh>
#include <ACGL/OpenGL/Objects/Texture.hh>
49
#include <ACGL/Math/Math.hh>
Robert Menzel's avatar
Robert Menzel committed
50 51

#include <vector>
Robert Menzel's avatar
Robert Menzel committed
52
#include <tr1/memory>
Robert Menzel's avatar
Robert Menzel committed
53 54

namespace ACGL{
Robert Menzel's avatar
Robert Menzel committed
55
namespace OpenGL{
Robert Menzel's avatar
Robert Menzel committed
56 57 58

class ShaderProgram
{
59
    ACGL_NOT_COPYABLE(ShaderProgram)
60

Robert Menzel's avatar
Robert Menzel committed
61 62 63 64
    // ===================================================================================================== \/
    // ============================================================================================ TYPEDEFS \/
    // ===================================================================================================== \/
public:
65
    typedef std::vector< ConstSharedShader > ConstSharedShaderVec;
Robert Menzel's avatar
Robert Menzel committed
66 67 68 69 70 71

    // ========================================================================================================= \/
    // ============================================================================================ CONSTRUCTORS \/
    // ========================================================================================================= \/
public:
    ShaderProgram(void)
72
    :   mObjectName(0),
Robert Menzel's avatar
Robert Menzel committed
73 74
        mShaders()
    {
75
        mObjectName = glCreateProgram();
Robert Menzel's avatar
Robert Menzel committed
76 77 78 79 80
    }

    virtual ~ShaderProgram(void)
    {
        // "DeleteProgram will silently ignore the value zero." - GL Spec
81
        glDeleteProgram(mObjectName);
Robert Menzel's avatar
Robert Menzel committed
82 83 84 85 86 87
    }

    // ==================================================================================================== \/
    // ============================================================================================ GETTERS \/
    // ==================================================================================================== \/
public:
88 89 90
    inline       GLuint                operator()   (void) const { return mObjectName; }
    inline       GLuint                getObjectName(void) const { return mObjectName; }
    inline const ConstSharedShaderVec& getShaders   (void) const { return mShaders;    }
Robert Menzel's avatar
Robert Menzel committed
91 92 93 94 95

    // ===================================================================================================== \/
    // ============================================================================================ WRAPPERS \/
    // ===================================================================================================== \/
public:
96
    inline GLint getUniformLocation      (const std::string& _nameInShader) const { return glGetUniformLocation (mObjectName, _nameInShader.c_str()); }
Robert Menzel's avatar
Robert Menzel committed
97
#if (ACGL_OPENGL_VERSION >= 30)
98 99 100 101
    inline GLint getAttributeLocation    (const std::string& _nameInShader) const { return glGetAttribLocation  (mObjectName, _nameInShader.c_str()); }
    inline GLint getFragmentDataLocation (const std::string& _nameInShader) const { return glGetFragDataLocation(mObjectName, _nameInShader.c_str()); }
    inline void bindAttributeLocation    (const std::string& _nameInShader, GLuint _location) const { glBindAttribLocation   (mObjectName, _location, _nameInShader.c_str()); }
    inline void bindFragmentDataLocation (const std::string& _nameInShader, GLuint _location) const { glBindFragDataLocation (mObjectName, _location, _nameInShader.c_str()); }
Robert Menzel's avatar
Robert Menzel committed
102
#endif
103
    inline void use(void) const { glUseProgram(mObjectName); }
Robert Menzel's avatar
Robert Menzel committed
104

105
    inline void attachShader(const ConstSharedShader& _shader)
Robert Menzel's avatar
Robert Menzel committed
106 107
    {
        mShaders.push_back(_shader);
108
        glAttachShader( mObjectName, _shader->getObjectName() );
Robert Menzel's avatar
Robert Menzel committed
109 110 111 112
    }

    bool link (void) const;

Robert Menzel's avatar
Robert Menzel committed
113

114 115 116
    inline void setUniform (GLint _location, GLint _v)   const { glUniform1i (_location, _v); }
    inline void setUniform (GLint _location, GLfloat _v) const { glUniform1f (_location, _v); }

Robert Menzel's avatar
Robert Menzel committed
117 118 119
    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)); }
120 121 122 123

    inline void setUniform (GLint _location, const glm::mat2& _v, GLboolean _transpose = GL_FALSE) const { glUniformMatrix2fv(_location, 1, _transpose, glm::value_ptr(_v)); }
    inline void setUniform (GLint _location, const glm::mat3& _v, GLboolean _transpose = GL_FALSE) const { glUniformMatrix3fv(_location, 1, _transpose, glm::value_ptr(_v)); }
    inline void setUniform (GLint _location, const glm::mat4& _v, GLboolean _transpose = GL_FALSE) const { glUniformMatrix4fv(_location, 1, _transpose, glm::value_ptr(_v)); }
Robert Menzel's avatar
Robert Menzel committed
124

125
    inline void setTexture (GLint _location, const ConstSharedTexture& _texture, GLenum _unit = 0) const { glUniform1i(_location, _unit); _texture->bind(_unit); }
Robert Menzel's avatar
Robert Menzel committed
126

127 128

    //DSA versions:
129 130
    inline void setProgramUniform (GLint _location, GLint _v)   const { glProgramUniform1i (mObjectName, _location, _v); }
    inline void setProgramUniform (GLint _location, GLfloat _v) const { glProgramUniform1f (mObjectName, _location, _v); }
131

132 133 134
    inline void setProgramUniform (GLint _location, const glm::vec2& _v) const { glProgramUniform2fv(mObjectName, _location, 1, glm::value_ptr(_v)); }
    inline void setProgramUniform (GLint _location, const glm::vec3& _v) const { glProgramUniform3fv(mObjectName, _location, 1, glm::value_ptr(_v)); }
    inline void setProgramUniform (GLint _location, const glm::vec4& _v) const { glProgramUniform4fv(mObjectName, _location, 1, glm::value_ptr(_v)); }
135

136 137 138
    inline void setProgramUniform (GLint _location, const glm::mat2& _v, GLboolean _transpose = GL_FALSE) const { glProgramUniformMatrix2fv(mObjectName, _location, 1, _transpose, glm::value_ptr(_v)); }
    inline void setProgramUniform (GLint _location, const glm::mat3& _v, GLboolean _transpose = GL_FALSE) const { glProgramUniformMatrix3fv(mObjectName, _location, 1, _transpose, glm::value_ptr(_v)); }
    inline void setProgramUniform (GLint _location, const glm::mat4& _v, GLboolean _transpose = GL_FALSE) const { glProgramUniformMatrix4fv(mObjectName, _location, 1, _transpose, glm::value_ptr(_v)); }
139

140
    inline void setProgramTexture (GLint _location, const ConstSharedTexture& _texture, GLenum _unit = 0) const { glProgramUniform1i(mObjectName, _location, _unit); _texture->bind(_unit); }
141

Robert Menzel's avatar
Robert Menzel committed
142 143 144 145
    // =================================================================================================== \/
    // ============================================================================== HIGH LEVEL FUNCTIONS \/
    // =================================================================================================== \/

146 147 148 149 150 151 152
    inline void setUniform (const std::string& _nameInShader, GLint _v)   const { setUniform( getUniformLocation(_nameInShader), _v); }
    inline void setUniform (const std::string& _nameInShader, GLfloat _v) const { setUniform( getUniformLocation(_nameInShader), _v); }

    inline void setUniform (const std::string& _nameInShader, const glm::vec2& _v) const { setUniform( getUniformLocation(_nameInShader), _v); }
    inline void setUniform (const std::string& _nameInShader, const glm::vec3& _v) const { setUniform( getUniformLocation(_nameInShader), _v); }
    inline void setUniform (const std::string& _nameInShader, const glm::vec4& _v) const { setUniform( getUniformLocation(_nameInShader), _v); }

153 154 155
    inline void setUniform (const std::string& _nameInShader, const glm::mat2& _v, GLboolean _transpose = GL_FALSE) const { setUniform( getUniformLocation(_nameInShader), _v, _transpose ); }
    inline void setUniform (const std::string& _nameInShader, const glm::mat3& _v, GLboolean _transpose = GL_FALSE) const { setUniform( getUniformLocation(_nameInShader), _v, _transpose ); }
    inline void setUniform (const std::string& _nameInShader, const glm::mat4& _v, GLboolean _transpose = GL_FALSE) const { setUniform( getUniformLocation(_nameInShader), _v, _transpose ); }
156 157 158 159 160 161 162 163 164 165 166

    inline void setTexture (const std::string& _nameInShader, const ConstSharedTexture& _texture, GLenum _unit = 0) const { setUniform( getUniformLocation(_nameInShader), (GLint) _unit); _texture->bind(_unit); }


    //DSA versions:
    inline void setProgramUniform (const std::string& _nameInShader, GLint _v)   const { setProgramUniform( getUniformLocation(_nameInShader), _v); }
    inline void setProgramUniform (const std::string& _nameInShader, GLfloat _v) const { setProgramUniform( getUniformLocation(_nameInShader), _v); }

    inline void setProgramUniform (const std::string& _nameInShader, const glm::vec2& _v) const { setProgramUniform( getUniformLocation(_nameInShader), _v); }
    inline void setProgramUniform (const std::string& _nameInShader, const glm::vec3& _v) const { setProgramUniform( getUniformLocation(_nameInShader), _v); }
    inline void setProgramUniform (const std::string& _nameInShader, const glm::vec4& _v) const { setProgramUniform( getUniformLocation(_nameInShader), _v); }
167

168 169 170
    inline void setProgramUniform (const std::string& _nameInShader, const glm::mat2& _v, GLboolean _transpose = GL_FALSE) const { setProgramUniform( getUniformLocation(_nameInShader), _v, _transpose ); }
    inline void setProgramUniform (const std::string& _nameInShader, const glm::mat3& _v, GLboolean _transpose = GL_FALSE) const { setProgramUniform( getUniformLocation(_nameInShader), _v, _transpose ); }
    inline void setProgramUniform (const std::string& _nameInShader, const glm::mat4& _v, GLboolean _transpose = GL_FALSE) const { setProgramUniform( getUniformLocation(_nameInShader), _v, _transpose ); }
171

172
    inline void setProgramTexture (const std::string& _nameInShader, const ConstSharedTexture& _texture, GLenum _unit = 0) const { setProgramUniform( getUniformLocation(_nameInShader), (GLint) _unit); _texture->bind(_unit); }
Robert Menzel's avatar
Robert Menzel committed
173 174 175 176 177 178


    // =================================================================================================== \/
    // ============================================================================================ FIELDS \/
    // =================================================================================================== \/
protected:
179
    GLuint               mObjectName;
180
    ConstSharedShaderVec mShaders;
Robert Menzel's avatar
Robert Menzel committed
181 182
};

183
ACGL_SHARED_TYPEDEF(ShaderProgram)
Robert Menzel's avatar
Robert Menzel committed
184 185

} // OpenGL
Robert Menzel's avatar
Robert Menzel committed
186 187
} // ACGL

188
#endif // ACGL_OPENGL_OBJECTS_SHADERPROGRAM_HH