Luple
Luple

Reputation: 491

basic fractal coloring problems

I am trying to get more comfortable with the math behind fractal coloring and understanding the coloring algorithms much better. I am the following paper:

http://jussiharkonen.com/files/on_fractal_coloring_techniques%28lo-res%29.pdf

The paper gives specific parameters to each of the functions, however when I use the same, my results are not quite right. I have no idea what could be going on though.

I am using the iteration count coloring algorithm to start and using the following julia set:

c = 0.5 + 0.25i and p = 2 

with the coloring algorithm:

The coloring function simply returns the number of
elements in the truncated orbit divided by 20

And the palette function:

I(u) = k(u − u0),
where k = 2.5 and u0 = 0, was used.

And with a palette being white at 0 and 1, and interpolating to black in-between.

and following this algorithm:

  1. Set z0 to correspond to the position of the pixel in the complex plane.
  2. Calculate the truncated orbit by iterating the formula zn = f(zn−1) starting from z0 until either • |zn| > M, or • n = Nmax, where Nmax is the maximum number of iterations.
  3. Using the coloring and color index functions, map the resulting truncated orbit to a color index value.
  4. Determine an RGB color of the pixel by using the palette function

Using this my code looks like the following:

float izoom = pow(1.001, zoom );

vec2 z = focusPoint + (uv * 4.0 - 2.0)  * 1.0 / izoom;

vec2 c = vec2(0.5f, 0.25f) ;


const float B = 2.0;
float l;

for( int i=0; i<100; i++ )
{
     z = vec2( z.x*z.x - z.y*z.y, 2.0*z.x*z.y ) + c;

     if( length(z)>10.0) break;
     l++;

}
float ind = basicindex(l);
vec4 col = color(ind);

and have the following index and coloring functions:

float basicindex(float val){
    return val / 20.0;
}

vec4 color(float index){

    float r  = 2.5 * index;
    float g = r; 
    float b = g;
    vec3 v = 0.5 - 0.5 *  sin(3.14/2.0 + 3.14 * vec3(r, g, b));
    return vec4(1.0 - v, 1.0) ;

}

The paper provides the following image: https://i.sstatic.net/QjpcV.jpg

While my code produces: https://i.sstatic.net/Ny999.jpg

I get the correct results by using k = 1.0 instead of 2.5, however I would prefer to understand why my results are incorrect. When extending this to the smooth coloring algorithms, my results are still incorrect so I would like to figure this out first.

Let me know if this isn't the correct place for this kind of question and I can move it to the math stack exchange. I wasn't sure which place was more appropriate.

Upvotes: 1

Views: 203

Answers (1)

Tatarize
Tatarize

Reputation: 10806

Your image is perfectly implemented for Figure 3.3 in the paper. The other image you posted uses a different routine.

figure 3.3

Your figure seems to have that bit of perspective code there at top, but remove that and they should be the same.

your result

If your objection is the color extremes you set that with the "0.5 - 0.5 * ..." part of your code. This makes the darkest black originally 0.5 when in the example image you're trying to duplicate the darkest black should be 1 and the lightest white should be 0.

You're making the whiteness equal to the distance from 0.5


If you ignore the fractal all together you are getting a bunch of values that can be normalized between 0 and 1 and you're coloring those in some particular ways. Clearly the image you are duplicating is linear between 0 and 1 so putting black as 0.5 cannot be correct.

o = {
    length : 500,
    width : 500,
    c : [.5, .25], // c = x + iy will be [x, y]
    maxIterate : 100,
    canvas : null
}

function point(pos, color){
    var c = 255 - Math.round((1 + Math.log(color)/Math.log(o.maxIterate)) * 255);
    c = c.toString(16);
    
    if (c.length == 1) c = '0'+c;
    o.canvas.fillStyle="#"+c+c+c;
    o.canvas.fillRect(pos[0], pos[1], 1, 1);
}

function conversion(x, y, R){
    var m = R / o.width;
    var x1 = m * (2 * x - o.width);
    var y2 = m * (o.width - 2 * y);
    return [x1, y2];
}

function f(z, c){
    return [z[0]*z[0] - z[1] * z[1] + c[0], 2 * z[0] * z[1] + c[1]];
}

function abs(z){
    return Math.sqrt(z[0]*z[0] + z[1]*z[1]);
}

function init(){
    var R = (1 + Math.sqrt(1+4*abs(o.c))) / 2,
        z, x, y, i;

    o.canvas = document.getElementById('a').getContext("2d");
    for (x = 0; x < o.width; x++){
        for (y = 0; y < o.length; y++){
            i = 0;
            z = conversion(x, y, R);
            while (i < o.maxIterate && abs(z) < R){
                z = f(z, o.c);
                if (abs(z) > R) break;
                i++;
            }
            

            if (i) point([x, y], i / o.maxIterate);
        }
    }
}

init();
<canvas id="a" width="500" height="500"></canvas>

via: http://jsfiddle.net/3fnB6/29/

Upvotes: 1

Related Questions