ShaderProgram.hh 25.3 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
/**
Robert Menzel's avatar
Robert Menzel committed
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>
Robert Menzel's avatar
Robert Menzel committed
49
#include <ACGL/OpenGL/Data/LocationMappings.hh>
50
#include <ACGL/Math/Math.hh>
Robert Menzel's avatar
Robert Menzel committed
51 52 53 54

#include <vector>

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
    inline       GLuint                getObjectName(void) const { return mObjectName; }
    inline const ConstSharedShaderVec& getShaders   (void) const { return mShaders;    }
Robert Menzel's avatar
Robert Menzel committed
90 91 92 93 94

    // ===================================================================================================== \/
    // ============================================================================================ WRAPPERS \/
    // ===================================================================================================== \/
public:
Robert Menzel's avatar
Robert Menzel committed
95
    //! use, or activate it for rendering, also needed to set uniforms:
96
    inline void use(void) const { glUseProgram(mObjectName); }
Robert Menzel's avatar
Robert Menzel committed
97

Robert Menzel's avatar
Robert Menzel committed
98
    //! attach a single shader, don't forget to relink!
99
    inline void attachShader(const ConstSharedShader& _shader)
Robert Menzel's avatar
Robert Menzel committed
100 101
    {
        mShaders.push_back(_shader);
102
        glAttachShader( mObjectName, _shader->getObjectName() );
Robert Menzel's avatar
Robert Menzel committed
103 104
    }

Robert Menzel's avatar
Robert Menzel committed
105
    //! link the program, has to be redone after changing input or output locations:
Robert Menzel's avatar
Robert Menzel committed
106 107
    bool link (void) const;

108 109 110 111 112 113 114 115
#if (ACGL_OPENGL_VERSION >= 41)
    //! set the program separable to be used in a program pipeline object
    inline bool setSeparable( GLboolean _b = GL_TRUE ) {
        glProgramParameteri( mObjectName, GL_PROGRAM_SEPARABLE, _b );
        return link();
    }
#endif

116
    // ===================================================================================================== \/
Robert Menzel's avatar
Robert Menzel committed
117
    // =========================================================================================== LOCATIONS \/
118
    // ===================================================================================================== \/
Robert Menzel's avatar
Robert Menzel committed
119

Robert Menzel's avatar
Robert Menzel committed
120 121 122 123 124
    //////////// uniform (block) locations:
    inline GLint getUniformLocation    (const std::string& _nameInShader) const { return glGetUniformLocation (mObjectName, _nameInShader.c_str()); }

#if (ACGL_OPENGL_VERSION >= 31)
    //! if the block name does not exist, GL_INVALID_INDEX will get returned
125 126 127 128 129 130 131 132 133
    inline GLuint getUniformBlockIndex (const std::string& _nameInShader) const { return glGetUniformBlockIndex(mObjectName, _nameInShader.c_str()); }

    //! binds a uniform block, the string version will ignore a non-existent block
    inline void   setUniformBlockBinding( GLuint            _blockIndex, GLuint _bindingPoint ) const { glUniformBlockBinding( mObjectName, _blockIndex, _bindingPoint ); openGLCommonErrorOccured(); }
    inline void   setUniformBlockBinding( const std::string& _blockName, GLuint _bindingPoint ) const {
        GLuint blockIndex = getUniformBlockIndex(_blockName);
        if (blockIndex != GL_INVALID_INDEX) glUniformBlockBinding( mObjectName, blockIndex, _bindingPoint );
        openGLCommonErrorOccured();
    }
Robert Menzel's avatar
Robert Menzel committed
134

135 136
    GLint getUniformBlockBinding( const std::string& _blockName ) const { return getUniformBlockBinding( getUniformBlockIndex(_blockName)); }
    GLint getUniformBlockBinding( GLuint            _blockIndex ) const {
137 138 139 140 141
        GLint bindingPoint;
        glGetActiveUniformBlockiv( mObjectName, _blockIndex, GL_UNIFORM_BLOCK_BINDING, &bindingPoint );
        return bindingPoint;
    }

Robert Menzel's avatar
Robert Menzel committed
142
    //! returns a mapping from the uniforms in a given block to the offset within the block
143 144
    SharedLocationMappings getUniformOffsetsOfBlock( const std::string &_blockName  ) const { return getUniformOffsetsOfBlock(getUniformBlockIndex(_blockName)); }
    SharedLocationMappings getUniformOffsetsOfBlock( GLuint             _blockIndex ) const;
Robert Menzel's avatar
Robert Menzel committed
145 146

    //! returns the size in bytes of the uniform block, can be used to allocate the right amount of memory
147 148
    GLsizeiptr getUniformBlockSize( const std::string &_blockName  ) const { return getUniformBlockSize(getUniformBlockIndex(_blockName)); }
    GLsizeiptr getUniformBlockSize( GLuint             _blockIndex ) const ;
Robert Menzel's avatar
Robert Menzel committed
149 150

#endif // OpenGL >= 3.1
Robert Menzel's avatar
Robert Menzel committed
151 152

    //////////// attribute locations:
Robert Menzel's avatar
Robert Menzel committed
153 154
    inline GLint getAttributeLocation  (const std::string& _nameInShader) const { return glGetAttribLocation  (mObjectName, _nameInShader.c_str()); }
    inline void bindAttributeLocation  (const std::string& _nameInShader, GLuint _location) const { glBindAttribLocation   (mObjectName, _location, _nameInShader.c_str()); }
155

156
    //! Sets the attribute locations of this ShaderProgram according to the mappings specified in _locationMappings
157
    void setAttributeLocations( ConstSharedLocationMappings _locationMappings );
Robert Menzel's avatar
Robert Menzel committed
158 159 160 161 162
    //! Get all attribute names with there locations:
    SharedLocationMappings getAttributeLocations();

    //////////// fragdata locations:
#if (ACGL_OPENGL_VERSION >= 30)
Robert Menzel's avatar
Robert Menzel committed
163
    //! if the location does not exist, -1 will get returned
Robert Menzel's avatar
Robert Menzel committed
164 165
    inline GLint getFragmentDataLocation (const std::string& _nameInShader) const { return glGetFragDataLocation(mObjectName, _nameInShader.c_str()); }
    inline void bindFragmentDataLocation (const std::string& _nameInShader, GLuint _location) const { glBindFragDataLocation (mObjectName, _location, _nameInShader.c_str()); }
166 167 168

    //! Sets the fragment data locations of this ShaderProgram according to the mappings specified in
    void setFragmentDataLocations( ConstSharedLocationMappings _locationMappings );
Robert Menzel's avatar
Robert Menzel committed
169 170 171 172
    //! Get all fragdata names with there locations:
    SharedLocationMappings getFragmentDataLocations();
#endif // OpenGL >= 3.0

173 174 175
    // ===================================================================================================== \/
    // ============================================================================================ UNIFORMS \/
    // ===================================================================================================== \/
176
public:
177 178
    // int by location
    inline void setUniform (GLint _location, GLint _v)             const { glUniform1i (_location, _v); }
179
    inline void setUniform (GLint _location, GLsizei _n, GLint *_v)const { glUniform1iv(_location, _n, _v); }
180 181 182 183 184 185
    inline void setUniform (GLint _location, const glm::ivec2& _v) const { glUniform2iv(_location, 1, glm::value_ptr(_v)); }
    inline void setUniform (GLint _location, const glm::ivec3& _v) const { glUniform3iv(_location, 1, glm::value_ptr(_v)); }
    inline void setUniform (GLint _location, const glm::ivec4& _v) const { glUniform4iv(_location, 1, glm::value_ptr(_v)); }

    // int DSA by location
    inline void setProgramUniform (GLint _location, GLint _v)             const { glProgramUniform1i (mObjectName, _location, _v); }
186
    inline void setProgramUniform (GLint _location, GLsizei _n, GLint *_v)const { glProgramUniform1iv(mObjectName, _location, _n, _v); }
187 188 189
    inline void setProgramUniform (GLint _location, const glm::ivec2& _v) const { glProgramUniform2iv(mObjectName, _location, 1, glm::value_ptr(_v)); }
    inline void setProgramUniform (GLint _location, const glm::ivec3& _v) const { glProgramUniform3iv(mObjectName, _location, 1, glm::value_ptr(_v)); }
    inline void setProgramUniform (GLint _location, const glm::ivec4& _v) const { glProgramUniform4iv(mObjectName, _location, 1, glm::value_ptr(_v)); }
190

191 192 193
#if (ACGL_OPENGL_VERSION >= 30)
    // unsigned int by location
    inline void setUniform (GLint _location, GLuint _v)            const { glUniform1ui (_location, _v); }
194
    inline void setUniform (GLint _location, GLsizei _n, GLuint*_v)const { glUniform1uiv(_location, _n, _v); }
195 196 197 198 199 200
    inline void setUniform (GLint _location, const glm::uvec2& _v) const { glUniform2uiv(_location, 1, glm::value_ptr(_v)); }
    inline void setUniform (GLint _location, const glm::uvec3& _v) const { glUniform3uiv(_location, 1, glm::value_ptr(_v)); }
    inline void setUniform (GLint _location, const glm::uvec4& _v) const { glUniform4uiv(_location, 1, glm::value_ptr(_v)); }

    // unsigned int DSA by location
    inline void setProgramUniform (GLint _location, GLuint _v)            const { glProgramUniform1ui (mObjectName, _location, _v); }
201
    inline void setProgramUniform (GLint _location, GLsizei _n, GLuint*_v)const { glProgramUniform1uiv(mObjectName, _location, _n, _v); }
202 203 204 205 206 207 208
    inline void setProgramUniform (GLint _location, const glm::uvec2& _v) const { glProgramUniform2uiv(mObjectName, _location, 1, glm::value_ptr(_v)); }
    inline void setProgramUniform (GLint _location, const glm::uvec3& _v) const { glProgramUniform3uiv(mObjectName, _location, 1, glm::value_ptr(_v)); }
    inline void setProgramUniform (GLint _location, const glm::uvec4& _v) const { glProgramUniform4uiv(mObjectName, _location, 1, glm::value_ptr(_v)); }
#endif // OpenGL >= 3.0

    // float by location
    inline void setUniform (GLint _location, GLfloat _v)          const { glUniform1f (_location, _v); }
209
    inline void setUniform (GLint _location, GLsizei _n, GLfloat*_v)const{ glUniform1fv(_location, _n, _v); }
Robert Menzel's avatar
Robert Menzel committed
210 211 212
    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)); }
213

214 215
    // float DSA by location
    inline void setProgramUniform (GLint _location, GLfloat _v)          const { glProgramUniform1f (mObjectName, _location, _v); }
216
    inline void setProgramUniform (GLint _location, GLsizei _n, GLfloat*_v)const{ glProgramUniform1fv(mObjectName, _location, _n, _v); }
217 218 219
    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)); }
220

221 222 223
#if (ACGL_OPENGL_VERSION >= 40)
    // double by location
    inline void setUniform (GLint _location, GLdouble _v)          const { glUniform1d (_location, _v); }
224
    inline void setUniform (GLint _location, GLsizei _n, GLdouble*_v)const{ glUniform1dv(_location, _n, _v); }
225 226 227 228 229 230
    inline void setUniform (GLint _location, const glm::dvec2& _v) const { glUniform2dv(_location, 1, glm::value_ptr(_v)); }
    inline void setUniform (GLint _location, const glm::dvec3& _v) const { glUniform3dv(_location, 1, glm::value_ptr(_v)); }
    inline void setUniform (GLint _location, const glm::dvec4& _v) const { glUniform4dv(_location, 1, glm::value_ptr(_v)); }

    // double DSA by location
    inline void setProgramUniform (GLint _location, GLdouble _v)          const { glProgramUniform1d (mObjectName, _location, _v); }
231
    inline void setProgramUniform (GLint _location, GLsizei _n, GLdouble*_v)const{glProgramUniform1dv(mObjectName, _location, _n, _v); }
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282
    inline void setProgramUniform (GLint _location, const glm::dvec2& _v) const { glProgramUniform2dv(mObjectName, _location, 1, glm::value_ptr(_v)); }
    inline void setProgramUniform (GLint _location, const glm::dvec3& _v) const { glProgramUniform3dv(mObjectName, _location, 1, glm::value_ptr(_v)); }
    inline void setProgramUniform (GLint _location, const glm::dvec4& _v) const { glProgramUniform4dv(mObjectName, _location, 1, glm::value_ptr(_v)); }
#endif // OpenGL >= 4.0

    // float matrix by location
    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::mat2x3& _v, GLboolean _transpose = GL_FALSE) const { glUniformMatrix2x3fv(_location, 1, _transpose, glm::value_ptr(_v)); }
    inline void setUniform (GLint _location, const glm::mat2x4& _v, GLboolean _transpose = GL_FALSE) const { glUniformMatrix2x4fv(_location, 1, _transpose, glm::value_ptr(_v)); }
    inline void setUniform (GLint _location, const glm::mat3x2& _v, GLboolean _transpose = GL_FALSE) const { glUniformMatrix3x2fv(_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::mat3x4& _v, GLboolean _transpose = GL_FALSE) const { glUniformMatrix3x4fv(_location, 1, _transpose, glm::value_ptr(_v)); }
    inline void setUniform (GLint _location, const glm::mat4x2& _v, GLboolean _transpose = GL_FALSE) const { glUniformMatrix4x2fv(_location, 1, _transpose, glm::value_ptr(_v)); }
    inline void setUniform (GLint _location, const glm::mat4x3& _v, GLboolean _transpose = GL_FALSE) const { glUniformMatrix4x3fv(_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)); }

    // float matrix DSA by location
    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::mat2x3& _v, GLboolean _transpose = GL_FALSE) const { glProgramUniformMatrix2x3fv(mObjectName, _location, 1, _transpose, glm::value_ptr(_v)); }
    inline void setProgramUniform (GLint _location, const glm::mat2x4& _v, GLboolean _transpose = GL_FALSE) const { glProgramUniformMatrix2x4fv(mObjectName, _location, 1, _transpose, glm::value_ptr(_v)); }
    inline void setProgramUniform (GLint _location, const glm::mat3x2& _v, GLboolean _transpose = GL_FALSE) const { glProgramUniformMatrix3x2fv(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::mat3x4& _v, GLboolean _transpose = GL_FALSE) const { glProgramUniformMatrix3x4fv(mObjectName, _location, 1, _transpose, glm::value_ptr(_v)); }
    inline void setProgramUniform (GLint _location, const glm::mat4x2& _v, GLboolean _transpose = GL_FALSE) const { glProgramUniformMatrix4x2fv(mObjectName, _location, 1, _transpose, glm::value_ptr(_v)); }
    inline void setProgramUniform (GLint _location, const glm::mat4x3& _v, GLboolean _transpose = GL_FALSE) const { glProgramUniformMatrix4x3fv(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)); }

#if (ACGL_OPENGL_VERSION >= 40)
    // double matrix by location
    inline void setUniform (GLint _location, const glm::dmat2&   _v, GLboolean _transpose = GL_FALSE) const { glUniformMatrix2dv(_location, 1, _transpose, glm::value_ptr(_v)); }
    inline void setUniform (GLint _location, const glm::dmat2x3& _v, GLboolean _transpose = GL_FALSE) const { glUniformMatrix2x3dv(_location, 1, _transpose, glm::value_ptr(_v)); }
    inline void setUniform (GLint _location, const glm::dmat2x4& _v, GLboolean _transpose = GL_FALSE) const { glUniformMatrix2x4dv(_location, 1, _transpose, glm::value_ptr(_v)); }
    inline void setUniform (GLint _location, const glm::dmat3x2& _v, GLboolean _transpose = GL_FALSE) const { glUniformMatrix3x2dv(_location, 1, _transpose, glm::value_ptr(_v)); }
    inline void setUniform (GLint _location, const glm::dmat3&   _v, GLboolean _transpose = GL_FALSE) const { glUniformMatrix3dv  (_location, 1, _transpose, glm::value_ptr(_v)); }
    inline void setUniform (GLint _location, const glm::dmat3x4& _v, GLboolean _transpose = GL_FALSE) const { glUniformMatrix3x4dv(_location, 1, _transpose, glm::value_ptr(_v)); }
    inline void setUniform (GLint _location, const glm::dmat4x2& _v, GLboolean _transpose = GL_FALSE) const { glUniformMatrix4x2dv(_location, 1, _transpose, glm::value_ptr(_v)); }
    inline void setUniform (GLint _location, const glm::dmat4x3& _v, GLboolean _transpose = GL_FALSE) const { glUniformMatrix4x3dv(_location, 1, _transpose, glm::value_ptr(_v)); }
    inline void setUniform (GLint _location, const glm::dmat4&   _v, GLboolean _transpose = GL_FALSE) const { glUniformMatrix4dv  (_location, 1, _transpose, glm::value_ptr(_v)); }

    // double matrix DSA by location
    inline void setProgramUniform (GLint _location, const glm::dmat2&   _v, GLboolean _transpose = GL_FALSE) const { glProgramUniformMatrix2dv  (mObjectName, _location, 1, _transpose, glm::value_ptr(_v)); }
    inline void setProgramUniform (GLint _location, const glm::dmat2x3& _v, GLboolean _transpose = GL_FALSE) const { glProgramUniformMatrix2x3dv(mObjectName, _location, 1, _transpose, glm::value_ptr(_v)); }
    inline void setProgramUniform (GLint _location, const glm::dmat2x4& _v, GLboolean _transpose = GL_FALSE) const { glProgramUniformMatrix2x4dv(mObjectName, _location, 1, _transpose, glm::value_ptr(_v)); }
    inline void setProgramUniform (GLint _location, const glm::dmat3x2& _v, GLboolean _transpose = GL_FALSE) const { glProgramUniformMatrix3x2dv(mObjectName, _location, 1, _transpose, glm::value_ptr(_v)); }
    inline void setProgramUniform (GLint _location, const glm::dmat3&   _v, GLboolean _transpose = GL_FALSE) const { glProgramUniformMatrix3dv  (mObjectName, _location, 1, _transpose, glm::value_ptr(_v)); }
    inline void setProgramUniform (GLint _location, const glm::dmat3x4& _v, GLboolean _transpose = GL_FALSE) const { glProgramUniformMatrix3x4dv(mObjectName, _location, 1, _transpose, glm::value_ptr(_v)); }
    inline void setProgramUniform (GLint _location, const glm::dmat4x2& _v, GLboolean _transpose = GL_FALSE) const { glProgramUniformMatrix4x2dv(mObjectName, _location, 1, _transpose, glm::value_ptr(_v)); }
    inline void setProgramUniform (GLint _location, const glm::dmat4x3& _v, GLboolean _transpose = GL_FALSE) const { glProgramUniformMatrix4x3dv(mObjectName, _location, 1, _transpose, glm::value_ptr(_v)); }
    inline void setProgramUniform (GLint _location, const glm::dmat4&   _v, GLboolean _transpose = GL_FALSE) const { glProgramUniformMatrix4dv  (mObjectName, _location, 1, _transpose, glm::value_ptr(_v)); }
#endif // OpenGL >= 4.0

Robert Menzel's avatar
Robert Menzel committed
283
    //! sets a texture uniform to a given texture unit and also binds the texture to the same unit
284 285 286 287
    inline void setTexture        (GLint _location,                  const ConstSharedTexture& _texture, GLint _unit) const { glUniform1i(_location, _unit);                                        _texture->bind(_unit); }
    inline void setTexture        (const std::string& _nameInShader, const ConstSharedTexture& _texture, GLint _unit) const { setUniform( getUniformLocation(_nameInShader), (GLint) _unit);        _texture->bind(_unit); }
    inline void setProgramTexture (GLint _location,                  const ConstSharedTexture& _texture, GLint _unit) const { glProgramUniform1i(mObjectName, _location, _unit);                    _texture->bind(_unit); }
    inline void setProgramTexture (const std::string& _nameInShader, const ConstSharedTexture& _texture, GLint _unit) const { setProgramUniform( getUniformLocation(_nameInShader), (GLint) _unit); _texture->bind(_unit); }
Robert Menzel's avatar
Robert Menzel committed
288 289 290

    //! set the texture to the texture unit the uniform is set to.
    //! Note: it is not guaranteed that all uniforms for textures are set to unique samplers by default after linking!
291
    void setTexture( const std::string& _nameInShader, const ConstSharedTexture& _texture ) const {
Robert Menzel's avatar
Robert Menzel committed
292 293 294 295 296 297 298
        GLint unit;
        GLint uniformLocation = getUniformLocation(_nameInShader);
        if ( uniformLocation != -1 ) {
            glGetUniformiv( mObjectName, uniformLocation, &unit );
            _texture->bind( unit );
        }
    }
299

300 301 302
    // ======================================================================================================= \/
    // ============================================================================================ HIGH LEVEL \/
    // ======================================================================================================= \/
303
public:
304 305 306 307 308 309
    // normal:
    template <typename T>
    inline void setUniform (const std::string& _nameInShader, T _v) const
    {
        setUniform( getUniformLocation(_nameInShader), _v);
    }
310

311 312 313 314 315 316
    // DSA:
    template <typename T>
    inline void setProgramUniform (const std::string& _nameInShader, T _v) const
    {
        setProgramUniform( getUniformLocation(_nameInShader), _v);
    }
317

318 319 320 321 322 323 324 325 326 327 328 329 330 331
    // normal for arrays:
    template <typename T>
    inline void setUniform (const std::string& _nameInShader, GLsizei _n, T _v) const
    {
        setUniform( getUniformLocation(_nameInShader), _n, _v);
    }

    // DSA for arrays:
    template <typename T>
    inline void setProgramUniform (const std::string& _nameInShader, GLsizei _n, T _v) const
    {
        setProgramUniform( getUniformLocation(_nameInShader), _n, _v);
    }

332 333 334 335 336 337
    // normal for matrices with additional transpose parameter
    template <typename T>
    inline void setUniform (const std::string& _nameInShader, T _v, GLboolean _transpose) const
    {
        setUniform( getUniformLocation(_nameInShader), _v, _transpose);
    }
338

339 340 341 342 343 344
    // DSA for matrices with additional transpose parameter
    template <typename T>
    inline void setProgramUniform (const std::string& _nameInShader, T _v, GLboolean _transpose) const
    {
        setProgramUniform( getUniformLocation(_nameInShader), _v, _transpose);
    }
Robert Menzel's avatar
Robert Menzel committed
345 346 347 348 349

    // =================================================================================================== \/
    // ============================================================================================ FIELDS \/
    // =================================================================================================== \/
protected:
350
    GLuint               mObjectName;
351
    ConstSharedShaderVec mShaders;
Robert Menzel's avatar
Robert Menzel committed
352 353
};

Robert Menzel's avatar
Robert Menzel committed
354
ACGL_SMARTPOINTER_TYPEDEFS(ShaderProgram)
Robert Menzel's avatar
Robert Menzel committed
355 356

} // OpenGL
Robert Menzel's avatar
Robert Menzel committed
357 358
} // ACGL

359
#endif // ACGL_OPENGL_OBJECTS_SHADERPROGRAM_HH