It's a good idea to separate parameters into a few categories based on how often they're changed, or which other parts of the renderer they hook up to. For instance:
- Frame parameters - like the camera matrix, screen size, and current time
- Material parameters - like textures, specular and gloss values, etc.
- Object parameters - like an object's world matrix, skinning matrices, etc.
If you're using uniform buffer objects it's convenient to make each category its own UBO as well; that way you can re-use UBOs, e.g. use the same frame parameters UBO across all shaders in the scene.
You can then write a little class to handle each group - for instance, have a
FrameParams class that would handle setting all those parameters for a shader program. It would look up uniform locations at initialization, then later set all the uniforms appropriately, or update the UBO and bind it, each frame. You'd have one instance of this class for each shader program, probably as a member in your
If there are a few fixed sets of parameters used by different materials, you could write similar
MaterialParams classes for each variation. For instance, one class could handle diffuse and specular colors while another could handle textures. If you need more variation than that, you're looking at a dynamic, data-driven parameter set - which is going to be more complicated, but still doable.
Each shader program could have a set of these parameter objects, kind of like a component-based system. When you want to set the parameters for a particular material, you find the appropriate parameters object in the program and call a method on it, passing in the parameter values for that material.