forked from AbleOS/ableos
170 lines
3.7 KiB
Plaintext
170 lines
3.7 KiB
Plaintext
// ln_f32 := fn(x: f32): f32 {
|
|
// if x <= 0 {
|
|
// return -1000000000000000.0
|
|
// }
|
|
// approx := x - 1.0
|
|
// i := 0
|
|
// loop if i == 10 break else {
|
|
// exp_approx := exp_f32(approx)
|
|
// approx -= (exp_approx - x) / exp_approx
|
|
// i += 1
|
|
// }
|
|
// return approx
|
|
// }
|
|
|
|
// exp_f32 := fn(x: f32): f32 {
|
|
// sum := 1.0
|
|
// term := 1.0
|
|
// n := @as(int, 1)
|
|
// loop if n == 20 break else {
|
|
// term *= x / @floatcast(@itf(n))
|
|
// sum += term
|
|
// if term < 0.000006 break
|
|
// n += 1
|
|
// }
|
|
// return sum
|
|
// }
|
|
|
|
// sqrt_f32 := fn(x: f32): f32 {
|
|
// if x <= 0 {
|
|
// return 0.0
|
|
// }
|
|
// guess := x / 2.0
|
|
// tolerance := 0.000001
|
|
// loop {
|
|
// new_guess := (guess + x / guess) / 2.0
|
|
// if guess - new_guess < tolerance {
|
|
// break
|
|
// }
|
|
// guess = new_guess
|
|
// }
|
|
// return guess
|
|
// }
|
|
|
|
render := @use("lib:render")
|
|
sunset := @use("lib:sunset_proto");
|
|
.{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
|
|
|
|
// if you use the minibrot this should be at least 100 to actually see the minibrot,
|
|
// if you use the mandelbrot it looks best under 30
|
|
$MAX_MAX_ITERATION := 100
|
|
|
|
$USE_SUNSET := true
|
|
|
|
$COLOUR_R := 200
|
|
$COLOUR_G := 100
|
|
$COLOUR_B := 255
|
|
|
|
// $COLOUR_R := 255
|
|
// $COLOUR_G := 255
|
|
// $COLOUR_B := 255
|
|
|
|
// $INTERIOR_COLOUR := render.white
|
|
$INTERIOR_COLOUR := render.Color.{r: COLOUR_R, g: COLOUR_G, b: COLOUR_B, a: 255}
|
|
|
|
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)
|
|
}
|
|
render.clear(screen, INTERIOR_COLOUR)
|
|
|
|
max_iteration := 0
|
|
prev_max_iteration := 0
|
|
|
|
x_scale := (X_MAX - X_MIN) / @floatcast(@itf(@bitcast(screen.width)))
|
|
y_scale := (Y_MAX - Y_MIN) / @floatcast(@itf(@bitcast(screen.height)))
|
|
|
|
loop if max_iteration >= MAX_MAX_ITERATION break else {
|
|
log.info("Iteration complete.\0")
|
|
py := 0
|
|
loop if py == screen.height break else {
|
|
px := 0
|
|
loop if px >= screen.width break else {
|
|
x0 := X_MIN + @floatcast(@itf(@bitcast(px))) * x_scale
|
|
y0 := Y_MIN + @floatcast(@itf(@bitcast(py))) * y_scale
|
|
|
|
q := (x0 - 0.25) * (x0 - 0.25) + y0 * y0
|
|
if q * (q + x0 - 0.25) <= 0.25 * y0 * y0 {
|
|
px += 1
|
|
continue
|
|
}
|
|
|
|
if (x0 + 1.0) * (x0 + 1.0) + y0 * y0 <= 0.0625 {
|
|
px += 1
|
|
continue
|
|
}
|
|
|
|
x := 0.0
|
|
y := 0.0
|
|
iteration := 0
|
|
x2 := x * x
|
|
y2 := y * y
|
|
loop if iteration == max_iteration break else {
|
|
if x2 + y2 > 4.0 break
|
|
y = 2.0 * x * y + y0
|
|
x = x2 - y2 + x0
|
|
iteration += 1
|
|
x2 = x * x
|
|
y2 = y * y
|
|
}
|
|
|
|
smooth_value := @itf(@bitcast(iteration - prev_max_iteration / 10)) / @itf(@bitcast(max_iteration))
|
|
smooth_value *= smooth_value * (3 - 2 * smooth_value)
|
|
if iteration < max_iteration & iteration > prev_max_iteration / 10 {
|
|
colour := render.Color.{
|
|
r: @intcast(@fti(smooth_value * COLOUR_R)),
|
|
g: @intcast(@fti(smooth_value * COLOUR_G)),
|
|
b: @intcast(@fti(smooth_value * COLOUR_B)),
|
|
a: 0,
|
|
}
|
|
render.put_pixel(screen, .(px, py), colour)
|
|
}
|
|
// faster
|
|
if iteration >= max_iteration {
|
|
px += 2
|
|
} else if iteration < 5 {
|
|
render.put_hline(screen, py, px, px + 5, .(0, 0, 0, 0))
|
|
px += 5
|
|
} else {
|
|
px += 1
|
|
}
|
|
// slower but more slightly more accurate
|
|
// px += 1
|
|
}
|
|
py += 1
|
|
}
|
|
prev_max_iteration = max_iteration
|
|
max_iteration += 5
|
|
if USE_SUNSET {
|
|
_ = sunset.client.send_frame(window)
|
|
}
|
|
}
|
|
// if USE_SUNSET {
|
|
// loop {
|
|
// _ = sunset.client.send_frame(window)
|
|
// }
|
|
// }
|
|
}
|