Combining Shaders

I'm currently working on implementing vertex and pixel shaders for a project and so far this is going alright. I'm using multiple passes to obtain the desired effects. The concern I have is related to what I call global geometry passes. A global geometry pass is basically a pass that requires all meshes in the scene to be rendered for the desired effect. A typical example is light (ambient, diffuse, specular). The concern isn't that this doesn't give the desired result, the concern is that this will eventually end up in a lot of global geometry passes.

So getting to the point. Is there a way to combine shaders to lower the number of global geometry passes I know you can not take the output of one shader and use it for the next one since you often have transformations and so on, but I was more thinking of a way to merge the code in each shader given they all adhere to a specified set or structural rules.

I have for some time tried to search these forums, so I have to apologize if my searching skills are lacking and this has already been answered. I would greatly appreciate it if someone could give me some pointers or even supply a link where best practices are explained.



Answer this question

Combining Shaders

  • MichaelWard

    This is a fairly common issue and to the best of my knowledge there is no single generally accepted "optimal" solution.

    Firstly, have you looked at culling systems for your "global geometry passes " Some effects genuinely do require all the geometry to be processed, but the majority do not - lighting, for example, acts within a specified volume. If you're rendering a spotlight then you only need to render those objects that intersect the cone of light that the spotlight is projecting.

    Secondly, have you got numbers for the cost of your geometry processing so far If the pixel shaders you're using far outweigh the cost of setting up triangles and transforming vertices then combining passes will not be a significant win.

    Thirdly... to really answer your original question... there are some ways of 'combining' shaders.

    If interpretted literally, you could look into fragment linking - it does just stitch shaders together, connecting up registers and so on. However it's quite hard to manage this.

    More commonly used is the "multiple shaders" approach whereby you generate a shader for every different combination of subshaders that you might want to use, and then pick the one you want from that set. You can achieve this generation of shaders through use of #define blocks or through static branching and uniform boolean parameters (the latter probably being a bit nicer).


  • Combining Shaders