How the flames were implemented in Doom on the Playstation

Original author: Fabien Sanglard
  • Transfer

A whole chapter of my book Game Engine Black Book: DOOM is dedicated to the console ports of DOOM and the difficulties that their developers faced. You can talk for a long time about the complete failure on 3DO, about the difficulties on Saturn due to affine texture mapping and about the tremendous “reverse engineering from scratch” performed by Randy Linden for Super Nintendo.

Initially, moving in the direction leading to the catastrophe [1] , the developers of the port under the Playstation 1 (PSX) were later able to change course and create a port that won success with critics and the market. Final doomwas the first true port, comparable to the PC version. The alpha-blended color sectors not only improved the visual quality, but also improved the gameplay thanks to the key indication of the desired color. Also, thanks to the PSX console's Audio Processing Unit reverb effects, the sound has been improved.

The development team has done so high-quality work that it still has a few free CPU cycles, which they decided to use to generate animated fire in the intro and gameplay. I was so much in awe that I decided to figure out how the effect was realized. When the first searches did not give an answer, I prepared to blow the dust off the MIPS book to crack the executable file, but Samuel Villarreal responded on time to Twitter that he had already completed the reverse development of the Nintendo 64 version [2] . It was enough for me just to clean it up a bit, simplify and optimize it.

It was interesting to re-discover this classic effect of the demoscene; its underlying idea is similar to the first water ripple , which was part of the mandatory set of programs of many developers of the 90s. The effect of fire became a living witness to the time when the combination of a carefully selected color palette and a simple trick was the only way to achieve the desired.

Basic idea




Basically, the fire effect uses a simple altitude map. The screen-sized array is filled with 37 values ​​ranging from 0 to 36. Each value is associated with a color from white to black, and captures yellow, orange and red along the way between them. The idea is to simulate the temperature of a flame particle that rises and cools gradually.


The frame buffer is initialized completely black (filled with zeros) with a single white row of white pixels at the bottom (36), which is the “source” of the flame.


Every time the screen is updated, the “heat” rises. For each pixel in the frame buffer, a new value is calculated. Each pixel is updated with the value immediately below it. In the code, the lower left corner is the zero index of the array, and the upper right corner has the index FIRE_HEIGHT * FIRE_WIDTH - 1.

function doFire(){
    for(x=0 ; x < FIRE_WIDTH; x++) {
        for (y = 1; y < FIRE_HEIGHT; y++) {
            spreadFire(y * FIRE_WIDTH + x);
        }
    }
 }
 function spreadFire(src){
    firePixels[src - FIRE_WIDTH] = firePixels[src] - 1;
 }

Note that line 0 is never updated (iteration on y does not begin with 0, but with 1). This zero-filled string is the “generator” of the fire. A simple version with linear cooling (- = 1) gives us a boring uniform output.


We can slightly change the spreadFire () function and modify the decay rate of heat values. Adding randomness is fine.

function spreadFire(src){
    var rand = Math.round(Math.random() * 3.0) & 3;
    firePixels[src - FIRE_WIDTH ] = pixel - (rand & 1);
 }


That's better. To improve the illusion, you can randomly distribute not only up, but also left and right.

function spreadFire(src){
    var rand = Math.round(Math.random() * 3.0) & 3;
    var dst = src - rand + 1;
    firePixels[dst - FIRE_WIDTH ] = firePixels[src] - (rand & 1);
 }


[Approx. Per.: Youtube awfully clamps the video, it is better to watch the demo on Javascript in the original article or open the GIF under the spoiler.]

Animation of a flame in GIF (23 megabytes)
image

Voila! Note that changing the flame spreading process can also simulate wind. I will leave this as an exercise for readers who have managed to finish reading the article.

Full source code




Samuel’s version (logically) looked more like assembly language. If you want to look at it, then there is a cleaned and simplified version.

Reference materials




[1] Source: The full story is described in detail in the Game Engine Black Book: DOOM book.

[2] Source: Twitter post for March 25, 2018

Also popular now: