LGE (Linux Game Engine for short) is a homebrew game engine that I started to write 5 years ago. Since then, I maxed out post-processing and lighting (and other effects) delivering equal or better quality than today’s game engines. I was also great practice, since there’s always something to do.
In order to get to this level with the engine I needed to “cheat” in a sense that I certainly didn’t have infinite time to do the work of the usual 40-50+ something people working on a commercial game engine.
This is where I had to establish certain rules in order to meet my goals. If you follow these rules, you might get a usable game engine in much shorter time than usual, however:
- it will NOT account for all the problems: I certainly didn’t know about many of them, but you can alleviate (more or less) this problem by reading: http://www.gameenginebook.com/ (I didn’t know about it at that time, therefore I had to rewrite the engine some times… but mistakes are there to be learned from)
- there will not be many tools if at all (that is where IMO a game engine starts to become million lines of code)
- you will certainly not make a GAME with the engine you’re writing in a sensible amount of time. If you want to create a game then look for already existing game engines, like Unity, Cryengine 3, Unreal Engine 4 etc.
The rules (philosophy)
- if something is written already AND it works the way you’d like it to AND it’s easily usable AND it seems to be maintained AND it has good documentation, then don’t try to rewrite that just so that you have your own implementation of that particular feature… Examples: STL functionality, mesh loading library, image loading library, math library etc.
- do rewrite stuff that is highly engine specific (and it doesn’t meet the previous criteria). Examples: engine-wide communication (messaging), component-entity-systems, resource management
- after most of your engine’s features are complete, you can go ahead and profile the engine! At this time if you find out that some of the functionality from the previous rules is slow, then go ahead and roll your own! Examples: memory allocation (you’re good with the default malloc/free, new/delete until you run into issues), string library, custom mesh format etc. However: if you want your engine to be highly multithreaded, you should build your engine with that in mind (but you don’t want to write your own thread pool –> use Intel Threading Building Blocks)
- you DON’T want to write you own: GUI, physics (Bullet) and the like. There are libs that already do this really well. For the GUI for the editor I’m using libberkelium (embedded browser), this way I can build my GUI in a website building application, and I can even test it using a dummy backend.
- visuals without compromises, in real-time: this isn’t really something that you have to do, but with LGE it felt logical, since this is the most rewarding part for me, I never got bored with it. It was interesting though that in 2009-10 I worried about adding HDR and bloom effects, because on a Geforce 8600GT it only ran with 30-something FPS (in something like 768p), but today I have gazillions of post-processing effects and I know that they’d run on any pc that was upgraded recently. So the goal here was the following: don’t care much about performance using non-realistic rendering (ie. not pathtracing) just add any and every effect possible that would make it look realistic, close to today’s best looking commercial engines. I mostly achieved this goal, I’m only missing good directional light shadows and global illumination, but these will be implemented soon too.
- don’t try to research new rendering technology (unless you really have to): you almost certainly won’t have time for this, you are not a 40-50 people team that has at least 3-4 members dedicated to this. Instead try to implement what the big guys do (they did have the time to research and optimize all this), and add your own ideas. There are tons of published technology available online, you just have to look for them.
- support only latest technology: your engine will only be done in say 5 years, therefore it’s pointless to support last gen technology (like DX9), because in 5 years it will become outdated. Use the latest DX and OGL versions, this way you can ensure that your engine will be up-to-date when you finally decide it’s done (it never is, but let’s assume that it does some stuff you wanted it to, and therefore it’s “done”)
- try to make your engine as flexible as possible, look up how the big guys do this: this isn’t really a rule either, but I wanted the engine to be this way. My favourite example of this is how it’s implemented in Unity: you can basically put your game objects together as legos and each script instance will be tied to a game object, therefore “this” will be the game object. This is incredibly intuitive to use, it “just makes sense”. You can also rewrite the post-processing and rendering pipeline in Unity too, which makes the engine really flexible to whatever style a game will try to implement.
- dynamic everything: not a rule either, I just wanted the engine to be a bit different from current gen game engines that have most of the world as static objects that you can’t interact with in any way (just collide with them maybe). This makes the world feel… dead… Plus if some of the objects are dynamic, like a football, the you’d miss the realism of breaking a window with that football. Get it? However this requires everything to work at least like it works in bullet: if an object comes to rest it becomes static, but it can be awaken later by another object. This also means that you need dynamic lighting, shadows, GI, physics, (totally) destructible environments, and the list goes on. This is incredibly hard to do in real-time, this may be the reason current gen game engines still contain static objects.
- cross-platform / cross compiler development: aside from having as many target platforms as possible, it’s also great because different compilers notice different bugs (gcc vs vsc++ vs clang). You should definitely try to develop for Win/Linux and if possible (if you have one) for osx too. If your game engine becomes a success on these platforms, then it will be much simpler to port it to consoles and mobile.
- cmake based build system: this makes sure that your build system is compiler agnostic, and that you are able to handle many platforms easily. Also some of your future team will work on different compilers, so your engine should compile fine under say Eclipse, QtCreator, Visual Studio.
- open source: (if you want to) it is beneficial to everybody if they can learn from your code. However you may not go this way if you plan to go commercial…