How many shaders ?

Dear forum,

I’ve already written my own 3D Game Engine in Java but I want to rewrite it for optimization.
I am NOT a beginner and i basically know how OpenGL works :slight_smile:
I’ve got a lot of questions so I try to structure this post as good as possible.

My engine looks like this:

There is an abstract superclass called RenderSystem.

public abstract class RenderSystem<T> {
	public abstract void addElement(T element);
	public abstract void enableSystem();
	public abstract void disableSystem();
	protected abstract void cleanUp();

Every RenderSystem extends “RenderSystem”.
For every different Material there is a render system and therefore a shader.
I’ve created an enum that stores what parts of my material are enabled (bump_map, displacement_map etc.)

It looks like this: (i missed out all the getter and setter stuff)

public enum MaterialType{
	COLOR_MAT (1,false,false,false,false,MasterRenderer.entity_system,null);
	private MaterialType(int index, boolean use_bump_map, boolean use_displacement_map, boolean use_normal_map,
			boolean use_specular_map, RenderSystem<?> default_system, RenderSystem<?> instanced_system) {
		this.index = index;
		this.use_bump_map = use_bump_map;
		this.use_displacement_map = use_displacement_map;
		this.use_normal_map = use_normal_map;
		this.use_specular_map = use_specular_map;
		this.default_system = default_system;
		this.instanced_system = instanced_system;
	private final int index;
	private final boolean use_bump_map;
	private final boolean use_displacement_map;
	private final boolean use_normal_map;
	private final boolean use_specular_map;
	private final RenderSystem<?> default_system;
	private final RenderSystem<?> instanced_system;

In this example, I stored only one Material in it, it does not use any of those maps except the color_map (which is always enabled).
Furthermore it stores the Systems that deals with those kinds of entities that use that material.


This will be done with everything else, I will add a skydome material, particle material etc. This is all straight forward but my question now is, which shaders do i need ?

Shall I write one shader for every entity, (entities are those who are created by using an obj. file, no particles etc. included)
or one shader for normal rendering without bump_maps and all that stuff, and one shader for my material with a normal_map ?
That would mean that i render every entity with that one shader, even if it does not have any of those maps it has to calculate that stuff.

Furthermore i want to add a BoneSystem to my characters. I guess that’s something that should have its own shader ?
Below i will list what shaders i would create:
[li]EntityShader (only colormap)
[/li][li]EntityShader (colormap and normalmap)
[/li][li]EntityShader (colormap and specularmap)
[/li][li]EntityShader (colormap, normalmap and specularmap)
[/li][li]EntityShader (colormap, bumpmap, displacementmap, normalmap, specularmap)
[/li][li]CharacterShader (only colormap with bones)
[/li][li]SkydomeShader (only colormap), renders the sky
[/li][li]ParticleShader (probably only colormap BUT INSTANCED!!)
[/li][li]TerrainShader (probably will get its own material to do stuff like blending)
[/li][li]ShadowShader (takes entities and no other map, renders only the depth to a framebuffer)
[/li][li]WaterShader (if i am really bored and have nothing else to do)
[/li][li]And finally: InstancedEntityShader (only colormap but instanced)

I might add some postProcessing effects but thats not safe yet.
I just want to know if THAT structure is okay and effective or should i change anything ?
Also, how many shaders are normally used in games ?
I am very happy for any kind of critic or advice :slight_smile:

Greetings, Finn


The default starting point should be one shader that can handle everything. Then use specialised versions once you’ve confirmed that the gains from a simplified shader outweigh the cost of having to split draw calls (assuming that you’re not already splitting draw calls unnecessarily because e.g. you’re swapping textures rather than using an array texture, or changing uniforms rather than using a material array, etc).

Also, is there a reason for some surfaces not having normal maps, you have you just not gotten around to creating the normal maps yet? If it’s the latter, then the (temporary) lack of normal maps shouldn’t influence the engine design.

More generally: if OOP is a good fit for your engine, there’s probably something wrong with your engine (e.g. you’ve tried to make it generic, rather than making decisions then requiring the assets to comply with those decisions).