Mandelbrot Set through shaders in GLSL with LOVE2d renders a circle, not a fractal -


i'm trying render mandelbrot set using glsl, full circle... have checked maths lot, , cannot find error, thought maybe problem semantic.

is able see what's wrong?

also, give me insights on organization, structure, etc? i'm trying learn proper coding, it's hard find material on styling.

obs.: shader can applied on image

the idea simple (you may skip this):

  • checkconvergence returns true if z has not diverged (i.e., abs(z) < 4
    • sumsquare returns complex multiplication (z.r, z.i)*(z.r, z.i) - (c.r, c.i), k.r = re(k) , k.i = im(k)
    • iterate actual algorithm: keeps squaring z until diverges or reaches maximum number of iterations (tol)
    • clr parameterized function returns rgb array depends on n
    • finally, effect magic should happen, doing 2 things:
      • it takes coordinates of pixel (glsl normalizes interval(0, 1) , normalizes mandelbrot set size (-2
      • it calls clr on iterate on coordinates.
glslshader = love.graphics.newshader[[     vec2 c = vec2(1.0, 0.0);     int tol = 100;      vec4 black = vec4(0.0, 0.0, 0.0, 1.0);     vec4 white = vec4(1.0, 1.0, 1.0, 1.0);      bool checkconvergence(vec2 z) {       return (z[0]*z[0] + z[1]*z[1] < 4);     }      vec2 sumsquare(vec2 z) {       return vec2(z[0]*z[0] - z[1]*z[1] - c[0], 2 * z[0] * z[1] - c[1]);     }      int iterate(vec2 z) {       int n = 0;       while (checkconvergence(z) && (n < tol)) {         vec2 z =  sumsquare(z);         n = n + 1;       }       return n;     }      vec4 clr(int n){       if(n == tol){return vec4(0.0,0.0,0.0,1.0);}        int r, g, b;       r = int(255*n + 47*(1-n));       g = int(180*n + 136*(1-n));       b = int(38*n + 255*(1-n));        if (r > 255) {r = 255;}       else{          if(r<0){r = 0;}       }        if (g > 255) {g = 255;}       else{         if(g<0){g = 0;}       }        if (b > 255) {b = 255;}       else{         if(b<0){b = 0;}       }        return vec4(r, g, b, 1.0);      }      vec4 effect( vec4 color, image texture, vec2 texture_coords, vec2 screen_coords){       vec2 z = vec2(texture_coords.x*4-2, texture_coords.y*4-2);        return clr(iterate(z));     }   ]] 

update

i've tried suggestions @weathervane:

  • add c instead of subtracting it;
  • start z (0.0, 0.0) , pass starting point of iteration c;

but no avail, still circle. tried using more iterations

i tried simplify coding without changing much.

i added condition clr function, returns green if n smaller 0 or greater 1. strange thing circle black , rest of screen white, don't see white can come (since clr never returns white 0 < n < 1 ).

    vec2 c = vec2(0.0, 0.0);     int tol = 1000;      vec4 black = vec4(0.0, 0.0, 0.0, 1.0);     vec4 white = vec4(1.0, 1.0, 1.0, 1.0);     vec4 green = vec4(0.0, 1.0, 0.0, 1.0);      int iterate(vec2 z) {       int n = 0;        while ( (z[0]*z[0] + z[1]*z[1] < 4) && (n < tol) ) {         vec2 z =  vec2( z[0]*z[0] - z[1]*z[1]  + c[0], 2 * z[0] * z[1] + c[1] );         n = n + 1;       }        return n;     }      vec4 clr(int n){         n = n / tol;          if(n == 1){return black;}         if(n > 1 || n < 0){return green;}          int r, g, b;         r = int(255*n + 47*(1-n));         g = int(180*n + 136*(1-n));         b = int(38*n + 255*(1-n));          return vec4(r, g, b, 1.0);        }      vec4 effect( vec4 color, image texture, vec2 texture_coords, vec2 screen_coords){       vec2 z = vec2(texture_coords.x*4-2, texture_coords.y*4-2);        return clr(iterate(z));     } 

the starting point of iteration should passed vector c, while z start {0.0.0.0}.

as can find in https://en.wikipedia.org/wiki/mandelbrot_set

a complex number c part of mandelbrot set if, when starting z = 0 , applying iteration z = z² + c repeatedly, absolute value of z remains bounded large n gets.

you using vec4 colors instead of using float, in code calculating rgb component integers value. should cast float , normalize each component (0.0,1.0) range. tried correct code, i'm afraid don't know lua nor love2d , wasn't able use texture_coords, used screen_coords. best this:

function love.load()     glslshader = love.graphics.newshader[[          vec4 black = vec4(0.0, 0.0, 0.0, 1.0);         vec4 white = vec4(1.0, 1.0, 1.0, 1.0);         int max_iter = 1024;          vec4 clr(int n){             if(n == max_iter){return black;}              float m = float(n)/float(max_iter);             float r = float(mod(n,256))/32;             float g = float(128 - mod(n+64,127))/255;             float b = float(127 + mod(n,64))/255;              if (r > 1.0) {r = 1.0;}             else{                  if(r<0){r = 0;}             }              if (g > 1.0) {g = 1.0;}             else{                 if(g<0){g = 0;}             }              if (b > 1.0) {b = 1.0;}             else{                 if(b<0){b = 0;}             }             return vec4(r, g, b, 1.0);         }          vec4 effect( vec4 color, image texture, vec2 texture_coords, vec2 screen_coords){              vec2 c = vec2((screen_coords[0]-500)/200,(screen_coords[1]-300)/200);             vec2 z = vec2(0.0,0.0);             vec2 zn = vec2(0.0,0.0);             int n_iter = 0;             while ( (z[0]*z[0] + z[1]*z[1] < 4) &&  (n_iter < max_iter) ) {                 zn[0] = z[0]*z[0] - z[1]*z[1] + c[0];                 zn[1] = 2*z[0]*z[1] + c[1];                 z[0] = zn[0];                 z[1] = zn[1];                 n_iter++;             }             return clr(n_iter);         }     ]] end  function love.draw()      love.graphics.setshader(glslshader)     love.graphics.rectangle('fill', 0,0,800,600)     love.graphics.setshader() end 

which gave me output:

enter image description here


Comments

Popular posts from this blog

ruby - Trying to change last to "x"s to 23 -

jquery - Clone last and append item to closest class -

c - Unrecognised emulation mode: elf_i386 on MinGW32 -