20201015

Retro-styled forest-fire cellular automata in WebGL


This is a cellular automata analogue of the model that we used for developmental retinal waves in this paper


Key rules

  • Vegetation "grows" occasionally (flip a coin to increment amount of trees)
  • Fires have a small chance of starting spontaneously
  • Intensity of ignited fires decay down to zero, at which point they leave ash
  • Fires spread to adjacent cells with a probability that depends on their intensity
  • Probability of a cell igniting given a fire is related to how much vegetation there is

Sketch of WebGL implementation:

  • A single RGBA texture stores the game state
  • Each color channel in [0,1] can be mapped to a [0,255] byte value
  • A "noise" texture creates pseudorandom numbers
  • The green channel stores the level of vegetation (BURNT,NONE,GRASS,SCRUB,TREE)
  • The blue channel stores the intensity of the fire
  • The red channel outputs a tile ID value that is passed to a tile shader to render the game


 The core of the code is implemented in this shader:

void main() {
    vec2 dx = vec2(1.0/game_size.x,0.0);
    vec2 dy = vec2(0.0,1.0/game_size.y);
    vec2  p = gl_FragCoord.xy/game_size;
    // Get neighborhood
    vec4 s01 = texture2D(game_state,p-dy);
    vec4 s10 = texture2D(game_state,p-dx);
    vec4 s11 = texture2D(game_state,p);
    vec4 s12 = texture2D(game_state,p+dx);
    vec4 s21 = texture2D(game_state,p+dy);
    // Get noise
    vec4 n = texture2D(noise,p);
    // Trees emerge with some probablity
    float tree = s11.g + float(n.r<4.0/256.0)*0.1;
    // Fire burns out
    float fire = s11.b-1.0/18.0;
    // Fire spreads if there are trees to burn
    float PrFire = s01.b+s10.b+s12.b+s21.b;
    PrFire = PrFire*0.5+0.0005;
    float u = n.g+n.b/256.0;
    if (u<(PrFire*(tree-0.1))) {fire=9.0/10.0;}
    if (fire>0.0) tree=0.0;
    // Tile IDs for each state
    int id = (fire>0.0)? ONFIRE+int(fire*9.0): 
        (tree>0.7)? TREE : 
        (tree>0.4)? SCRUB : 
        (tree>0.3)? GRASS :  
        (tree>0.0)? NONE : 
        BURNT;
    gl_FragColor = vec4(float(id)/255.0,tree,fire,0.0);
}

No comments:

Post a Comment