Engine Architecture Postmortem

Published October 23, 2006
Advertisement
I've been fairly busy working on my terrain engine which is coming along pretty well. I've done a lot of restructuring of the engine, mostly as it applys to data transfer through the engine. My original architecture was to separate every object from any other object, except it's dependencies (pretty much only inherited objects or global types). Objects just contained their data, knew some basic operations of that data, and knew how to give the data out. The renderer knew how to draw basic things. The engine core was left up to getting the data from the object and then handing it to the renderer to be drawn.

For encapsulation and data management in a large project (like a game engine), this seemed like a good idea. However, this didn't turn out to be the case. Every time I wanted to draw something, per say the terrain, I had to strip together indices for rendering the patches. This required prompting the terrain map object to generate these indices every frame, which got kind of expensive (even though it was mostly just a fetch of patch indices and then a degenerate triangle to stitch them together). This also made it very difficult to implement level of detail, blending, and all those nifty graphical tricks since objects didn't know how to draw themselves. The engine had to get the texture token(s) from the terrain map, vertex array/buffer token(s), bind them, enable blending, retrieve the indices and perform the draw. The engine was constantly busy trafficking data back and forth to various components of the engine, and it got insanely cluttered really fast.

Unfortunately, I couldn't really find a light at the end of the tunnel for this architecture and it was just getting out of hand. So I took a few steps back and reevaluated some things that I was doing. I had somewhat neglected the use of interfaces in my engine, mostly due to my ignorance on their extreme usefulness even for some of the simplest of objects. So, I ran back down the tunnel to the fork of architecture type decision and took a different branch.

I wrapped a lot of my components with interfaces and allowed components to know about the interfaces to other components that they communicate with. This allows me to simply invoke a function and pass the object to communicate with to the component that needs to do the communicating and the interfaces take care of keeping GUI objects from knowing about OpenGL and other things they really don't need to know specifically about. This allows me to keep the code cleaner and I can completely rewrite the engine components using different APIs or rolling my own without having much, if any, of an effect on the rest the engine.

As far as performance goes, I've increased the efficiency of the engine and it's overall feel of interaction to something more befitting of an actual game engine. Frame rates have increased and I have greatly increased my capability of performing graphical effects much easier since objects control their own rendering. I've alleviated the core of the engine from playing messenger and having to decipher and translate and leaving it up the the objects and components to handle that, and leaving the core to simply orchestrate the interaction.

The biggest beneficiary of this switch, is probably my eyes. They aren't screaming at me any more for having to read through the cluttered code anymore ;-).
0 likes 0 comments

Comments

Nobody has left a comment. You can be the first!
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Profile
Author
Advertisement
Advertisement