I'm writing code in C++ to deal with the usual 3D stuff - models, materials, lights, etc. However, I'm finding that for anything to work, it needs to know about the shader. EG, to set uniform variables for a material, you need to know their handles from the shader; to load a mesh into memory, you need to know handles to different in
locations.
I've ended up having models, materials, etc. each have a handle to the shader so they can do things like glUniform1f(shader->getKdLocation(),kd)
, but this kind of hot potato seems like bad design to me. I've seen tutorials where uniforms and ins and outs are hardcoded in the shader (eg layout = 0) and then just bound with glUniform1f(0,kd)
,. However, this means the rest of my code will only function with my specially laid out shaders and therefore seems like a suboptimal solution. Also, I don't think you can do this for subroutines, which makes this an inconsistent option.
It seems like a choice between everything getting a shader reference and in some cases being unable to even properly instantiate without one (eg meshes) OR hardcoding numbers in more places and having to deal with the problems that follow with hardcoding.
I should be able to have these models, lights, etc. live/operate independently and only "work" when I set a shader for the scene, but I can't seem to find a solid way to do this. My bottom line question is what is the best practice for handling shaders? I'm okay if it doesn't solve all my problems, I just want to know what a good design decision(s) is and why.
A Shader is a user-defined program designed to run on some stage of a graphics processor. Shaders provide the code for certain programmable stages of the rendering pipeline. They can also be used in a slightly more limited form for general, on-GPU computation.
Multiple shader objects of the same type may not be attached to a single program object. However, a single shader object may be attached to more than one program object. However, even in OpenGL, using multiple shaders of the same type does not work they way you outline it in your question.
After creating a program, the shader objects you wish to link to it must be attached to the program. This is done via this function: void glAttachShader(GLuint program, GLuint shader); This can be called multiple times with different shader objects.
To recap, shaders are programs that manipulate rendering output and are run on the GPU. Alternatives to shaders would be other methods of modifying rendering (output). The closests alternatives are the fixed-function pipeline and rendering manipulating software.
The problem is your engine architecture,or it's lack.In many game engines game objects are divided into several categories like Mesh object which takes care of geometry (vertex buffers etc),Material objects(responsible for the appearance of the mesh object).In such a design the material is usually an entity which contains info for the uniforms that being passed into shaders during rendering.Such a design allows a good amount of flexibility as you can reuse,reassign different materials between different renderable objects.So for the starter you can set specific shader program to specific material type so each time a mesh is drawn, its materials interacts with the shader program passing in all needed uniforms.
I would suggest you to take a look at open source OpenGL engine to get an idea how it works.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With