<p>Yes it is. I use template to solve the problem. Here is
<a href="https://github.com/EternalSaga/RGL/blob/master/render_core/gl/glUniformWrapper.hpp" rel="nofollow noreferrer">my solution.</a></p>
<p>Since the template code in C++ is overly verbose and quite similar, I'm only pasting snippets as examples.<br />
These template codes primarily utilize variable-length template parameters and constexpr if. When calling these wrappers, the C++ compiler can automatically deduce the template type based on your parameters, without you having to explicitly declare any template type parameters.<br />
Of course, if you're dealing with bulk transfer of uniform data to OpenGL, the UBO (Uniform Buffer Object) solution mentioned in the previous answer is definitely better. My scheme is simply an experimental encapsulation.</p>
<pre><code>    template &lt;typename T, typename... Args&gt;
        constexpr bool all_same_type_v = (std::is_same_v&lt;T, Args&gt; &amp;&amp; ...);
        //wrapper for glUniform number type
        template&lt;typename... Args&gt;
        void glUniform(GLint location, Args... values) {
            constexpr GLuint numOfArgs = sizeof...(values);
            static_assert(numOfArgs &lt; 5, &quot;Size of arguments must less than 5&quot;);
            if constexpr (numOfArgs == 1) {
                if constexpr (all_same_type_v&lt;float, Args...&gt;) {
                    glUniform1f(location, std::forward&lt;Args&gt;(values)...);
                }
                else if constexpr (all_same_type_v&lt;GLint, Args...&gt;)
                {
                    glUniform1i(location, std::forward&lt;Args&gt;(values)...);
                }
    //.....

    //Wrapper for glUniformVec
    template&lt;GLuint UVarLength, typename T&gt;
        void glUniformVec(GLint location, GLsizei uniformVarCount, T* data) {
            assert(uniformVarCount &lt; 5);
            if constexpr (UVarLength == 1) {
                if constexpr (std::is_same_v&lt;T, float&gt;)
                {
                    glUniform1fv(location, uniformVarCount, data);
                }
                else if constexpr (std::is_same_v&lt;T, GLint&gt;)
                {
                    glUniform1iv(location, uniformVarCount, data);
                }
                else if constexpr (std::is_same_v&lt;T, GLuint&gt;) {
                    glUniform1uiv(location, uniformVarCount, data);
                }
            }
            else if constexpr (UVarLength == 2)
    //.....

    //wrapper for uniform matirx, value is a glm matrix type
    template&lt;GLuint Cols, GLuint Rows,glm::qualifier q&gt;
        void glUniformMatrix(GLint location, const glm::mat&lt;Cols, Rows,glm::f32, q&gt;&amp; value) {

                if constexpr (Cols == 2)
                {
                    if constexpr (Rows == 2) {
                        glCall(glUniformMatrix2fv,location, 1, GL_FALSE, glm::value_ptr(value));
                    }
                    else if constexpr (Rows == 3) {
                        glCall(glUniformMatrix2x3fv,location, 1, GL_FALSE, glm::value_ptr(value));
                    }
                    else if constexpr (Rows == 4) {
                        glCall(glUniformMatrix2x4fv,location, 1, GL_FALSE, glm::value_ptr(value));
                    }
                    else
                    {
                        static_assert(false, &quot;Unsupport matrix type&quot;);
                    }
                }
                else if constexpr (Cols == 3) {
                    if constexpr (Rows == 2) {
                        glCall(glUniformMatrix3x2fv,location, 1, GL_FALSE, glm::value_ptr(value));
                    }
    //......
</code></pre>
<p>However, the problem what annoyed me at present is sometimes I mismatch the type  in shaders and glUniform family methods. I'm finding some solution to check this error.</p>

CC BY-SA 4.0
2024-08-20T14:16:07.507Z
Please copy the relevant code to your answer. The link might expire in the future.
wychmaster
CC BY-SA 4.0
2024-09-01T14:18:48.917Z
From what I've learned since writing my question, is that uniform buffers and shader storage buffers are the best way to go. And also many engines do checks if shader uniforms and code uniforms match either at runtime or in built-in editor. It seems that many people find the easy to make type errors annoying :D
LemonJumps
CC BY-SA 4.0
2024-08-07T08:06:25.910Z
2024-08-21T02:54:19.357Z
2024-08-21T02:54:19.357Z
Robin Lew
<p>You should use <a href="https://www.khronos.org/opengl/wiki/Uniform_Buffer_Object" rel="nofollow noreferrer">uniform buffer objects</a> instead of individual <code>glUniform</code> calls. Then the uniforms are all stored in one block of memory which you tell OpenGL about. The shader and the code that fills the buffer with data have to agree on what the memory layout is, but the code that selects the UBO while drawing doesn't need to care.</p>
<p>You will likely also be able to have one UBO per “mesh object” and one per “shader object”, so that each combination can be activated just with two bindings.</p>

CC BY-SA 4.0
2023-07-07T15:06:37.650Z
woah i didn't knew you could do this!!! that saves me so much work!!
LemonJumps
CC BY-SA 4.0
2023-07-06T14:54:25.087Z
2023-07-06T14:54:25.087Z
Kevin Reid
<p>so I'm working on a game engine.
It's partially python and c++.</p>
<p>One part that is currently a pain point is setting the uniforms for shaders.
Currently I have to define a behavior for all 50+ methods used for setting the uniforms <strong>glUniform{1,2,3,4}{uifd}{v}</strong></p>
<p>Is there a single method that I could just call, give it some memory, and tell it, this is a <em>&lt;inset type here&gt;</em> at this location and it repeats this many times?</p>
<h4>My motivation:</h4>
<p>These uniforms usually come from the &quot;mesh object&quot;, (containing single values, bones, textures, etc.) or they come from &quot;shader object&quot; where they're set per shader, (like light position, camera orientation etc.)</p>
<p>So setting all of it programmatically, instead of having to deal with multiple different methods is preferable.</p>

<opengl><shader><glsl>
is there an universal way to set a uniform?
LemonJumps
# is there an universal way to set a uniform?

(Asked by: username_0 on 2023-07-05)

so I'm working on a game engine.
It's partially python and c++.

One part that is currently a pain point is setting the uniforms for shaders.
Currently I have to define a behavior for all 50+ methods used for setting the uniforms **glUniform{1,2,3,4}{uifd}{v}**

Is there a single method that I could just call, give it some memory, and tell it, this is a *<inset type here>* at this location and it repeats this many times?

#### My motivation:

These uniforms usually come from the "mesh object", (containing single values, bones, textures, etc.) or they come from "shader object" where they're set per shader, (like light position, camera orientation etc.)

So setting all of it programmatically, instead of having to deal with multiple different methods is preferable.

**Tags:** opengl, shader, glsl


---

## 2 answers

### Answer by username_3 on 2023-07-06. Score: 4 | Accepted answer

You should use [uniform buffer objects](https://www.khronos.org/opengl/wiki/Uniform_Buffer_Object) instead of individual `glUniform` calls. Then the uniforms are all stored in one block of memory which you tell OpenGL about. The shader and the code that fills the buffer with data have to agree on what the memory layout is, but the code that selects the UBO while drawing doesn't need to care.

You will likely also be able to have one UBO per “mesh object” and one per “shader object”, so that each combination can be activated just with two bindings.

> **Comments:**
> **username_0**: woah i didn't knew you could do this!!! that saves me so much work!!  

---

### Answer by username_1 on 2024-08-07. Score: 2

Yes it is. I use template to solve the problem. Here is
[my solution.](https://github.com/EternalSaga/RGL/blob/master/render_core/gl/glUniformWrapper.hpp)

Since the template code in C++ is overly verbose and quite similar, I'm only pasting snippets as examples.  
These template codes primarily utilize variable-length template parameters and constexpr if. When calling these wrappers, the C++ compiler can automatically deduce the template type based on your parameters, without you having to explicitly declare any template type parameters.  
Of course, if you're dealing with bulk transfer of uniform data to OpenGL, the UBO (Uniform Buffer Object) solution mentioned in the previous answer is definitely better. My scheme is simply an experimental encapsulation.

```
    template <typename T, typename... Args>
        constexpr bool all_same_type_v = (std::is_same_v<T, Args> && ...);
        //wrapper for glUniform number type
        template<typename... Args>
        void glUniform(GLint location, Args... values) {
            constexpr GLuint numOfArgs = sizeof...(values);
            static_assert(numOfArgs < 5, "Size of arguments must less than 5");
            if constexpr (numOfArgs == 1) {
                if constexpr (all_same_type_v<float, Args...>) {
                    glUniform1f(location, std::forward<Args>(values)...);
                }
                else if constexpr (all_same_type_v<GLint, Args...>)
                {
                    glUniform1i(location, std::forward<Args>(values)...);
                }
    //.....

    //Wrapper for glUniformVec
    template<GLuint UVarLength, typename T>
        void glUniformVec(GLint location, GLsizei uniformVarCount, T* data) {
            assert(uniformVarCount < 5);
            if constexpr (UVarLength == 1) {
                if constexpr (std::is_same_v<T, float>)
                {
                    glUniform1fv(location, uniformVarCount, data);
                }
                else if constexpr (std::is_same_v<T, GLint>)
                {
                    glUniform1iv(location, uniformVarCount, data);
                }
                else if constexpr (std::is_same_v<T, GLuint>) {
                    glUniform1uiv(location, uniformVarCount, data);
                }
            }
            else if constexpr (UVarLength == 2)
    //.....

    //wrapper for uniform matirx, value is a glm matrix type
    template<GLuint Cols, GLuint Rows,glm::qualifier q>
        void glUniformMatrix(GLint location, const glm::mat<Cols, Rows,glm::f32, q>& value) {

                if constexpr (Cols == 2)
                {
                    if constexpr (Rows == 2) {
                        glCall(glUniformMatrix2fv,location, 1, GL_FALSE, glm::value_ptr(value));
                    }
                    else if constexpr (Rows == 3) {
                        glCall(glUniformMatrix2x3fv,location, 1, GL_FALSE, glm::value_ptr(value));
                    }
                    else if constexpr (Rows == 4) {
                        glCall(glUniformMatrix2x4fv,location, 1, GL_FALSE, glm::value_ptr(value));
                    }
                    else
                    {
                        static_assert(false, "Unsupport matrix type");
                    }
                }
                else if constexpr (Cols == 3) {
                    if constexpr (Rows == 2) {
                        glCall(glUniformMatrix3x2fv,location, 1, GL_FALSE, glm::value_ptr(value));
                    }
    //......

```

However, the problem what annoyed me at present is sometimes I mismatch the type in shaders and glUniform family methods. I'm finding some solution to check this error.

> **Comments:**
> **username_2**: Please copy the relevant code to your answer. The link might expire in the future.  
> **username_0**: From what I've learned since writing my question, is that uniform buffers and shader storage buffers are the best way to go. And also many engines do checks if shader uniforms and code uniforms match either at runtime or in built-in editor. It seems that many people find the easy to make type errors annoying :D  

---

