# Stripe Colouring

# 1 Definition

Stripe average colouring involves accumulating \(\sin(s \arg Z)\) during iteration of escape time fractals like the Mandelbrot set and Burning Ship.

It turns out that generally all the interesting appearance comes from the last few iterations.

# 2 Example

Stripe colouring example

# 3 Modification

I found that it’s possible to skip accumulating during iteration and just apply a slightly different algorithm after the point has escaped. This works for a subset of escape time formulas, that escape to infinity like monomial power:

  1. at escape, keep the integer iteration count and calculate the fractional iteration count in the normal way;

  2. normalize Z to magnitude 1, or provide data like final angle that allows this to be reconstructed.

  3. run modified stripe average algorithm for a few iterations (e.g. 5 or so): do the formula without adding C

  4. fade the first and last items summed using the fractional iteration count

This basically assumes that if Z escaped, then adding C does almost nothing, and to avoid huge values that might overflow, the Z value is kept normalized to 1, which has the small added benefit that \(\sin(\arg(z)) = \Im(Z)\), which can save some mathops if the stripe density is 1, as in the implementation below.

# 4 Implementation

# 4.1 Fraktaler 3 GLSL

For Fraktaler 3 version 3 unreleased WIP.

Switch statement body must match formula definition, currently set up for M-BS-M-M. Adjustments are needed for non-power-2 formulas.

const float pi = 3.141592653;
const int phases = 4; // number of parts of formula
const int stripes = 5; // octaves of effect

float getStripe(void)
{
  float f = getNF(); // NF fractional part of smooth iteration count
  float t = getT() * 2.0 * pi; // T is arg at escape in turns
  int phase = int(getN0()) % phases; // N0 is integer part of smooth iteration count
  vec2 z = vec2(cos(t), sin(t)); // ignore +c as after escape |z|>>|c|
  float w = 1.0 - f; // fade between iteration bands
  float g = 0.0; // accumulated gradient
  for (int stripe = 0; stripe < stripes; ++stripe)
  {
    g += w * z.y;
    w = 1.0;
    switch ((phase + stripe) % phases)
    {
      case 1: // burning ship part
        z = vec2(abs(z.x), -abs(z.y));
        break;
      default: // mandelbrot part
        break;
    }
    // complex squaring
    z = vec2(z.x * z.x - z.y * z.y, 2.0 * z.x * z.y);
  }
  w = f;
  g += w * z.y;
  g /= float(stripes);
  // now use g in [-1,1] as index for whichever colouring algorithm
  return g;
}

# 5 References