I have several shaders with uniform variables, which have the same names in all shaders. What is the best way to update uniforms with same names in all shaders at once? I consider the following approaches:
1) Just store locations of that uniform for each program and update it just after the program is assigned as "used" program (glUseProgram
).
Disadvantages:
All "shared" uniform variables will be updated after each glUseProgram
call. Moreover, if a program is being used not for the first time during the current frame, all glUniform*
calls will be redundant.
Alternatively there should be a set of flags which will tell if the program is used for the first time or not. "Unused" flags should be reset every frame.
2) Use uniform buffers and shared
(or even std140
) layout. In this approach we can set an uniform at once and then change shader programs without updating buffers. But what if there is a bunch of simple shaders, where the only shared variable is transformation matrix? Is it okay to use uniform buffers for such a small amount of memory? In some forum discussions I've read that
glBindBuffer(GL_UNIFORM_BUFFER,buf);
glBufferSubData(/*just 16 floats*/);
glBindBuffer(GL_UNIFORM_BUFFER,0);
is much slower than glUniform*
call. Here we can notice, that the choice between first and second approach depends on the following conditions:
- How often will the shaders change per frame and how often will they repeat?
- How many "shared" uniforms are there?
- What amount of data should be passed to shader program in each frame?
Is there any compromise design pattern which will have good performance regardless of answers for these three questions?
3) Use ubershader. Mentioned here in the second paragraph: GLSL multiple shaderprogram VS uniforms switches. I have two questions about it:
What has better performance: one glUseProgram
call or several uniform switches, which will change ubershader's functionality?
Author of that question mentioned
Uniforms have to be changed many times per frame
as one of disadvantages of ubershader. But why is it bad? Does it have bad performance? If so, is it okay to pass transformation matrices and some other low-sized stuff as uniform variables and update them each frame?
And the main question to summarize all above: may you suggest any other techniques or design patterns for updating same-named uniform variables in several different shader programs?
UPD: the answer is accepted, nevertheless if you can suggest a nontrivial high-level design technique (in C++ or language-independent), plese leave it here.