11
\$\begingroup\$

My scene has multiple objects in it. (Let's say 3 cubes, 1 cylinder, 8 spheres.) I assume I should create a vertex shader for each. How many programs should I have?

Alternatives:

  • One program per object
  • One program for all cubes and another for all spheres (assuming they use the same shaders)
  • One large program for everything

What is the correct approach?

\$\endgroup\$
1
  • 1
    \$\begingroup\$ "I assume I should create a vertex shader for each." Why are you assuming this? A vertex shader will transform vertices according to your model and view matrices and you almost always want it to be the same for everything. \$\endgroup\$
    – usm
    Commented Sep 2, 2014 at 21:42

2 Answers 2

8
\$\begingroup\$

You should consider shader programs as similar part of the state as textures. Changing the state is expensive, so you may be able to get away with combining several textures to one to avoid texture changes; the same applies to shaders - you may be able to combine several shaders to avoid state changes.

Similarly to combining textures, combining shaders comes with an overhead - if you only render 16x16 pixel area out of a 4096x4096 texture, you're not using the hardware efficiently. Similarly, if the object you render only uses 10% of the code in your shader, it's possible (and even likely) that the graphics card is computing a lot of stuff unnecessarily.

In short, "depends".

\$\endgroup\$
2
  • 4
    \$\begingroup\$ In addition, in many cases you can get away with only one shader. The differences are only in the uniforms you pass to the shader, like, color, texture, normal maps, etc. \$\endgroup\$
    – rioki
    Commented Sep 2, 2014 at 12:29
  • \$\begingroup\$ Yup, for example you might have a "Scaly" shader that produces fragments that look scaly, and which works in such a way (most shaders do...) that you can render all 3 cubes, 1 cylinder, and 8 spheres using that one shader (with corresponding geometry primitives, of course). A reasonable set of uniforms here might be a vector value defining the color, and maybe a few scalars or something that affect how "scaly" or "shiny" the visual effect will be. Then you have one shader and you change how the shader colors fragments by changing the uniforms between the draws of the individual geometries. \$\endgroup\$
    – Steven Lu
    Commented Sep 2, 2014 at 14:26
6
\$\begingroup\$

It's best to keep things as simple as possible. Duplicating the same shader for every object is unnecessary and will quickly get bloated. You also don't want one giant shader that covers every possible use-case, as this causes unnecessary overhead.

There are several opinions on shader management and no "optimal" way to approach this. I've even seen some shader implementations where every shader is generated on-the-fly based off parameters (e.g. in Unreal engine).

For someone just starting out in this area, it might be good to pencil out the basic shaders first. For example, I have a shader for textureless objects, a shader with basic texture and per-pixel-lighting support, etc... Then each time I want a different effect that can't be done using a previous shader, then I'll create a new one for the new effect.

The purpose of such a system is to keep things simple. Just. Keep. It. Simple.

\$\endgroup\$
1
  • \$\begingroup\$ +1 because you mentioned what the current industry is doing. \$\endgroup\$
    – Krythic
    Commented Jun 19, 2017 at 6:59

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .