How to look on shaders - as materials or renderers?

Started by
3 comments, last by wolf 16 years, 8 months ago
I usualy write one single shader and use it for everything in my game, maybe some exceptions for the skybox and other special things like 2d-gui but otherwhise i only got one shader. Now i've read alot of tutorials where i see alot of people who use one shader per material, this is also how most 3d-modeling programs work, they export shaderinformation for every material in the model. Is there any advantage in performance in eighter of the options or is it just a matter of personal preference? What method do you use/prefer? Advatages/Disadvatages? :) [Edited by - toomeg on August 5, 2007 3:23:54 PM]
Advertisement
It's the same difference between writing all you C++ code in one file versus splitting it up into multiple files. After a while it will become an organizational nightmare with all those hundreds of techniques. Plus every time you touch one effect you touch ALL the effects, and one compile error will bring down your entire shader system!

I can't think of any performance differences off the top of my head, but I'm not sure if the shader compiler can handle an effect file several megabytes large. It can be rather finicky.
There are a lot of different ways to structure shaders. One way is to have one or a small set of shaders/effects which have a whole bunch of different capabilities. You turn these capabilities on and off by using #ifdef blocks and setting the appropriate defines when creating the effects. Another option is static branching, where the behavior of the shader is controlled by uniform/shader constant flags that are set before rendering. (This causes the shader to be recompiled a couple times, until the various versions are cached.) You can also use a separate shader for every effect. Then there's fragment linking, which works a lot like C -- you have a bunch of files with different functions, and you link them together to produce a final effect. You can alter the behavior of a shader in fragment linked systems by linking different implementations of the same function in.

The shader-per-effect model is popular with small programs but falls apart quickly as things get bigger. The problem with using an individual shader for each effect is that it leads to a lot of duplicated code. Fragment linking is unpopular because it doesn't mix with D3DX's effects. Some systems will do fragment linking anyway, but at build time instead, so that the final game has a separate shader for every material with lots of duplicated code, but the programmers can work with a more maintainable system. Alternately, you can simulate fragment linking using #include directives and modifying the include handler to use different files (D3DX trick). Static branching, as well as the #ifdef approach, are fairly effective. I find that some combination of static branching and multiple shaders works out best for me.

This page discusses some of the things I mentioned, although you have to scroll down a bit to get past the basics.
SlimDX | Ventspace Blog | Twitter | Diverse teams make better games. I am currently hiring capable C++ engine developers in Baltimore, MD.
For myself I have several fx files, each with a number of shaders and techniques, grouped by material type.. I have all my vegetation shaders in one file, my per-pixel lghting shaders in another, a general system shader like bloom and blur shaders etc..

Bascially a mdern engine uses many shaders so its essentially like other source code, you organize it to be convenient for yourself. However, changing the active effect is a state change so you dont want to change it too much per-frame.
Drawback of using many shaders: shader switching overhead. Good number of shaders is 15 - 20 fx files. This number also keeps you shader switching down because of texture, constant changes.

This topic is closed to new replies.

Advertisement