This is my first article here, in which I will try to explain how we render things and what changes we need to make to it.
Rendering KaM Remake frame is not a trivial task of deciding the right render order both to make the picture look right and to make the code controlling it to be elegant.
In preparations for upcoming release we usually issue a number of release candidate versions for our playtesters. During these tests we receive a lot of bugreports and crashreports, as well feature requests. Working through all these issues makes us inspect a lot of code in different areas of the game. Some areas we have just added and it is natural to encounter bugs there, but some areas are much older, the new features we have added have triggered the flaws in there, sometimes that reveals poor design choices. One of such areas is our rendering system. It worked well for past years and we mostly appended new stuff to it without much design refactoring. But over time it came more and more tangled ball of yarn, spreading its threads around many other sub-systems. The code kept on sticking together without much of a plan.
The new plan is to dissect the rendering and reorganize it in several big layers, each of which is doing one certain thing is a controlled environment, while maintaining the proper order of rendered entities.
Why is the order is so important? Because we need to render a whole lot of the things properly going beyond and above each other, to keep the players perspective realistic on one side yet clear to use with editing tools, and most important to us – to keep our code neat and easy to work with.
How does it works? Diagram follows. We start with a blank screen. Switching render to tile coordinates. First comes the background, which is terrain tiles, tile overlays (like roads and unfinished digging sites), then lighting is applied. At that step there’s no water yet, instead we render and lit sand tiles. Then comes the animated water overlay. Resulting effect is that the water looks flat, but the waterbed is lit and visible as a nice sandhills. Following comes shadows combined with player fog of war, adjoining them was a good idea, but now we will probably have to split that for easier upgrading to player perspective changes (another change we plan, to let player control several towns and several players to control one town). Dynamic fog of war also needs that change, but that is a whole different topic we plan to show later. Then there’s also fences and plans, which need to go after the fog for proper lighting across their small, yet existing height.
When we are done with background things related to plain terrain we switch on to a different domain – cursors. We need to render cursor highlight on terrain, those that are occluded by the objects rendered next. Such cursors are mainly needed for MapEd (radius highlights, selection highlights).
Next domain are the objects (trees, units, houses), these are collected throughout the engine and rendered in a far-to-near order to overlay each other properly. Object shading with fog is computed by sampling the point shading at the objects feet, but we will need to change that when we add dynamic fog.
After that comes cursor highlights that are rendered above everything, cos we don’t want tall houses to occlude roadplans and etc.
Finally we can switch to UI coordinates mode and paint all the controls that form the GUI with pixel precision, which again consists of few parts, one for terrain overlays (e.g. deposits in MapEd) and one for interface controls.
Thats it, main rendering path goes top to bottom diagonally, with sub-items positioned below. Each domain has its own color:
Reorganizing render flow is a medium size task which mostly involves moving code pieces around and checking for dependencies, yet there’s plenty of possibilities to introduce new bugs. We cannot add such big changes during release candidate testing, because each new change might trigger a bug, that we are so pedantically fixing to make a stable release. So all of these plans are for the future “after release” 🙂