Progressive Enhancement

Here’s an idea borrowed from the world of the internet. On websites, “progressive enhancement” is a way to design websites to work with a variety of browsers. The idea is to build your website first to work in a browser that doesn’t support css or javascript or ajax. You then enhance the basic website with each of these things, so all your users get the most from your site.

Developing mods, models and maps for quake is a similar experience, because your users have a wide array of engines to choose from, and each one has a different combination of features. Today I’m just going to focus on models and how to design them progressively, but maps and mods can be thought about in the same way (fog and skyboxes in maps are two good examples of features that progressively enhance maps).

So what engine features do we care about when making models? Some of the big ones are:

  • Fullbrights
  • Animation interpolation
  • Alpha blending
  • Full colour skins

For these, stock glquake is the baseline to consider, because it supports none of the 4. The interesting thing is that winquake, an older engine, supports fullbrights and so is more capable! On the other end of the scale, Fitzquake is an engine which supports all the features we care about today (by default, although some users might disable them!).


Fullbrights are a nice enhancement to models and they are one of the widest supported features. For those poor engines without them, we don’t need to worry too much. The colours in the fullbright section are already quite bright. So the nicest thing we can do for models which mix fullbrights and regular colours is create high contrast around the fullbright pixels, making the non-fullbright portions dark. This makes the fullbrights pop somewhat, even when in glquake.

Beware of the interaction between fullbrights and full colour skins. On the one hand, if you’re converting a high colour skin down to the quake palette, be careful not to introduce fullbrights unintentionally. On the other hand, when creating a full colour skin from an original with fullbrights, you may need to provide an extra fullbright texture – and some engines may not support this feature.

Animation Interpolation

Animation interpolation really improves the animation of quake models, given the low precision that the format offers for animations. For progressive enhancement we need our model to first work without interpolation, then not break when it is added. If it improves when interpolation is added then that is a bonus! Although the point of this article is that getting things to work before the enhancement is the top priority, it’s also a more subtle problem here so we’ll start with how to make interpolation friendly models.

It’s easy to find an example of a model which looks wrong when interpolation is added: the nailgun firing animation. The muzzle flash model can be seen moving from one barrel to the other, then flying back at the player when the attack stops (n.b. Fitzquake gets round this by not applying interpolation to this model, so you’ll need to find a different engine to see this happen). When interpolation is off, the muzzle flash appears instantly at the destination, so there was no need to consider where it was travelling from.

To make a frame interpolation friendly, we need to think where all the parts of the model might be coming from in the previous frame, and where they are going to in the following frame. In the nailgun’s case, the fix is to create two muzzle flashes and make sure each one hides inside the barrel when not needed. This turns interpolation into an enhancement, as you get an animation of the muzzle flash growing and shrinking. To fix the nailgun completely, all of the firing frames have to consider two continuation frames: not just the next firing frame, but the idle frame as well. The idle frame will (eventually) be followed by the first firing frame – we fix both at once by hiding both muzzle flashes inside the gun barrel during the idle frame.

If you need something to disappear completely, the best thing to do is collapse the vertices of that portion of the model into a single point (or make the polygons have zero volume). The way we do this affects how the interpolation looks, a modest example can be seen in the effects models from an earlier post. The forcefield particles stretch vertically as they collapse horizontally, so they create more of a flash in interpolation engines. The smoke just winds up into nothingness. Crucially we wait for these bits of the model to be zero-volume for a frame before we move them back to their starting positions, so that the animation can loop.

The spark grows vertically as it collapses horizontally

Models that break when not interpolated are rarer. Imagine a conveyor belt model with a series of identical panels. We animate it so that each panel moves exactly one space down the line each frame. The interpolation engines will insert frames in-between which make it clear which direction the belt is moving. However in the non-interpolation engines the model looks identical in every frame, so it appears to not move at all!

Even if your model isn’t that exact, it is harder to read the motion of looping models like conveyor belts, waterfalls, and so on when the interpolation isn’t there to help. In the conveyor example, making the panels varied visually would help, as would moving them in fractions of a panel each frame. Making a loop so that eight panels take nine frames to return to their starting positions ensures no two poses are the same, although this makes the animation harder to manage. I ran into exactly this problem when making a waterfall model(returning soon!), and had to add white waves to the texture so the movement could be read.

Alpha blending

You might be designing a model with the intention of applying alpha blending (also known as transparency) to it in game. Mechtech has helped me out here by posting an example of just that in the comments of yesterday’s smoke model. Remember we’re looking at progressive enhancement, and the alpha is that enhancement. So the question we have to ask is, does the model work without the alpha? Luckily in this case the answer is yes: if we looked at that map in winquake the steam would still look okay, we’d be able to see it and it wouldn’t obscure anything important.

Do we ever have to worry? I think sometimes we do. Imagine that we have a window, and the most important thing for gameplay is that players are able to see through the window to the monster/key/button beyond it. The progressive enhancement approach says that we should draw nothing in engines which don’t support alpha, and only draw the window(with alpha) in engines which have it. This is not that easy to do, because there is no reliable way to tell from the QuakeC if alpha is supported. The proper way is to use CheckExtensions, but many engines don’t support it and would show up as false negatives for alpha support. Since we’re doing progressive enhancement that’s not the end of the world, but it is a shame.

The window problem seems like something worth solving, to add another string to the bow of base maps. Is there a good way to progressively enhance windows which adds alpha to a wider selection of engines? And can we still indicate to the player that the window is there, even in our base engines with no alpha support? Well, watch this space…

Full colour skins

Although full colour skins are a useful tool to have, they need to be treated with some caution to fit in with progressive enhancement. The question to ask is: what does my model look like without the full colour skin? There are lots of traps to fall into:

Trap 1: Making the skin far outside the quake palette. If our full colour skin is a long way from normal quake hues, it will be impossible to convert into a quake palette skin for our base engines. It’ll also stick out like a sore thumb in the game world so just don’t do it!

Trap 2: Making a lazy conversion of the skin. It’s very tempting to just throw a placeholder skin on a model while you’re still working on the full colour version, but remember that you need to convert it as well before the model is finished. Because it’s much easier to convert down to a lower colour palette than to convert up from one, your workflow may not follow the order of creating the basic content first, then the enhanced version. What’s more important is designing from the start so your 8-bit skin can look good, and then making sure that when you make the conversion it does look good. This means checking all the seams again for the 8 bit version, dithering carefully, perhaps with some colour balance changes first, and manually repainting anything which still looks off.

Trap 3: Relying on the alpha channel. Full colour skins come with a free alpha channel, so it’s tempting to make use of it. Rely is the keyword here, adding some tatters to a cloak with alpha isn’t a problem because the cloak will work fine without them, making it progressive. If you have a tower crane with girders created by the alpha channel, you’d need to redesign the whole model with polygon details to get something similar in base engines. The progressive enhancement way says: design the model for the base engines first, and then improve it with alpha.

Trap 4: Fullbrights again. Just don’t do it.

The heart of all of this is a) make sure the model without the skin is still good quality and b) that the model isn’t too different with the full colour skin. It’s a fine line to tread though, because the skin can be so similar that it doesn’t really add anything, so use your judgement


That’s all for today. None of these things are absolute rules- if you need to design your mod for the darkplaces engine anyway, then there’s no need to worry about anything else when making your models. If you are making something that you’re hoping other people can use, having these ideas in mind should improve the compatibility of what you make.

One thought on “Progressive Enhancement

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.