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

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

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

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

45
#include <ACGL/Base/Macros.hh>
Robert Menzel's avatar
Robert Menzel committed
46
47
48
#include <ACGL/OpenGL/GL.hh>
#include <ACGL/OpenGL/Objects/Shader.hh>
#include <ACGL/OpenGL/Objects/Texture.hh>
49
#include <ACGL/OpenGL/Objects/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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
    //////////// 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
    inline GLuint getUniformBlockIndex (const std::string& _nameInShader) { return glGetUniformBlockIndex(mObjectName, _nameInShader.c_str()); }

    inline void   setUniformBlockBinding( GLuint            _blockIndex, GLuint _bindingPoint ) { glUniformBlockBinding( mObjectName, _blockIndex, _bindingPoint ); }
    inline void   setUniformBlockBinding( const std::string& _blockName, GLuint _bindingPoint ) { glUniformBlockBinding( mObjectName, getUniformBlockIndex(_blockName), _bindingPoint ); }

    //! returns a mapping from the uniforms in a given block to the offset within the block
    SharedLocationMappings getUniformOffsetsOfBlock( const std::string &_blockName  ) { return getUniformOffsetsOfBlock(getUniformBlockIndex(_blockName)); }
    SharedLocationMappings getUniformOffsetsOfBlock( GLuint             _blockIndex );

    //! returns the size in bytes of the uniform block, can be used to allocate the right amount of memory
    GLsizeiptr getUniformBlockSize( const std::string &_blockName  ) { return getUniformBlockSize(getUniformBlockIndex(_blockName)); }
    GLsizeiptr getUniformBlockSize( GLuint             _blockIndex );

#endif // OpenGL >= 3.1
Robert Menzel's avatar
Robert Menzel committed
139
140

    //////////// attribute locations:
Robert Menzel's avatar
Robert Menzel committed
141
142
    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()); }
143
144
145

    //! Sets the attribute locations of this ShaderProgram according to the mappings specified in
    void setAttributeLocations( ConstSharedLocationMappings _locationMappings );
Robert Menzel's avatar
Robert Menzel committed
146
147
148
149
150
    //! Get all attribute names with there locations:
    SharedLocationMappings getAttributeLocations();

    //////////// fragdata locations:
#if (ACGL_OPENGL_VERSION >= 30)
Robert Menzel's avatar
Robert Menzel committed
151
    //! if the location does not exist, -1 will get returned
Robert Menzel's avatar
Robert Menzel committed
152
153
    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()); }
154
155
156

    //! 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
157
158
159
160
    //! Get all fragdata names with there locations:
    SharedLocationMappings getFragmentDataLocations();
#endif // OpenGL >= 3.0

161
162
163
    // ===================================================================================================== \/
    // ============================================================================================ UNIFORMS \/
    // ===================================================================================================== \/
164
public:
165
166
    // int by location
    inline void setUniform (GLint _location, GLint _v)             const { glUniform1i (_location, _v); }
167
    inline void setUniform (GLint _location, GLsizei _n, GLint *_v)const { glUniform1iv(_location, _n, _v); }
168
169
170
171
172
173
    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); }
174
    inline void setProgramUniform (GLint _location, GLsizei _n, GLint *_v)const { glProgramUniform1iv(mObjectName, _location, _n, _v); }
175
176
177
    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)); }
178

179
180
181
#if (ACGL_OPENGL_VERSION >= 30)
    // unsigned int by location
    inline void setUniform (GLint _location, GLuint _v)            const { glUniform1ui (_location, _v); }
182
    inline void setUniform (GLint _location, GLsizei _n, GLuint*_v)const { glUniform1uiv(_location, _n, _v); }
183
184
185
186
187
188
    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); }
189
    inline void setProgramUniform (GLint _location, GLsizei _n, GLuint*_v)const { glProgramUniform1uiv(mObjectName, _location, _n, _v); }
190
191
192
193
194
195
196
    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); }
197
    inline void setUniform (GLint _location, GLsizei _n, GLfloat*_v)const{ glUniform1fv(_location, _n, _v); }
Robert Menzel's avatar
Robert Menzel committed
198
199
200
    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)); }
201

202
203
    // float DSA by location
    inline void setProgramUniform (GLint _location, GLfloat _v)          const { glProgramUniform1f (mObjectName, _location, _v); }
204
    inline void setProgramUniform (GLint _location, GLsizei _n, GLfloat*_v)const{ glProgramUniform1fv(mObjectName, _location, _n, _v); }
205
206
207
    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)); }
208

209
210
211
#if (ACGL_OPENGL_VERSION >= 40)
    // double by location
    inline void setUniform (GLint _location, GLdouble _v)          const { glUniform1d (_location, _v); }
212
    inline void setUniform (GLint _location, GLsizei _n, GLdouble*_v)const{ glUniform1dv(_location, _n, _v); }
213
214
215
216
217
218
    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); }
219
    inline void setProgramUniform (GLint _location, GLsizei _n, GLdouble*_v)const{glProgramUniform1dv(mObjectName, _location, _n, _v); }
220
221
222
223
224
225
226
227
228
229
230
231
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
    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
271
    //! sets a texture uniform to a given texture unit and also binds the texture to the same unit
272
273
274
275
    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
276
277
278
279
280
281
282
283
284
285
286

    //! 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!
    void setTexture( const std::string& _nameInShader, const ConstSharedTexture& _texture ) {
        GLint unit;
        GLint uniformLocation = getUniformLocation(_nameInShader);
        if ( uniformLocation != -1 ) {
            glGetUniformiv( mObjectName, uniformLocation, &unit );
            _texture->bind( unit );
        }
    }
287

288
289
290
    // ======================================================================================================= \/
    // ============================================================================================ HIGH LEVEL \/
    // ======================================================================================================= \/
291
public:
292
293
294
295
296
297
    // normal:
    template <typename T>
    inline void setUniform (const std::string& _nameInShader, T _v) const
    {
        setUniform( getUniformLocation(_nameInShader), _v);
    }
298

299
300
301
302
303
304
    // DSA:
    template <typename T>
    inline void setProgramUniform (const std::string& _nameInShader, T _v) const
    {
        setProgramUniform( getUniformLocation(_nameInShader), _v);
    }
305

306
307
308
309
310
311
312
313
314
315
316
317
318
319
    // 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);
    }

320
321
322
323
324
325
    // 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);
    }
326

327
328
329
330
331
332
    // 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
333
334
335
336
337

    // =================================================================================================== \/
    // ============================================================================================ FIELDS \/
    // =================================================================================================== \/
protected:
338
    GLuint               mObjectName;
339
    ConstSharedShaderVec mShaders;
Robert Menzel's avatar
Robert Menzel committed
340
341
};

Robert Menzel's avatar
Robert Menzel committed
342
ACGL_SMARTPOINTER_TYPEDEFS(ShaderProgram)
Robert Menzel's avatar
Robert Menzel committed
343
344

} // OpenGL
Robert Menzel's avatar
Robert Menzel committed
345
346
} // ACGL

347
#endif // ACGL_OPENGL_OBJECTS_SHADERPROGRAM_HH