Plotting Fractals in WebAssembly
Plotting Fractals in WebAssembly
Previous | Top | Next |
---|---|---|
4: Optimised WAT Implementation | 5: Plotting a Julia Set | 6: Zooming In |
5.1 Web Page Changes | 5.2: WebAssembly Changes |
5.2: WebAssembly Changes
Our existing WebAssembly function mandel_plot
is already very close to what we need for plotting a Julia Set.
Only a few changes are needed:
Rename Function From mandel_plot
To mj_plot
Since the mandel_plot
function is now dual-purpose, this functionality should be reflected in the name.
;; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;; Plot Mandelbrot or Julia set
(func (export "mj_plot")
;; snip...
Supply Function mj_plot
With Additional Arguments
When we were only plotting the Mandelbrot Set, we didn’t care about either the type of image we were plotting (there was only one), or where the mouse pointer was located over that image. However, in order for this function to also plot a Julia Set, some extra information must be supplied:
-
The mouse pointer’s coordinates over the Mandelbrot Set.
These are supplied as twof64
values calledzx
andzy
-
Whether we are plotting the Mandelbrot Set or a Julia Set.
This is supplied as a Boolean flag calledis_mandelbrot
. -
The memory offset where the data for the current image starts.
This is supplied as ani32
argument calledimage_offset
.1
The function signature has now expanded and looks like this:
;; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;; Plot Mandelbrot or Julia set
(func (export "mj_plot")
(param $width i32) ;; Canvas width
(param $height i32) ;; Canvas height
(param $origin_x f64) ;; X origin coordinate
(param $origin_y f64) ;; Y origin coordinate
(param $zx f64) ;; Mouse X coordinate in Mandelbrot Set
(param $zy f64) ;; Mouse Y coordinate in Mandelbrot Set
(param $ppu i32) ;; Pixels per unit (zoom level)
(param $max_iters i32) ;; Maximum iteration count
(param $is_mandelbrot i32) ;; Are we plotting the Mandelbrot Set?
(param $image_offset i32) ;; Shared memory offset of image data
Skip Early Bailout Check For Julia Sets
Since the test for early bailout only applies when plotting the Mandelbrot Set, we must first check what sort of fractal we are plotting.
All we need to do here is extend the early bailout test by AND
ing it with the value of the $is_mandelbrot
flag:
;; Store the current pixel's colour using the value returned from the following if expression
(i32.store
(local.get $pixel_offset)
(if (result i32)
;; If we're plotting the Mandelbrot Set, can we avoid running the escape-time algorithm?
(i32.and
(local.get $is_mandelbrot)
(call $early_bailout (local.get $cx) (local.get $cy))
)
Swap Argument Order
Maybe there’s a glitch in my implementation, but when plotting the Julia Set, I found that the order of the first two pairs of arguments to function escape_time_mj
need to be swapped around, otherwise it plots a strange hybrid Mandelbrot/Julia image.
Hence the call to escape_time_mj
contains an if
expression that reverses the order in which the zx
, zy
and cx
, cy
argument pairs are pushed onto the stack.
(local.tee $pixel_val
;; Reverse argument order for function $escape_time_mj when plotting Julia Set
(call $escape_time_mj
(if (result f64 f64 f64 f64 i32)
(local.get $is_mandelbrot)
(then
(local.get $zx) (local.get $zy)
(local.get $cx) (local.get $cy)
(local.get $max_iters)
)
(else
(local.get $cx) (local.get $cy)
(local.get $zx) (local.get $zy)
(local.get $max_iters)
)
)
)
)
-
Now that function
mj_plot
is used to plot both types of fractal, it is simpler to supply the memory offset at which the image data should be written as an argument, rather than trying to decide which of several possible memory offsets should be used that have been supplied from the host environment. ↩