When making games you often create the following game object from which all entities inherit:
public class GameObject{
abstract void Update(...);
abstract void Draw(...);
}
So in you update loop you iterate over all the game objects and give them a chance to change state, then in the next draw loop you iterate again over all the game objects and give them a chance to draw themselves.
Although this works fairly well in a simple game with a simple forward renderer it often leads to a few gigantic game objects that need to store their models, multiple textures and worst of all a fat draw method that creates a tight coupling between the game object, the current render strategy and any rendering related classes.
If I were to change the render strategy from forward to deferred I would have to update a lot of game objects. And the game objects I make are not as reusable as they could be. Of course inheritance and/or composition can help me fight code duplication and make it a bit easier to change implementation but it still feels lacking.
A better way, perhaps, would be to remove the Draw method from the GameObject class altogether and create a Renderer class. The GameObject would still need to contain some data about it's visuals, like what model to represent it with and what textures should be painted on the model, but how this is done would be left to the renderer. However there are often a lot of border cases in rendering so although this would remove the tight-coupling from the GameObject to the Renderer, the Renderer would still have to be all knowing about all the game objects which would make it fat, all knowing and tightly-coupled. This would violate quite a few good practices. Maybe Data-Oriented-Design could do the trick. Game objects would certainly be data, but how would the renderer be driven by this? I'm not sure.
So I'm at a loss and can't think of a good solution. I've tried to use the principles of MVC and in the past I had some ideas about how to use that in games, but recently it doesn't seem as applicable as I thought. I would love to know how you all tackle this problem.
Anyway let's recap, I'm interested in how the following design goals can be achieved.
- No rendering logic in the game object
- Loose coupling between game objects and render engine
- No all knowing renderer
- Preferably runtime switching between render engines
The ideal project setup would be a separate 'game logic' and render logic project that don't need to reference each other.
This thought train all started when I heard John Carmack say on twitter that he has a system so flexible he can swap out render engines at run time and can even tell his system to use both renderers (a software renderer and a hardware-accelerated renderer) at the same time so he can inspect differences. The systems I've programmed so far aren't even near that flexible