Working on render quality – Part 1 (SSAO)


Ever since the beginning of Knights Province project I wanted it to be visually pleasing. Slightly cartoonish style with bright colors, semi-realistic soft lighting and shading. Ambient Occlusion (AO) is one of those shading effects that add depth and sense of scale to whole scene, tying objects together and highlighting details.

SSAO composition

What is AO

So what is AO exactly and how does it relate to real world? AO is an effect of ambient light spreading between objects (hence the effects name) and also of some dirt accumulation naturally occuring in crevices. Counter to popular belief, AO is not 100% real-world based. Take a look at walls-ceiling corner – it has no dark gradient on it (even worse, some corners seem to gain brightness near the edge due to light reflecting from other side). Still, AO is a nice artistic effect that adds depth to the picture and gives objects more “weight”, making details to stand out more.

How AO is done

AO can be done in several different ways depending on the use-case. It could be raytraced and recalculated every frame (typical for offline rendering, what 3DSMax and Blender and other rendering apps usually do) when quality is the king. It offers superior quality at a cost of speed (typical scene can take 30+ seconds or minutes to calculate). Games can not afford this. For games, AO could be raytraced once and baked into lighting textures (so-called lightmaps). This offers greater speed. Downsides are – only static objects could be baked. Dynamic objects won’t have proper AO on them and on objects they interact with. Oftentimes older games combined lightmaps with fake shadow patches below actors feet/wheels/etc. That looked okay in 2000’s when computational resources were limited. Now, as the computational powers of GPUs have sufficiently increased, dynamic solutions for games could be made – SSAO, HBAO, HBAO+ and other variants. They don’t come that close to offline rendering solutions, but still offer good enough compromise between performance and looks, with some shortcuts taken.


Here’s a short list of options I’ve considered viable for the Knights Province:

  • Pre-baked lightmaps – look best on static objects, but don’t cope well with dynamic ones, needing lots of special-case “hacks” convoluting the render pipeline. They also require either separate UV map or unique UV mapping (which does not mix well with houses reusing textures and materials, cloned trees and terrain)
  • Dynamically baked lightmaps or vector maps – offer more general approach to the problem, but still require a lot of hassle and have noticeable flaws.
  • SSAO and its variants – is even more general solution. It works on top of any geometry and does not care about how it was combined. What you see is what gets AOed – It’s that simple.

Why did I pick SSAO

I’ve picked SSAO for its generality and simple SSAO implementation specifically for its widespread popularity, which must mean that it’s a good enough compromise between ease of implementation, performance and picture quality. There are many tutorials, common problems and solutions to them are well known too. Optimization techniques are plentiful as well.

How SSAO works in general

SSAO works by basically checking each pixels surroundings within a small sphere, to see if they block ambient light from reaching the surface. The more of those surrounding are covered by other objects, the more occluded the pixel is and the darker it will be. Ideally, each surfaces pixel checks whole multitude of directions and ranges to see how occluded it is from ambient space. In practice, this is very costly operation, so only handful of tests are made and their coarse results get averaged out.


Illustration below shows 2D version of SSAO where 3 surface points are checked with hemispheres oriented towards surface normal (reasonable optimization):

SSAO needs DR

In older times, when render was simpler, GPUs were rendering frames in one go and would calculate each pixels color by factoring everything at once. Now SSAO samples a lot of pixels over and over (even for coarse results, every pixel needs to test 16+ surrounding pixels to figure out its shading). Because of that, it makes sense to prerender required information and access it from some buffer. Providing for that is a complex rework of the rendering pipeline. Approach with rendering intermediate buffers is called Deferred Render (DR). Where’s before the game drew objects one by one in one go, now all objects need to be drawn into temporary buffers (typically that’s position, normal to surface, color) to later combine them into final picture. DR is already sort of in the game – shadowmaps, water reflections and fog of war are prepared in separate buffers and combined into final rendering.

DR plan

Render pipeline needed some planning in order to find correct place and sequence for each operation. Here’s how render pipeline is planned to be with DR and SSAO:

Current render structure of the game

SSAO optimizations

SSAO is very resource hungry algorithm – it needs to test dozens of pixels for every drawn pixel. Optimizations are vital. Most straightforward ones are – sampling only those points that are above tested surfaces (testing within hemi-sphere instead of whole sphere of directions). Then comes in randomizing of samples – it is done by rotating sampling hemisphere for each next pixel – thus output is more evenly distributed, but noisy. Blurring helps with reducing noise. SSAO has a number of controls, allowing to trade-off quality vs. performance – e.g. reducing number of test-samples used, reducing blur radius. At the moment I plan to add 3 SSAO setting – off, low and high quality.

DR and AA

Unfortunately DR does not mix well with traditional AA techniques, since DR relies on pixel perfect information in buffers, only straightforward AA could work (that is rendering frame X times larger and downscaling it), which is unfortunate for SSAO where each new pixel needs whole lot of sampling from neighbour area. Luckily there are known AA algorithms well suited for DR. FXAA is quite popular and easy to implement.

DR and transparency

DR has certain difficulty coping with semi-transparent surfaces (STS), since depth buffer can only contain a single value per pixel, it is either of surface behind the STS or the STS. Which means that either the surface behind or the STS one gets shaded wrongly. There are smart techniques to deal with that (e.g. using a checkerboard pattern and storing every 2nd pixel from other surface), but for the RTS that has quite few STSs (namely smoke particles and water surface) it is easier to deal with the issue by simply rendering STS on top of DR/AO geometry. STS generally don’t need AA too, since their transparency means they don’t create a lot of sharp pixels in the first place. Even better – STSs rendered on top of normal geometry cover some of it, thus reducing amount of sharp edges that AA will need to smooth out.

Recombining the render

Once AO is computed and applied, the render needs to return back to “normal” functioning to render STSs. This is done by writing RGB and depth values back into a buffer and rendering STSs using default depth test.

(Particle textures are replaced with checkerboards for debug)

In the following articles (which are already in works) I’ll cover FXAA and general render perspectives.

P.S. Thanks to Thimo for reviewing this article 🙂

Posted in How things work, Live progress | 1 Comment

Knights Province on Patreon

I’ve finally set up Patreon page for Knights Province!

Patreon is a site that allows to collect monthly donations to support and sponsor projects and people. I’ve been asked a lot about setting up donations for the Knights Province. Finally I did it. Last month I did a small test and money are really getting processed and send to my PayPal account. This means I am ready to announce it.

Since there’s no way of estimating how good this Patreon thing will work, my current Patreon plan is to just start collecting donations and seeing how it goes. I’m planning to add donations to funds I pay from my pocket for freelancers work on assets creation for the Knights Province (2D/3D artists, musicians, animators, etc). It would also be nice to buy a glass of beer every now and then, knowing it was gifted to me by Knights Province fans and players 😉

Patreon page link

Irregardless of donations or not, I’m still very grateful for your support and interest in my humble hobby project. Thank you!

Posted in News | Leave a comment

Where does smoke go?

One of the features I’m working on for Alpha 10 is particle effects. Those include smoke, dust, fire, mist and others.

Here are some early particle tests from dev tools:

First particles

Smoke affected by wind

Rigging smoke to tavern

Faced difficulties included writing a shader for billboard particles (so they always face the camera) and keeping spawn rate stable. Rigging particles to the game was also a bit complicated.

So now game will include small dust puffs on roadplans and house plans placement as well as lite smoke from tavern when anyone is eating in it.

Next – some damaged houses fires!

Posted in Live progress, Tools | 6 Comments

Working on Caster unit navigation

Been working on unit navigation for Alpha 10. It is still very hard and complicated, but progress makes me happy. Made some terrain collision outlines generation code tonight:

Posted in How things work, Screenshots | Leave a comment

Alpha 9.1

Alpha 9.1 (r5956)
Thanks to everyone sending in crashreports – includes following bugfixes:

+ Fixed non-warrior under attack from a house would cause a crash
+ Fixed removal of decals in MapEd
+ Fixed crash on towers hitting non-warrior units
+ Attempt to fix crash on Wine trying to init OpenGL 3.2 function
+ Allowed to change depth buffer bitdepth and shadowmaps bitdepth
+ Added attempt to recover if unsupported GFX settings were chosen
+ Selecting an animal in Replay would cause a crash
+ Fixed crash on setting group attack orders outside of map bounds in MapEd
+ Fixed group attack position offset in MapEd
+ Fixed render of rubble on house demolish
+ Fixed crash on loading savegame where unit training was cancelled

Download links:

Knights Province Alpha 9.1 (7z package)
Knights Province Alpha 9.1 (installer)

Posted in Downloads | 4 Comments

Alpha 9 is ready!

I’m happy to announce new Alpha of the game!

Alpha 9 changes and improvements:

Three major gameplay mechanics (described in detail in earlier article):

  • Wildlife (aggressive animals and dens)
  • Early army (militia can be trained in Camp)
  • Morale to affect warrior’s attack


  • More great music by Juan I. Goncebat
  • New fight and death sounds
  • New scripted map Walkers (survive Walkers waves)
  • New scripted map Into the Swamps (by Klassix)
  • New skirmish map Horseshoe (with aggressive wolves)
  • New skirmish map Borders (by Klassix)
  • New campaign Orthalm (3 missions, by DarkianMaker)
  • New terrains (yellow grass on dirt, coarse gravel)
  • Diagonal transition for mountains/flat terrain
  • New temp house models (by Icomatix)
  • House building animation for 2 houses (with help from Dah)
  • New palm trees


  • Simplified gold production (no coal required)
  • Increased unit walking speed by 25%
  • Reworked AI setup and presets for skirmish
  • Changed defence position setup in MapEd
  • Tweaked AI to handle food production better
  • Tweaked AI to handle offense better
  • Tweaked AI to handle defense better
  • Increased max stone volume up to 6 in one tile
  • Gold and Iron ore can be placed on any mountain type now
  • Fixed AI iron mining
  • Improved iron mining rate
  • Lots of smaller improvements in MapEd
  • Lots of gameplay bugfixes and smaller improvements

As usual – this is still Alpha, there are likely a lot of bugs, flaws, incomplete features, broken mechanics and such. Please report them and also your thoughts on what should change and why.

Download links (updated to latest version):

Knights Province Alpha 9.1 (7z package)
Knights Province Alpha 9.1 (installer)

Posted in Downloads, News | 18 Comments


Did some low-poly palms for the upcoming Alpha 9:

Posted in Screenshots, Sidenotes | 1 Comment

Alpha 9 wip versions

I’m still working on wrapping up features/bugfixes for Alpha 9. Last big feature that needs to be done before Alpha 9 release – AI troop management between defence/offence positions. It’s proven to be one of the greater AI flaw so far.

Until then, wip builds are available in Discord community: #new_versions channel.

Posted in Sidenotes | 2 Comments

Happy New Year 2018 everyone! :-)

Posted in Uncategorized | 6 Comments

Alpha 9 features

Alpha 9 will have the following major features:

  • Aggressive animals
  • Early army
  • Warriors morale

Let’s see how they work!

Aggressive animals

Wolves, bears and boars will now attack all nearby units within some range. Wolves and Bears also got special spawning house – Den. It will spawn new animals until destroyed. Animals spawned from den will wander within certain radius (attacking anyone passing by) and “guard” in smaller radius (running to attack anyone approaching).

Animals and dens can be placed and configured via built-in Map Editor.

So now, animals are a real threat for citizens working in the field and for advancing armies. This can be seen in Horseshoe  – 1vs1 map, designed around wolves obstacle in between 2 players.

Early army

Soldiers can be trained from the first second now. Militia training was moved to Camp. Cost of training is 1 Blank (who will leave his Cottage upon completion) and 1 Club. Clubs can be made later in the game in Weapons Workshop at a cost of 1 Wood. Typical Camp will have a dozen of clubs at the start, allowing player to hire Militia for exploring and self-defense, but not enough for full-scale offense operation (more on that in Morale section).

Along with Militia, now Camps can train Serfs and Builders (they cost only 1 Blank).

Warriors morale

Warriors attack strength now depends on their class and proximity to their (or any allied) town. Militia has lowest morale strength – only 15%. This means that it will fight at full strength within it’s town borders and only at 15% strength when far from the town (e.g. in enemy town). Better warriors have stronger morale (which goes all the way up to 100%). This means, that for example 2 enemy militia can be easily beaten by just one defending unit.

I want the system to be stateless – that is given static setup (units/houses placement) morale should always be the same, irregardless of previous/next system state. In other words, if you see a screenshot you can calculate everyone’s morale without knowing what happened before.

The factors at play are:

  • proximity to own houses is the best and strongest factor
  • proximity to enemy houses lowers morale
  • allied houses are also counted (after all we want to encourage allied help)
  • campfires should boost morale as well (so they play a bigger role as outposts)

Here are some results of 100 test runs. First number is defenders count in their own town, second is approaching enemies. Tests were made with 2 and with 10 defenders to find out equivalent number of attackers:

  • Militia: 2/4 10/41
  • Axeman: 2/3 10/18
  • Swordsman: 2/2 10/11

All these features are aimed at making early game more engaging.

Posted in News | 5 Comments