ShaderProgram.hh 27.3 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>
50
#include <ACGL/OpenGL/Objects/TextureBuffer.hh>
Robert Menzel's avatar
Robert Menzel committed
51
#include <ACGL/OpenGL/Data/LocationMappings.hh>
52
#include <ACGL/Math/Math.hh>
Robert Menzel's avatar
Robert Menzel committed
53
54
55
56

#include <vector>

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

class ShaderProgram
{
61
    ACGL_NOT_COPYABLE(ShaderProgram)
62

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

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

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

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

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

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

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

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

118
    // ===================================================================================================== \/
Robert Menzel's avatar
Robert Menzel committed
119
    // =========================================================================================== LOCATIONS \/
120
    // ===================================================================================================== \/
121
public:
Robert Menzel's avatar
Robert Menzel committed
122
    //////////// uniform (block) locations:
123
124
125
126
127
128
129
	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
130
131
132

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

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

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

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

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

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

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

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

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

180
181
182
    // ===================================================================================================== \/
    // ============================================================================================ UNIFORMS \/
    // ===================================================================================================== \/
183
public:
184
185
    // int by location
    inline void setUniform (GLint _location, GLint _v)             const { glUniform1i (_location, _v); }
186
    inline void setUniform (GLint _location, GLsizei _n, GLint *_v)const { glUniform1iv(_location, _n, _v); }
187
188
189
190
191
192
193
    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); }
194
    inline void setUniform (GLint _location, GLsizei _n, GLuint*_v)const { glUniform1uiv(_location, _n, _v); }
195
196
197
198
199
200
201
202
    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); }
203
    inline void setUniform (GLint _location, GLsizei _n, GLfloat*_v)const{ glUniform1fv(_location, _n, _v); }
Robert Menzel's avatar
Robert Menzel committed
204
205
206
    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)); }
207
#if (ACGL_OPENGL_VERSION >= 40)
208

209
210
    // double by location
    inline void setUniform (GLint _location, GLdouble _v)          const { glUniform1d (_location, _v); }
211
    inline void setUniform (GLint _location, GLsizei _n, GLdouble*_v)const{ glUniform1dv(_location, _n, _v); }
212
213
214
215
216
217
    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
218
219
#ifndef ACGL_OPENGLES_VERSION_20
    // ES 2 only has square matrices, so omit these:
220
221
222
223
224
225
    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)); }
226
227
228
#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)); }
229
    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
230
231
232
233
234
235
236
237
238
239
240
241
242
243

    // 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)); }
244
    
245
246
247
248
249
250
251
252
253
254
255
256
257
#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
258
    //! sets a texture uniform to a given texture unit and also binds the texture to the same unit
259
260
261
    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); }
    inline void setTexture (const std::string& _nameInShader, const ConstSharedTextureBuffer& _texture, GLint _unit) const { setUniform( getUniformLocation(_nameInShader), (GLint) _unit);      _texture->bindTexture(_unit); }
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
315
316
    
    #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)); }

317
318
    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); }
319
320

#endif
321

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

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

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

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

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

    // =================================================================================================== \/
    // ============================================================================================ FIELDS \/
    // =================================================================================================== \/
protected:
372
    GLuint               mObjectName;
373
    ConstSharedShaderVec mShaders;
374
375
376

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

Robert Menzel's avatar
Robert Menzel committed
379
ACGL_SMARTPOINTER_TYPEDEFS(ShaderProgram)
Robert Menzel's avatar
Robert Menzel committed
380
381

} // OpenGL
Robert Menzel's avatar
Robert Menzel committed
382
383
} // ACGL

384
#endif // ACGL_OPENGL_OBJECTS_SHADERPROGRAM_HH