From e6c8125cfe4be7dcb05a20ed8ec290ece72158a5 Mon Sep 17 00:00:00 2001 From: cpsdqs Date: Sun, 25 Oct 2020 00:10:27 +0200 Subject: [PATCH] Interactive mandelbrot: use quadtree table for nicer previews --- .../mandelbrot/mandelbrot-interactive.csn | 89 +++++++++++++------ 1 file changed, 60 insertions(+), 29 deletions(-) diff --git a/examples/mandelbrot/mandelbrot-interactive.csn b/examples/mandelbrot/mandelbrot-interactive.csn index 4c2ab2a..cc53e42 100644 --- a/examples/mandelbrot/mandelbrot-interactive.csn +++ b/examples/mandelbrot/mandelbrot-interactive.csn @@ -5,10 +5,6 @@ (def H 768) (def MAXITER 50) - ; size of big pixels - (def COL_SKIP 8) - (def ROW_SKIP 8) - (lds @cout "Interactive Mandelbrot\n") (lds @cout "----------------------\n") (lds @cout "Navigate using WASD, zoom using Q/E\n") @@ -20,8 +16,46 @@ (sym mb_y r3) (sym mb_s r4) (sym mb_row r5) - (sym mb_col_skip r6) - (sym mb_row_skip r7) + + ; index into the skip/size table + (sym mb_skip_index r6) + + ; size of big pixels + (def COL_SKIP 8) + (def ROW_SKIP 8) + ; incrementally renders 1x1, 2x2, 4x4, ... + (def MB_SKIP_TABLE_SIZE 80) + (def MB_SKIP_REPEAT_INDEX 16) + (sym mb_skip_table_x r7) + (sym mb_skip_table_y r8) + (sym mb_size_table r12) + (mkbf mb_skip_table_x ( + 0 4 0 4 2 6 0 2 4 6 2 6 0 2 4 6 + ; 8x8 grid + 1 3 5 7 1 3 5 7 1 3 5 7 1 3 5 7 + 0 2 4 6 0 2 4 6 0 2 4 6 0 2 4 6 + 1 3 5 7 1 3 5 7 1 3 5 7 1 3 5 7 + ; do top left pixels again + 0 2 4 6 0 2 4 6 0 2 4 6 0 2 4 6 + )) + (mkbf mb_skip_table_y ( + 0 0 4 4 0 0 2 2 2 2 4 4 6 6 6 6 + ; 8x8 grid + 0 0 0 0 2 2 2 2 4 4 4 4 6 6 6 6 + 1 1 1 1 3 3 3 3 5 5 5 5 7 7 7 7 + 1 1 1 1 3 3 3 3 5 5 5 5 7 7 7 7 + ; do top left pixels again + 0 0 0 0 2 2 2 2 4 4 4 4 6 6 6 6 + )) + (mkbf mb_size_table ( + 8 4 4 4 2 2 2 2 2 2 2 2 2 2 2 2 + ; 8x8 grid + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + ; do top left pixels again + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + )) (ld mb_x 0.0) (ld mb_y 0.0) @@ -31,13 +65,13 @@ (ld is_first_render 1) ; render row - ; big - is this the first render? if yes, use big pixels - ; col - mb_col_skip column offset + ; size - pixel size + ; col - column offset ; px - offset x ; py - offset y ; scale - scaling ; row - row position - (proc render_row big col px py scale row + (proc render_row size col px py scale row (sym gradient r9) (mkbf gradient ( 0x421e0f 0x19071a 0x09012f 0x040449 0x000764 0x0c2c8a 0x1852b1 0x397dd1 @@ -57,13 +91,7 @@ ) (else? (ld r0 0)) ) - (cmp big 1) - (j.ne :not_big) - (sc-rect x y COL_SKIP ROW_SKIP r0) - (j :was_big) - (:not_big) - (sc-wr x y r0) - (:was_big) + (sc-rect x y size size r0) (add x COL_SKIP) (cmp x W) (j.lt :col) @@ -126,14 +154,19 @@ ; mark this as a first render and reset col_skip and row_skip (ld is_first_render 1) - (ld mb_col_skip 0) - (ld mb_row_skip 0) + (ld mb_skip_index 0) (:did_not_move) - ; render row mb_row + mb_row_skip + (sym mb_col_skip r9) + (sym mb_row_skip r11) + (bfrd mb_col_skip @mb_skip_table_x mb_skip_index) + (bfrd mb_row_skip @mb_skip_table_y mb_skip_index) + (bfrd r1 @mb_size_table mb_skip_index) + + ; render row mb_row + row skip (ld r0 mb_row) (add r0 mb_row_skip) - (call render_row is_first_render mb_col_skip mb_x mb_y mb_s r0) + (call render_row r1 mb_col_skip mb_x mb_y mb_s r0) (cmp mb_row H) (j.ge :render_done) @@ -143,16 +176,14 @@ (:render_done) ; otherwise, this frame is done (ld mb_row 0) - (add mb_col_skip 1) + (add mb_skip_index 1) (ld is_first_render 0) - (mod mb_col_skip COL_SKIP) - - ; if mb_col_skip wrapped back to zero increase mb_row_skip - (cmp mb_col_skip 0) - (j.ne :not_col) - (add mb_row_skip 1) - (mod mb_row_skip ROW_SKIP) - (:not_col) + + (cmp mb_skip_index MB_SKIP_TABLE_SIZE) + ; if skip index is out of bounds, go back to repeating area + (j.lt :not_end) + (ld mb_skip_index MB_SKIP_REPEAT_INDEX) + (:not_end) (:render_not_done) (j :slp)