GingerBear's Web Log

Simulate Fire in DOOM

Few days ago I was browsing HN and found an article about how fire is implemented in DOOM http://fabiensanglard.net/doom_fire_psx/. It’s very simple and the result is surprisingly good. I cannot stop but trying to implemented in JavaScript right away. I managed to get it working and added some extra controls. Since I found the original article still need a bit digestion to understand. I want to talk about how it is implemented in my own (hopefully even simpler) words.

The Basic

To make fire in a pixel grid, the basic idea is that, we traverse each pixel and update each pixel above them to be “cooler”. And we do it over and over again. This way, if we set all bottom line of pixels to “hottest”. we can see just sit and let it grow up. Like this:

If we make it bigger and put fire's color on it, based on the number. It looks like this.

The Trick

But that doesn’t really look like fire, it’s too “linear”. The trick to make it look like fire is adding some randomness on how the fire “grow” up.

First, instead of always make the above pixel “cooler”, we only do it by 50% chance. So 50% chance the above pixel will be cooler, and 50% the above pixel won't change. It looks like this:

It looks better. Next, when we look for the above pixel, instead of going straight up, we can add a shift to left or right randomly. In code, when we traverse each pixel, find the pixel above, then either, update that pixel, or update the one on its left, or update the one on its right. The result looks like this:

Now it starts to look like fire. Let's try to add more pixels and render it on canvas instead of HTML to get a better performance. We will also get ride of the pixel border and number.

Control fire

wind

In the original article, the author left an exercise for readers to simulate wind. If you get the idea how the fire is generated, it’s pretty straight forward to know wind can be simulated. All we need to do adjust the shift of left or right when update the above pixel. If we shift more to the left, it will cause the pixel leaning toward left, which makes it look like there is a wind blow from right to left. And the same goes to the other way.

Fade the fire

Fading the fire can be simulated by gradually updating the bottom section of the pixel to be “cooler”. It will not only “fade” the bottom section but also “fade” all the pixels above, because they are propagated.

fire intensity

Fire intensity basically means how long does it take for a pixel to get “cool down” as it propagates up. Currently, we set it to be 50% chance to cool down. So if we want the fire to be more “intense”, we just need to make let less possible to cool down.

You can try to control the fire here:

wind
intensity

You can find the source code at https://github.com/GingerBear/doom-fire