render := @use("lib:render") sunset := @use("lib:sunset_proto"); .{math, log} := @use("stn") // full mandelbrot $X_MIN := -2.0 $X_MAX := 0.47 $Y_MIN := -1.12 $Y_MAX := 1.12 // a minibrot // $X_MIN := -0.94 // $X_MAX := -0.93 // $Y_MIN := 0.31 // $Y_MAX := 0.306 // zoom into that weird curve part of the main cardioid // $X_MIN := 0.25 // $X_MAX := 0.34 // $Y_MIN := -0.075 // $Y_MAX := 0.075 $MAX_ITERATION := 300 $USE_SUNSET := true palette := render.Color.[.(50, 0, 60, 0), .(93, 0, 157, 0), .(140, 98, 229, 0), .(191, 190, 255, 0), .(226, 234, 255, 0), .(242, 250, 255, 0), .(226, 234, 255, 0), .(191, 190, 255, 0), .(140, 98, 229, 0), .(93, 0, 157, 0), .(50, 0, 60, 0)] $LEN_PALETTE := @sizeof(@TypeOf(palette)) / @sizeof(render.Color) example := fn(): void { screen := @as(render.Surface, idk) window := @as(?sunset.Window, null) if USE_SUNSET { sunset.client.find_server() window = sunset.client.new(.(.(450, 140), .(400, 400), "Mandelbrot Set\0")) if window == null { log.error("got no window\0") return } screen = window.surface } else { screen = render.init(false) } x_scale := @as(f64, X_MAX - X_MIN) / @itf(@bitcast(screen.width)) y_scale := @as(f64, Y_MAX - Y_MIN) / @itf(@bitcast(screen.height)) py := 0 loop if py == screen.height break else { px := 0 loop if px >= screen.width break else { x0 := @as(f64, X_MIN) + @itf(@bitcast(px)) * x_scale y0 := @as(f64, Y_MIN) + @itf(@bitcast(py)) * y_scale q := (x0 - 0.25) * (x0 - 0.25) + y0 * y0 if q * (q + x0 - 0.25) <= 0.25 * y0 * y0 | (x0 + 1.0) * (x0 + 1.0) + y0 * y0 <= 0.0625 { px += 1 continue } x := @as(f64, 0.0) y := @as(f64, 0.0) iteration := 0 // arbitrary, i cant tell the difference between 32 and 1 << 16 loop if x * x + y * y > 32.0 | iteration == MAX_ITERATION break else { x_temp := x * x - y * y + x0 y = 2 * x * y + y0 x = x_temp iteration += 1 } if iteration < MAX_ITERATION { log_zn := math.ln(f64, x * x + y * y) / 2 nu := math.ln(f64, log_zn / math.LN_2) / math.LN_2 smoothed := @as(f64, @itf(@bitcast(iteration + 1))) - nu smoothed_int := @fti(smoothed) normalised := smoothed - @itf(smoothed_int) colour0 := palette[@bitcast(smoothed_int) % LEN_PALETTE] colour1 := palette[@bitcast(smoothed_int + 1) % LEN_PALETTE] colour := render.Color.{ r: @intcast(@fti(math.lerp(f64, @itf(colour0.r), @itf(colour1.r), normalised))), g: @intcast(@fti(math.lerp(f64, @itf(colour0.g), @itf(colour1.g), normalised))), b: @intcast(@fti(math.lerp(f64, @itf(colour0.b), @itf(colour1.b), normalised))), a: 0, } screen.put_pixel(.(px, py), colour) } px += 1 } py += 1 if USE_SUNSET { _ = sunset.client.send_frame(window) } } if USE_SUNSET loop { _ = sunset.client.send_frame(window) } }