1
0
Fork 0
forked from AbleOS/ableos
ableos/sysdata/programs/render_example/src/examples/mandelbrot.hb
2024-12-21 12:01:48 +00:00

98 lines
2.8 KiB
Plaintext

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)
}
}