Mandelbrot Set

A shader implemetation of the mandelbrot set.

Usage:
Make a Color Rect, apply the material with the shader to it, set the palette image (example one given below).

Uniforms:
Iteration limit – Limit the number of iterations per pixel
View – Camera position
Zoom – Camera zoom
Ratio – Aspect ratio of the color rect (height divided by width)
Palette Image – Image representing the color palette. The shader only cares about the first row. The left-most pixel is applied when given pixel is inside the set (usually black), the pixels to the right correspond to number of iterations. You can use this one: https://i.vgy.me/TDVB1i.png

Shader code
shader_type canvas_item;

uniform int iteration_limit = 500;
uniform vec2 view = vec2(-0.75, 0.0);
uniform float zoom: hint_range(0.0, 15.0) = 0.0;
uniform float ratio = 1.0;
uniform sampler2D palette_image: hint_albedo;

// Returns: vec4(final position, iterations, is inside the set)
vec4 mandelbrot(vec2 c, int iterations) {
	vec2 z = vec2(0.0, 0.0);
	vec2 z2 = vec2(0.0, 0.0);
	int i = 0;
	
	while (z2.x + z2.y <= 4.0 && ++i < iterations) {
		z = vec2(z2.x - z2.y + c.x, 2.0 * z.x * z.y + c.y);
		z2 = z * z;
	}
	
	return vec4(z, float(i), i == iterations ? 1.0 : 0.0);
}

vec4 mandelbrot_smooth(vec2 c, int iterations) {
	vec4 m = mandelbrot(c, iterations);
	
	return vec4(
		m.xy,
		m.z + 1.0 - log(log(m.x * m.x + m.y * m.y) / 2.0 / log(2)) / log(2),
		m.w
	);
}

vec3 palette(vec4 m) {
	int color_count = textureSize(palette_image, 0).x - 1;
	
	if (m.w == 1.0) {
		return texelFetch(palette_image, ivec2(0, 0), 0).rgb;
	}
	
	vec3 color1 = texelFetch(palette_image, ivec2(1 + int(m.z) % color_count, 0), 0).rgb;
	vec3 color2 = texelFetch(palette_image, ivec2(1 + (int(m.z) + 1) % color_count, 0), 0).rgb;
	return mix(color1, color2, fract(m.z));
}

void fragment() {
	vec2 uv = ((UV - vec2(0.5)) * vec2(ratio, 1.0)) / exp(zoom - 1.25) + view;
	
	vec4 result = mandelbrot_smooth(uv, iteration_limit);
	vec3 color = palette(result);
	
	COLOR = vec4(color, 1.0);
}
Tags
fractal, mandelbrot
The shader code and all code snippets in this post are under CC0 license and can be used freely without the author's permission. Images and videos, and assets depicted in those, do not fall under this license. For more info, see our License terms.

More from Mighty Duke

PS1 Post-processing

PS1 Shader

Related shaders

set corner radius for texture

guest
0 Comments
Inline Feedbacks
View all comments