ShaderProgram.hh 27.1 KB
Newer Older
1
2
3
4
5
/***********************************************************************
 * Copyright 2011-2012 Computer Graphics Group RWTH Aachen University. *
 * All rights reserved.                                                *
 * Distributed under the terms of the MIT License (see LICENSE.TXT).   *
 **********************************************************************/
Robert Menzel's avatar
Robert Menzel committed
6

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

Robert Menzel's avatar
Robert Menzel committed
10
/**
Robert Menzel's avatar
Robert Menzel committed
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
43
 * 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
44
45
#include <ACGL/ACGL.hh>

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

#include <vector>

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

class ShaderProgram
{
60
    ACGL_NOT_COPYABLE(ShaderProgram)
61

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

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

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

    // ==================================================================================================== \/
    // ============================================================================================ GETTERS \/
    // ==================================================================================================== \/
public:
89
90
    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:
Robert Menzel's avatar
Robert Menzel committed
96
    //! use, or activate it for rendering, also needed to set uniforms:
97
    inline void use(void) const { glUseProgram(mObjectName); }
Robert Menzel's avatar
Robert Menzel committed
98

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

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

109
110
111
112
113
114
115
116
#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

117
    // ===================================================================================================== \/
Robert Menzel's avatar
Robert Menzel committed
118
    // =========================================================================================== LOCATIONS \/
119
    // ===================================================================================================== \/
120
public:
Robert Menzel's avatar
Robert Menzel committed
121
    //////////// uniform (block) locations:
122
123
124
125
126
127
128
	inline GLint getUniformLocation(const std::string& _nameInShader) const 
	{
		// Cache uniform location
		if ( !mUniformLocationCache.count(_nameInShader) ) 
			mUniformLocationCache[_nameInShader] = glGetUniformLocation(mObjectName, _nameInShader.c_str()); 
		return mUniformLocationCache[_nameInShader];
	}
Robert Menzel's avatar
Robert Menzel committed
129
130
131

#if (ACGL_OPENGL_VERSION >= 31)
    //! if the block name does not exist, GL_INVALID_INDEX will get returned
132
133
134
    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
135
    inline void   setUniformBlockBinding( GLuint            _blockIndex, GLuint _bindingPoint ) const { glUniformBlockBinding( mObjectName, _blockIndex, _bindingPoint ); openGLCommonError(); }
136
137
138
139
    inline void   setUniformBlockBinding( const std::string& _blockName, GLuint _bindingPoint ) const {
        GLuint blockIndex = getUniformBlockIndex(_blockName);
        if (blockIndex != GL_INVALID_INDEX) glUniformBlockBinding( mObjectName, blockIndex, _bindingPoint );
    }
Robert Menzel's avatar
Robert Menzel committed
140

141
142
    GLint getUniformBlockBinding( const std::string& _blockName ) const { return getUniformBlockBinding( getUniformBlockIndex(_blockName)); }
    GLint getUniformBlockBinding( GLuint            _blockIndex ) const {
143
144
145
146
147
        GLint bindingPoint;
        glGetActiveUniformBlockiv( mObjectName, _blockIndex, GL_UNIFORM_BLOCK_BINDING, &bindingPoint );
        return bindingPoint;
    }

Robert Menzel's avatar
Robert Menzel committed
148
    //! returns a mapping from the uniforms in a given block to the offset within the block
149
150
    SharedLocationMappings getUniformOffsetsOfBlock( const std::string &_blockName  ) const { return getUniformOffsetsOfBlock(getUniformBlockIndex(_blockName)); }
    SharedLocationMappings getUniformOffsetsOfBlock( GLuint             _blockIndex ) const;
Robert Menzel's avatar
Robert Menzel committed
151
152

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

#endif // OpenGL >= 3.1
Robert Menzel's avatar
Robert Menzel committed
157
158

    //////////// attribute locations:
Robert Menzel's avatar
Robert Menzel committed
159
160
    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()); }
161

162
    //! Sets the attribute locations of this ShaderProgram according to the mappings specified in _locationMappings
163
    void setAttributeLocations( ConstSharedLocationMappings _locationMappings );
Robert Menzel's avatar
Robert Menzel committed
164
    //! Get all attribute names with there locations:
165
    SharedLocationMappings getAttributeLocations() const;
Robert Menzel's avatar
Robert Menzel committed
166
167
168

    //////////// fragdata locations:
#if (ACGL_OPENGL_VERSION >= 30)
Robert Menzel's avatar
Robert Menzel committed
169
    //! if the location does not exist, -1 will get returned
Robert Menzel's avatar
Robert Menzel committed
170
171
    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()); }
172
173
174

    //! 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
175
176
177
178
    //! Get all fragdata names with there locations:
    SharedLocationMappings getFragmentDataLocations();
#endif // OpenGL >= 3.0

179
180
181
    // ===================================================================================================== \/
    // ============================================================================================ UNIFORMS \/
    // ===================================================================================================== \/
182
public:
183
184
    // int by location
    inline void setUniform (GLint _location, GLint _v)             const { glUniform1i (_location, _v); }
185
    inline void setUniform (GLint _location, GLsizei _n, GLint *_v)const { glUniform1iv(_location, _n, _v); }
186
187
188
189
190
191
192
    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)); }

#if (ACGL_OPENGL_VERSION >= 30)
    // unsigned int by location
    inline void setUniform (GLint _location, GLuint _v)            const { glUniform1ui (_location, _v); }
193
    inline void setUniform (GLint _location, GLsizei _n, GLuint*_v)const { glUniform1uiv(_location, _n, _v); }
194
195
196
197
198
199
200
201
    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)); }

#endif // OpenGL >= 3.0

    // float by location
    inline void setUniform (GLint _location, GLfloat _v)          const { glUniform1f (_location, _v); }
202
    inline void setUniform (GLint _location, GLsizei _n, GLfloat*_v)const{ glUniform1fv(_location, _n, _v); }
Robert Menzel's avatar
Robert Menzel committed
203
204
205
    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)); }
206
#if (ACGL_OPENGL_VERSION >= 40)
207

208
209
    // double by location
    inline void setUniform (GLint _location, GLdouble _v)          const { glUniform1d (_location, _v); }
210
    inline void setUniform (GLint _location, GLsizei _n, GLdouble*_v)const{ glUniform1dv(_location, _n, _v); }
211
212
213
214
215
216
    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)); }
#endif // OpenGL >= 4.0

    // float matrix by location
217
218
#ifndef ACGL_OPENGLES_VERSION_20
    // ES 2 only has square matrices, so omit these:
219
220
221
222
223
224
    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::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)); }
225
226
227
#endif
    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)); }
228
    inline void setUniform (GLint _location, const glm::mat4&   _v, GLboolean _transpose = GL_FALSE) const { glUniformMatrix4fv  (_location, 1, _transpose, glm::value_ptr(_v)); }
Felix Rath's avatar
Felix Rath committed
229
230
231
232
233
234
235
236
237
238
239
240
241
242

    // float matrix array by location
#ifndef ACGL_OPENGLES_VERSION_20
    // ES 2 only has square matrices, so omit these:
    inline void setUniform (GLint _location, const glm::mat2x3* _v, GLsizei _n, GLboolean _transpose = GL_FALSE) const { glUniformMatrix2x3fv(_location, _n, _transpose, glm::value_ptr(*_v)); }
    inline void setUniform (GLint _location, const glm::mat2x4* _v, GLsizei _n, GLboolean _transpose = GL_FALSE) const { glUniformMatrix2x4fv(_location, _n, _transpose, glm::value_ptr(*_v)); }
    inline void setUniform (GLint _location, const glm::mat3x2* _v, GLsizei _n, GLboolean _transpose = GL_FALSE) const { glUniformMatrix3x2fv(_location, _n, _transpose, glm::value_ptr(*_v)); }
    inline void setUniform (GLint _location, const glm::mat3x4* _v, GLsizei _n, GLboolean _transpose = GL_FALSE) const { glUniformMatrix3x4fv(_location, _n, _transpose, glm::value_ptr(*_v)); }
    inline void setUniform (GLint _location, const glm::mat4x2* _v, GLsizei _n, GLboolean _transpose = GL_FALSE) const { glUniformMatrix4x2fv(_location, _n, _transpose, glm::value_ptr(*_v)); }
    inline void setUniform (GLint _location, const glm::mat4x3* _v, GLsizei _n, GLboolean _transpose = GL_FALSE) const { glUniformMatrix4x3fv(_location, _n, _transpose, glm::value_ptr(*_v)); }
#endif
    inline void setUniform (GLint _location, const glm::mat2*   _v, GLsizei _n, GLboolean _transpose = GL_FALSE) const { glUniformMatrix2fv  (_location, _n, _transpose, glm::value_ptr(*_v)); }
    inline void setUniform (GLint _location, const glm::mat3*   _v, GLsizei _n, GLboolean _transpose = GL_FALSE) const { glUniformMatrix3fv  (_location, _n, _transpose, glm::value_ptr(*_v)); }
    inline void setUniform (GLint _location, const glm::mat4*   _v, GLsizei _n, GLboolean _transpose = GL_FALSE) const { glUniformMatrix4fv  (_location, _n, _transpose, glm::value_ptr(*_v)); }
243
    
244
245
246
247
248
249
250
251
252
253
254
255
256
#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)); }
#endif // OpenGL >= 4.0

Robert Menzel's avatar
Robert Menzel committed
257
    //! sets a texture uniform to a given texture unit and also binds the texture to the same unit
258
259
    inline void setTexture        (GLint _location,                  const ConstSharedTextureBase& _texture, GLint _unit) const { glUniform1i(_location, _unit);                                        _texture->bind(_unit); }
    inline void setTexture        (const std::string& _nameInShader, const ConstSharedTextureBase& _texture, GLint _unit) const { setUniform( getUniformLocation(_nameInShader), (GLint) _unit);        _texture->bind(_unit); }
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
    
    #if (ACGL_OPENGL_VERSION >= 41)
    // DSA versions:
    
    // int DSA by location
    inline void setProgramUniform (GLint _location, GLint _v)             const { glProgramUniform1i (mObjectName, _location, _v); }
    inline void setProgramUniform (GLint _location, GLsizei _n, GLint *_v)const { glProgramUniform1iv(mObjectName, _location, _n, _v); }
    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)); }
    
    // unsigned int DSA by location
    inline void setProgramUniform (GLint _location, GLuint _v)            const { glProgramUniform1ui (mObjectName, _location, _v); }
    inline void setProgramUniform (GLint _location, GLsizei _n, GLuint*_v)const { glProgramUniform1uiv(mObjectName, _location, _n, _v); }
    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)); }
    
    // float DSA by location
    inline void setProgramUniform (GLint _location, GLfloat _v)          const { glProgramUniform1f (mObjectName, _location, _v); }
    inline void setProgramUniform (GLint _location, GLsizei _n, GLfloat*_v)const{ glProgramUniform1fv(mObjectName, _location, _n, _v); }
    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)); }
    
    // double DSA by location
    inline void setProgramUniform (GLint _location, GLdouble _v)          const { glProgramUniform1d (mObjectName, _location, _v); }
    inline void setProgramUniform (GLint _location, GLsizei _n, GLdouble*_v)const{glProgramUniform1dv(mObjectName, _location, _n, _v); }
    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)); }
    
    // 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)); }

    
    // 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)); }

315
316
    inline void setProgramTexture (GLint _location,                  const ConstSharedTextureBase& _texture, GLint _unit) const { glProgramUniform1i(mObjectName, _location, _unit);                    _texture->bind(_unit); }
    inline void setProgramTexture (const std::string& _nameInShader, const ConstSharedTextureBase& _texture, GLint _unit) const { setProgramUniform( getUniformLocation(_nameInShader), (GLint) _unit); _texture->bind(_unit); }
317
318

#endif
319

320
321
322
    // ======================================================================================================= \/
    // ============================================================================================ HIGH LEVEL \/
    // ======================================================================================================= \/
323
public:
324
325
326
327
328
329
    // normal:
    template <typename T>
    inline void setUniform (const std::string& _nameInShader, T _v) const
    {
        setUniform( getUniformLocation(_nameInShader), _v);
    }
330

331
332
333
334
335
336
    // DSA:
    template <typename T>
    inline void setProgramUniform (const std::string& _nameInShader, T _v) const
    {
        setProgramUniform( getUniformLocation(_nameInShader), _v);
    }
337

338
339
340
341
342
343
344
345
346
347
348
349
350
351
    // 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);
    }

352
353
354
355
356
357
    // 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);
    }
358

359
360
361
362
363
364
    // 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
365
366
367
368
369

    // =================================================================================================== \/
    // ============================================================================================ FIELDS \/
    // =================================================================================================== \/
protected:
370
    GLuint               mObjectName;
371
    ConstSharedShaderVec mShaders;
372
373
374

	/// Cache for uniform locations
	mutable std::map<std::string, int> mUniformLocationCache;
Robert Menzel's avatar
Robert Menzel committed
375
376
};

Robert Menzel's avatar
Robert Menzel committed
377
ACGL_SMARTPOINTER_TYPEDEFS(ShaderProgram)
Robert Menzel's avatar
Robert Menzel committed
378
379

} // OpenGL
Robert Menzel's avatar
Robert Menzel committed
380
381
} // ACGL

382
#endif // ACGL_OPENGL_OBJECTS_SHADERPROGRAM_HH