mandelbrot

Mandelbrot viewer written in C and GLSL
git clone anongit@rnpnr.xyz:mandelbrot.git
Log | Files | Refs | Feed | LICENSE

frag.glsl (3160B)


      1 /* see LICENSE for licensing details */
      2 #version 460 core
      3 
      4 out vec4 colour;
      5 
      6 uniform uvec2 u_screen_dim;
      7 uniform vec2  u_top_left;
      8 uniform vec2  u_bottom_right;
      9 
     10 uniform vec2 u_z_n[300];
     11 uniform bool u_use_approx = false;
     12 
     13 const int   iterations    = 300;
     14 const float escape_radius = 4.0;
     15 
     16 /* input:  h [0,360] | s,v [0, 1] *
     17  * output: rgb [0,1]              */
     18 vec3 hsv2rgb(vec3 hsv)
     19 {
     20 	vec3 k = mod(vec3(5, 3, 1) + hsv.x / 60, 6);
     21 	k = max(min(min(k, 4 - k), 1), 0);
     22 	return hsv.z - hsv.z * hsv.y * k;
     23 }
     24 
     25 vec3 wavelength2rgb(float lambda)
     26 {
     27 	vec3 rgb = vec3(0);
     28 	float t;
     29 	/* red */
     30 	if        (lambda >= 400 && lambda < 410) {
     31 		t = (lambda - 400) / 10;
     32 		rgb.x =        0.33 * t - (0.20 * t * t);
     33 	} else if (lambda >= 410 && lambda < 475) {
     34 		t = (lambda - 410) / 65;
     35 		rgb.x = 0.14            - (0.13 * t * t);
     36 	} else if (lambda >= 545 && lambda < 595) {
     37 		t = (lambda - 545) / 50;
     38 		rgb.x =        1.98 * t - (      t * t);
     39 	} else if (lambda >= 595 && lambda < 650) {
     40 		t = (lambda - 595) / 65;
     41 		rgb.x = 0.98 + 0.06 * t - (0.40 * t * t);
     42 	} else if (lambda >= 650 && lambda < 700) {
     43 		t = (lambda - 650) / 50;
     44 		rgb.x = 0.65 - 0.84 * t + (0.20 * t * t);
     45 	}
     46 
     47 	/* green */
     48 	if        (lambda >= 415 && lambda < 475) {
     49 		t = (lambda - 415) / 60;
     50 		rgb.y =                 + (0.80 * t * t);
     51 	} else if (lambda >= 475 && lambda < 585) {
     52 		t = (lambda - 475) / 115;
     53 		rgb.y = 0.80 + 0.76 * t - (0.80 * t * t);
     54 	} else if (lambda >= 585 && lambda < 639) {
     55 		t = (lambda - 585) / 54;
     56 		rgb.y = 0.84 - 0.84 * t                 ;
     57 	}
     58 
     59 	/* blue */
     60 	if        (lambda >= 400 && lambda < 475) {
     61 		t = (lambda - 400) / 75;
     62 		rgb.z =        2.20 * t - (1.50 * t * t);
     63 	} else if (lambda >= 475 && lambda < 560) {
     64 		t = (lambda - 475) / 85;
     65 		rgb.z = 0.70 +        t + (0.30 * t * t);
     66 	}
     67 	return rgb;
     68 }
     69 
     70 vec2 map_mandelbrot(vec2 v)
     71 {
     72 	vec2 scale = abs(u_top_left - u_bottom_right);
     73 	return vec2(u_top_left.x, u_bottom_right.y) + v * scale;
     74 }
     75 
     76 vec2 complex_mult(vec2 a, vec2 b)
     77 {
     78 	vec2 result;
     79 	result.x = a.x * a.x - b.y * b.y;
     80 	result.y = 2 * a.x * b.y;
     81 	return result;
     82 }
     83 
     84 void main()
     85 {
     86 	vec2 vf = gl_FragCoord.xy / u_screen_dim.xy;
     87 	vec2 d  = map_mandelbrot(vf);
     88 
     89 	int i;
     90 	vec2 z = u_use_approx ? u_z_n[0] : d;
     91 	vec2 e = vec2(0);
     92 	float xx = 0, yy = 0;
     93 
     94 	if (u_use_approx) {
     95 		for (i = 0; i < iterations && xx + yy < escape_radius; i++) {
     96 			xx = z.x * z.x;
     97 			yy = z.y * z.y;
     98 			e = complex_mult(2 * u_z_n[i], e) + complex_mult(e, e) + d;
     99 			z = u_z_n[i] + e;
    100 		}
    101 	} else {
    102 		for (i = 0; i < iterations && xx + yy < escape_radius; i++) {
    103 			xx = z.x * z.x;
    104 			yy = z.y * z.y;
    105 			z  = vec2(xx - yy + d.x, 2 * z.x * z.y + d.y);
    106 		}
    107 	}
    108 
    109 	/* extra iterations to reduce error in escape calculation */
    110 	/* fun value j = 5 */
    111 	for (int j = 0; j < 2; j++) {
    112 		xx = z.x * z.x;
    113 		yy = z.y * z.y;
    114 		z  = vec2(xx - yy + d.x, 2 * z.x * z.y + d.y);
    115 	}
    116 
    117 	float zmag = sqrt(xx + yy);
    118 	float mu = i - log(log(zmag)) / log(2.0);
    119 	mu = clamp(mu, 0, iterations);
    120 	float q = pow(mu / iterations, 0.8);
    121 	//float q = pow(mu / iterations, 0.69);
    122 	//float q = mu / iterations;
    123 	//colour = vec4(hsv2rgb(vec3(q, 0.8, 0.8)), 1.0);
    124 	colour = vec4(wavelength2rgb(400.0 + 300 * q).xyz, 1.0);
    125 }