Pass optional emission map to material

Hey, I’m currently using a material struct in my fragment shader:

   struct Material
     {
     	sampler2D diffuse;
     	sampler2D specular;
     	sampler2D emission;
     	float shininess;
     };

And I do not wish to pass in the material uniform emission map all the time as the material might not be emissive, how would I code it in this way that the material emission is optional and not always calculated in the final fragment color?

By using a black texture (which doesn’t need to be any larger than 1x1) for the emission map. This is likely to be more efficient than changing the shader program simply to disable emission.

Few question:
Is that still better than changing the shader (we still do IO and bind stuff to accomplish this)
Is that the standard way game engine deal with materials with no emission?
How would I also tackle materials where they’re just colors programming wise? Would I define different struct Material on the shader side and a class that can handlle either texture or vector colors?

If only a small proportion of meshes have emission, then you’d probably have separate shaders with and without the emission component. The slight performance increase from using a simplified shader for the majority of rendering would likely outweigh the cost of switching shaders.

If you use the black texture approach, you’d probably have one texture unit which holds the black texture (or a texture containing a fixed set of colours) at all times, so you only need to change the sampler uniform, not rebind the texture.

Use a 1x1 texture as the map. Or a texture where each texel is a different colour, with the texture coordinates for all vertices set to the centre of the appropriate texel.

Caching means that texture fetches are cheap if you’re reading the same texel every time.

Beyond that, the next step for performance is to coalesce meshes so that you can draw multiple meshes with a single draw call. Which means not changing uniforms or rebinding textures for different meshes. Instead of changing uniforms, you have a uniform array with a single integer attribute holding the index into the array. Instead of rebinding textures, you put similar textures in distinct layers of an array texture and use the third texture coordinate to select the layer (in this case, “similar” means having the same dimensions and format and using the same sampling parameters).