From what I read you should avoid changing shaders if you can.
As a rule of thumb you should avoid unnecessarily changing render states or bound resources, yes... But you should also avoid unnecessary 'if' statements within shaders!
You're making every pixel much more expensive in order to save a little bit of CPU time.
I see; is there a happy medium inbetween where I can use one shader to do simple stuff like draw SkyBoxes/wireframes?
I understand what folks are saying here; but having multiple shaders just to do simple tasks like drawing skyboxes/wireframes/other simple stuff seems like a waste, no?
Having complex shader to do simple things like skyboxes/wireframes is waste. It's also make your code mess if you bundle totally separate functionality to same shader code.
Just be aware that the cost of wasteful shaders is multiplied by the number of pixels draw, which tend to be very large numbers.
e.g. Let's say your skydome covers every pixel on a 1080p render target, that there's an unnecessary if statement in there, that this if statement adds a dozen clock cycles to the shader, that your GPU shades 1000 pixels simultaneously, and it runs at 800MHz.
12cycles * 1920*1080 pixels / 800MHz / 1000 cores = 0.03ms cost (0.2% of a 60Hz frametime budget).
But on an older GPU that shades 24 pixels at 700MHz -
12cycles * 1920*1080 pixels / 700MHz / 24 cores = 1.48ms cost (8.9% of a 60Hz frametime budget).
If you keep adding those kinds of tiny inefficiencies to your shaders, it can add up to a decent percentage of your total frame time. You can always optimize later though...
wireframe/lightning will fire some much of a different pixel function input interpolated variables also, and you cannot ubershader those. Also remember that you may omit routine, but shader will consume the same amount of GPU cache/stacky memory/ local variables/ and so on. You should sort rendering by programs and just switch narrow designed several shaders.