cooler mandelbrot
This commit is contained in:
parent
5b3a97e580
commit
642b0b74b5
14
Cargo.lock
generated
14
Cargo.lock
generated
|
@ -88,18 +88,18 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-queue"
|
name = "crossbeam-queue"
|
||||||
version = "0.3.11"
|
version = "0.3.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35"
|
checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-utils"
|
name = "crossbeam-utils"
|
||||||
version = "0.8.20"
|
version = "0.8.21"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
|
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "derive_more"
|
name = "derive_more"
|
||||||
|
@ -213,12 +213,12 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hbbytecode"
|
name = "hbbytecode"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#dc96c8b10ae85af7a11bd1e8ca2cd29e2c42a033"
|
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#9f43e3bb925534f613cb2089df6e5fe315fc851a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hblang"
|
name = "hblang"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#dc96c8b10ae85af7a11bd1e8ca2cd29e2c42a033"
|
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#9f43e3bb925534f613cb2089df6e5fe315fc851a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
"hbbytecode",
|
"hbbytecode",
|
||||||
|
@ -229,7 +229,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hbvm"
|
name = "hbvm"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#dc96c8b10ae85af7a11bd1e8ca2cd29e2c42a033"
|
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#9f43e3bb925534f613cb2089df6e5fe315fc851a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hbbytecode",
|
"hbbytecode",
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,45 +1,66 @@
|
||||||
// ln_f32 := fn(x: f32): f32 {
|
ln_f64 := fn(x: f64): f64 {
|
||||||
// if x <= 0 {
|
if x <= 0.0 return -100000000000000000000000.0
|
||||||
// return -1000000000000000.0
|
if x == 1.0 return 0.0
|
||||||
// }
|
if x == E return 1.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 {
|
scale := @as(f64, 0.0)
|
||||||
// sum := 1.0
|
scaled_x := x
|
||||||
// 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 scaled_x > 2.0 {
|
||||||
// if x <= 0 {
|
loop if scaled_x <= 2.0 break else {
|
||||||
// return 0.0
|
scaled_x = scaled_x / E
|
||||||
// }
|
scale += 1.0
|
||||||
// guess := x / 2.0
|
}
|
||||||
// tolerance := 0.000001
|
} else if scaled_x < 1.0 {
|
||||||
// loop {
|
loop if scaled_x >= 1.0 {
|
||||||
// new_guess := (guess + x / guess) / 2.0
|
scaled_x = scaled_x * E
|
||||||
// if guess - new_guess < tolerance {
|
scale -= 1.0
|
||||||
// break
|
}
|
||||||
// }
|
}
|
||||||
// guess = new_guess
|
|
||||||
// }
|
guess := (scaled_x - 1.0) / (scaled_x + 1.0)
|
||||||
// return guess
|
|
||||||
// }
|
max_iter := 30
|
||||||
|
i := 0
|
||||||
|
loop if i == max_iter break else {
|
||||||
|
exp_g := exp_f64(guess)
|
||||||
|
f := exp_g - scaled_x
|
||||||
|
f_prime := exp_g
|
||||||
|
|
||||||
|
delta := f / (f_prime * (1.0 - 0.5 * f * f_prime / (f_prime * f_prime)))
|
||||||
|
|
||||||
|
guess = guess - delta
|
||||||
|
|
||||||
|
if abs_f64(delta) < 0.0000000001 break
|
||||||
|
i += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return guess + scale
|
||||||
|
}
|
||||||
|
|
||||||
|
exp_f64 := fn(x: f64): f64 {
|
||||||
|
result := @as(f64, 1.0)
|
||||||
|
term := @as(f64, 1.0)
|
||||||
|
n := @as(int, 1)
|
||||||
|
|
||||||
|
loop if n == 20 break else {
|
||||||
|
term = term * x / @itf(n)
|
||||||
|
result += term
|
||||||
|
|
||||||
|
if abs_f64(term) < 0.0000000001 break
|
||||||
|
n += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
abs_f64 := fn(x: f64): f64 {
|
||||||
|
if x < 0 return -x else return x
|
||||||
|
}
|
||||||
|
|
||||||
|
lerp_f64 := fn(v0: f64, v1: f64, t: f64): f64 {
|
||||||
|
return v0 + t * (v1 - v0)
|
||||||
|
}
|
||||||
|
|
||||||
render := @use("lib:render")
|
render := @use("lib:render")
|
||||||
sunset := @use("lib:sunset_proto");
|
sunset := @use("lib:sunset_proto");
|
||||||
|
@ -57,22 +78,21 @@ $X_MAX := -0.93
|
||||||
$Y_MIN := 0.31
|
$Y_MIN := 0.31
|
||||||
$Y_MAX := 0.306
|
$Y_MAX := 0.306
|
||||||
|
|
||||||
// if you use the minibrot this should be at least 100 to actually see the minibrot,
|
$MAX_ITERATION := 300
|
||||||
// if you use the mandelbrot it looks best under 30
|
|
||||||
$MAX_MAX_ITERATION := 30000000
|
|
||||||
|
|
||||||
$USE_SUNSET := true
|
$USE_SUNSET := false
|
||||||
|
|
||||||
$COLOUR_R := 200
|
$COLOUR_R := 200
|
||||||
$COLOUR_G := 100
|
$COLOUR_G := 100
|
||||||
$COLOUR_B := 255
|
$COLOUR_B := 255
|
||||||
|
|
||||||
// $COLOUR_R := 255
|
$LOG_2 := 0.693147180559945309417232121458176568
|
||||||
// $COLOUR_G := 255
|
$E := 2.71828182845904523536028747135266250
|
||||||
// $COLOUR_B := 255
|
|
||||||
|
|
||||||
// $INTERIOR_COLOUR := render.WHITE
|
$INTERIOR_COLOUR := render.BLACK
|
||||||
$INTERIOR_COLOUR := render.Color.{r: COLOUR_R, g: COLOUR_G, b: COLOUR_B, a: 255}
|
|
||||||
|
palette := [render.Color].(render.RED, render.YELLOW, render.GREEN, render.CYAN, render.BLUE, render.MAGENTA)
|
||||||
|
$LEN_PALETTE := @sizeof(@TypeOf(palette)) / @sizeof(render.Color)
|
||||||
|
|
||||||
example := fn(): void {
|
example := fn(): void {
|
||||||
screen := @as(render.Surface, idk)
|
screen := @as(render.Surface, idk)
|
||||||
|
@ -90,19 +110,15 @@ example := fn(): void {
|
||||||
}
|
}
|
||||||
screen.clear(INTERIOR_COLOUR)
|
screen.clear(INTERIOR_COLOUR)
|
||||||
|
|
||||||
max_iteration := 0
|
x_scale := @as(f64, X_MAX - X_MIN) / @itf(@bitcast(screen.width))
|
||||||
prev_max_iteration := 0
|
y_scale := @as(f64, Y_MAX - Y_MIN) / @itf(@bitcast(screen.height))
|
||||||
|
|
||||||
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 {
|
|
||||||
py := 0
|
py := 0
|
||||||
loop if py == screen.height break else {
|
loop if py == screen.height break else {
|
||||||
px := 0
|
px := 0
|
||||||
loop if px >= screen.width break else {
|
loop if px >= screen.width break else {
|
||||||
x0 := X_MIN + @floatcast(@itf(@bitcast(px))) * x_scale
|
x0 := @as(f64, X_MIN) + @itf(@bitcast(px)) * x_scale
|
||||||
y0 := Y_MIN + @floatcast(@itf(@bitcast(py))) * y_scale
|
y0 := @as(f64, Y_MIN) + @itf(@bitcast(py)) * y_scale
|
||||||
|
|
||||||
q := (x0 - 0.25) * (x0 - 0.25) + y0 * y0
|
q := (x0 - 0.25) * (x0 - 0.25) + y0 * y0
|
||||||
if q * (q + x0 - 0.25) <= 0.25 * y0 * y0 {
|
if q * (q + x0 - 0.25) <= 0.25 * y0 * y0 {
|
||||||
|
@ -115,49 +131,43 @@ example := fn(): void {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
x := 0.0
|
x := @as(f64, 0.0)
|
||||||
y := 0.0
|
y := @as(f64, 0.0)
|
||||||
iteration := 0
|
iteration := 0
|
||||||
x2 := x * x
|
|
||||||
y2 := y * y
|
loop if x * x + y * y > @itf(1 << 16) | iteration == MAX_ITERATION break else {
|
||||||
loop if iteration == max_iteration break else {
|
x_temp := x * x - y * y + x0
|
||||||
if x2 + y2 > 4.0 break
|
y = 2 * x * y + y0
|
||||||
y = 2.0 * x * y + y0
|
x = x_temp
|
||||||
x = x2 - y2 + x0
|
|
||||||
iteration += 1
|
iteration += 1
|
||||||
x2 = x * x
|
|
||||||
y2 = y * y
|
|
||||||
}
|
}
|
||||||
|
|
||||||
smooth_value := @itf(@bitcast(iteration - prev_max_iteration / 10)) / @itf(@bitcast(max_iteration))
|
c := *screen.indexptr(px, py)
|
||||||
smooth_value *= smooth_value * (3 - 2 * smooth_value)
|
if c.r != INTERIOR_COLOUR.r | c.b != INTERIOR_COLOUR.b | c.g != INTERIOR_COLOUR.g {
|
||||||
if iteration < max_iteration & iteration > prev_max_iteration / 10 {
|
px += 1
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if iteration < MAX_ITERATION {
|
||||||
|
log_zn := ln_f64(x * x + y * y) / 2.0
|
||||||
|
nu := ln_f64(log_zn / LOG_2) / LOG_2
|
||||||
|
smoothed := @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.{
|
colour := render.Color.{
|
||||||
r: @intcast(@fti(smooth_value * COLOUR_R)),
|
r: @intcast(@fti(lerp_f64(@itf(@intcast(colour0.r)), @itf(@intcast(colour1.r)), normalised))),
|
||||||
g: @intcast(@fti(smooth_value * COLOUR_G)),
|
g: @intcast(@fti(lerp_f64(@itf(@intcast(colour0.g)), @itf(@intcast(colour1.g)), normalised))),
|
||||||
b: @intcast(@fti(smooth_value * COLOUR_B)),
|
b: @intcast(@fti(lerp_f64(@itf(@intcast(colour0.b)), @itf(@intcast(colour1.b)), normalised))),
|
||||||
a: 0,
|
a: 0,
|
||||||
}
|
}
|
||||||
screen.put_pixel(.(px, py), colour)
|
screen.put_pixel(.(px, py), colour)
|
||||||
}
|
}
|
||||||
// faster
|
|
||||||
if iteration >= max_iteration {
|
|
||||||
px += 2
|
|
||||||
} else if iteration < 5 {
|
|
||||||
screen.put_hline(py, px, px + 5, .(0, 0, 0, 0))
|
|
||||||
px += 5
|
|
||||||
} else {
|
|
||||||
px += 1
|
px += 1
|
||||||
}
|
}
|
||||||
// slower but more slightly more accurate
|
|
||||||
// px += 1
|
|
||||||
}
|
|
||||||
py += 1
|
py += 1
|
||||||
}
|
}
|
||||||
prev_max_iteration = max_iteration
|
if USE_SUNSET loop {
|
||||||
max_iteration += 5
|
|
||||||
if USE_SUNSET {
|
|
||||||
_ = sunset.client.send_frame(window)
|
_ = sunset.client.send_frame(window)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
|
@ -25,11 +25,11 @@ resolution = "1024x768x24"
|
||||||
[boot.limine.ableos.modules.render_example]
|
[boot.limine.ableos.modules.render_example]
|
||||||
path = "boot:///render_example.hbf"
|
path = "boot:///render_example.hbf"
|
||||||
|
|
||||||
[boot.limine.ableos.modules.sunset_server]
|
# [boot.limine.ableos.modules.sunset_server]
|
||||||
path = "boot:///sunset_server.hbf"
|
# path = "boot:///sunset_server.hbf"
|
||||||
|
|
||||||
[boot.limine.ableos.modules.ps2_mouse_driver]
|
# [boot.limine.ableos.modules.ps2_mouse_driver]
|
||||||
path = "boot:///ps2_mouse_driver.hbf"
|
# path = "boot:///ps2_mouse_driver.hbf"
|
||||||
|
|
||||||
# [boot.limine.ableos.modules.ps2_keyboard_driver]
|
# [boot.limine.ableos.modules.ps2_keyboard_driver]
|
||||||
# path = "boot:///ps2_keyboard_driver.hbf"
|
# path = "boot:///ps2_keyboard_driver.hbf"
|
||||||
|
|
Loading…
Reference in a new issue