/* Fire.sl
 *
 * animated fire -- adapted from shader by Flip Phillips
 *
 */

surface fire(float frame = 1;
             tfactor = .1;
             color Ctop = color (1, .3, .1);
             color Cmtop = color (.95, .7, .05);
             color Cmlow = color (.95, .95, .1);
             color Clow = color (1, 1, .8))
{
  color layer_color, surface_color;
  color surface_opac, layer_opac;
  float width, cutoff, f, turb, maxfreq = 16;
  float flame;
  float ss, tt;


  /* ATTENTION SHADE PLUGIN WRITERS: Since I am dealing with surface colors
     and transparencies in a little different manner, these statements don't
     exist in the fire2d.c Evaluate_Fire2D function.
   */
  surface_color = 0;
  surface_opac = 0;


  /* compress ss & offset both by factor of current frame */

  ss = s * 5 + frame * tfactor;
  tt = t + frame * (10 * tfactor);

  /* compute turbulence */

  width = max(filterwidth(ss), filterwidth(tt));

  turb = 0;
  cutoff = clamp(0.5 / width, 0, maxfreq);
  for (f = 1; f < 0.5 * cutoff; f *= 2) 
    turb += abs(snoise2(ss * f, tt * f)) / f;
  fade = clamp(2 * (cutoff - f) / cutoff, 0, 1);
  turb += fade * abs(snoise2(ss * f, tt * f)) / f;
  turb *= 0.5;

  /* index into color spline using turbulence */

  flame = clamp(t - turb, 0, 1);
  layer_opac = flame;

  layer_color = spline(flame, Ctop, Ctop, Ctop, Ctop, Cmtop, Cmlow, Clow, Clow);


  /* ATTENTION SHADE PLUGIN WRITERS: Since I am dealing with surface colors
     and transparencies in a little different manner, these statements don't
     have exact translations in the fire2d.c Evaluate_Fire2D function.
   */
  surface_color = blend(surface_color, layer_color, layer_opac);
  surface_opac = union(surface_opac, layer_opac);


  /* output */

  Oi = surface_opac;
  Ci = surface_color;
}

