Link to shadertoy |
Here's my source code:
struct complex {
float r;
float i;
};
complex add(complex c1, complex c2) {
return complex(c1.r + c2.r, c1.i + c2.i);
}
complex multiply(complex c1, complex c2) {
complex c_new = complex(0.0, 0.0);
c_new.r = c1.r * c2.r - (c1.i * c2.i);
c_new.i = c1.r * c2.i + (c1.i * c2.r);
return c_new;
}
vec2 create_uv() {
float aspectRatio = iResolution.x / iResolution.y;
float scaling = 2.5;
vec2 uv = (gl_FragCoord.xy / iResolution.xy) * scaling;
uv.x = uv.x * aspectRatio - scaling * 1.1;
uv.y -= scaling / 2.0;
return uv;
}
bool has_escaped(complex c) {
return abs(c.r) + abs(c.i) >= 4.0;
}
void main(void)
{
vec2 uv = create_uv();
complex z = complex(uv.x, uv.y);
complex c = complex(uv.x, uv.y);
vec3 col = vec3(0.0);
const float iterations = 50.0;
for (float i = 0.0; i < iterations; i++) {
complex z_new = multiply(z, z);
z = add(z_new, c);
if (has_escaped(z)) {
col += vec3(i / iterations, 0.0, i / iterations);
col.z = col.z + 0.05*cos(iGlobalTime);
break;
}
}
gl_FragColor = vec4(col, 1.0);
}
float r;
float i;
};
complex add(complex c1, complex c2) {
return complex(c1.r + c2.r, c1.i + c2.i);
}
complex multiply(complex c1, complex c2) {
complex c_new = complex(0.0, 0.0);
c_new.r = c1.r * c2.r - (c1.i * c2.i);
c_new.i = c1.r * c2.i + (c1.i * c2.r);
return c_new;
}
vec2 create_uv() {
float aspectRatio = iResolution.x / iResolution.y;
float scaling = 2.5;
vec2 uv = (gl_FragCoord.xy / iResolution.xy) * scaling;
uv.x = uv.x * aspectRatio - scaling * 1.1;
uv.y -= scaling / 2.0;
return uv;
}
bool has_escaped(complex c) {
return abs(c.r) + abs(c.i) >= 4.0;
}
void main(void)
{
vec2 uv = create_uv();
complex z = complex(uv.x, uv.y);
complex c = complex(uv.x, uv.y);
vec3 col = vec3(0.0);
const float iterations = 50.0;
for (float i = 0.0; i < iterations; i++) {
complex z_new = multiply(z, z);
z = add(z_new, c);
if (has_escaped(z)) {
col += vec3(i / iterations, 0.0, i / iterations);
col.z = col.z + 0.05*cos(iGlobalTime);
break;
}
}
gl_FragColor = vec4(col, 1.0);
}
What's happening is basically that we're in the complex number plane and all that means is we count its value on the x axis as a real number but we count its value on the y axis as an imaginary number. We apply an equation for each pixel (remember we represent the pixel with a real number on x axis, imaginary number on y axis) and see if the results are greater than a certain number after running through the equation several times. If they are greater (they "escape"), we color the point based on how quickly it escaped (how many times we ran it through the equation until it reached that number). The Mandelbrot set is the set of all points who haven't escaped (the black part in the middle).