Files
FractalInspector/shaders/mandelbrot.frag.glsl

85 lines
2.9 KiB
GLSL

#version 120
#ifdef GL_ES
precision highp float;
#endif
#define PI 3.14159265359
vec3 pal(in float t, in vec3 a, in vec3 b, in vec3 c, in vec3 d) {
return a + b*cos(6.28318*(c*t+d));
}
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
uniform vec2 u_translation;
uniform float u_scale;
uniform vec3 u_rgb_1;
uniform vec3 u_rgb_2;
uniform vec3 u_rgb_3;
uniform vec3 u_rgb_4;
#define N 256. // Number of iterations?
#define B 8. // What does B mean?
// The mandelbrot set is a set of complex numbers c for which the function:
// f(z) = z*z + c
// stays bounded between a certain range of values when iterated from z = 0.
float iterate_mandelbrot(vec2 p) {
// Initializes the complex number z to 0, and the constant c to the input coordinate p.
vec2 z = vec2(0), c = p;
float i; // Track iterations.
for (i=0.; i < N; i++ ) {
// This line performs the core Mandelbrot iteration: z = z^2 + c.
// It is done using a matrix multiplication to perform the complex number squaring.
// If z = x + iy, then z&2 = (x+iy)(x+iy) = x^2 - y ^ 2 + 2ixy.
// The matrix [x, -y; y, x] multiplied by [x, y] gives [x*x - y*y, y*x + x*y] = [Re(z^2) Im(z^2)].
// Then we add the constant complex number c (represented by the input vec2).
z = mat2(z, -z.y, z.x) * z + c;
// Check if the magnitude squared of z (distance from the origin squared) exceeds a certain bound (B*B).
// If it does, the point is likely to escape to infinity, so we break out of the loop.
if (dot(z, z) > B*B) break;
}
// The following section calculates a smooth iteration count for better visual results.
// This condition seems to handle a specific case, possibly related to symmetry.
// If the y-component of the input point p is negative, it returns the integer iteration count.
if (p.y < 0.f) return i;
// If the point didn't escape within the maximum iterations or if p.y is non-negative,
// this line calculates a more precise, floating-point iteration count.
// It uses the logarithm of the magnitude squared of z to estimate how far "outside" the
// Mandelbrot set the point is. This allows for smoother color gradients in the fractal.
// - log(log(dot(z, z)) / log(B)) / log(2.) is a common formula for this smoothing.
return i - log(log(dot(z, z)) / log(B)) / log(2.);
// The commented-out line would simply return the integer number of iterations.
// return i;
}
void main() {
vec2 R = u_resolution.xy;
// Unused as of yet, see TODOs for what and why.
float scale = (3.0 - u_scale);
vec2 uv = (u_scale * gl_FragCoord.xy - R - 1.) / R.y - u_translation;
float n = iterate_mandelbrot(uv) / N;
vec3 col = pal(fract(n + 0.5), u_rgb_1, u_rgb_2, u_rgb_3, u_rgb_4);
//if (n == 1.) {n = 0; }
gl_FragColor = vec4(n == 1. ? vec3(0) : col, 1.);
}