Skip to content

Commit

Permalink
feat: can load wasm now
Browse files Browse the repository at this point in the history
  • Loading branch information
istudyatuni committed Feb 5, 2022
1 parent 3657a27 commit f9122af
Show file tree
Hide file tree
Showing 15 changed files with 140 additions and 100 deletions.
1 change: 1 addition & 0 deletions .eslintrc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ ignorePatterns:
- node_modules
- public
- build
- src/wasm
extends: eslint:recommended
globals:
Atomics: readonly
Expand Down
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
build
node_modules
/build
/node_modules

*.sublime-workspace
3 changes: 2 additions & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
build
/build
src/wasm
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1 +1,7 @@
# Mandelbrot set

## Build WASM

```bash
yarn build:wasm
```
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"scripts": {
"dev": "snowpack dev",
"build": "snowpack build",
"build:wasm": "./scripts/build/wasm.sh",
"test": "jest",
"prepare": "husky install .husky",
"format": "redrun format:eslint format:prettier",
Expand Down
17 changes: 17 additions & 0 deletions scripts/build/wasm.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/bin/bash

# optimization
O='-O3'

cd src/wasm

docker run --rm -v "$(pwd):/src" -u "$(id -u):$(id -g)" emscripten/emsdk \
em++ $O mandelbrot.cpp -o mandelbrot.js \
-s NO_EXIT_RUNTIME=1 \
-s EXPORTED_RUNTIME_METHODS=ccall,cwrap \
-s EXPORTED_FUNCTIONS=_checkSeries \
-s EXPORT_ES6=1 \
-s MODULARIZE=1 \
$@

# options EXPORT_ES6, MODULARIZE, EXPORTED_RUNTIME_METHODS from https://stackoverflow.com/q/53309095
34 changes: 0 additions & 34 deletions src/canvas/draw.js

This file was deleted.

4 changes: 3 additions & 1 deletion src/components/App.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<script context="module">
import Canvas from 'src/components/Canvas.svelte'
import { wasmLoaded } from 'src/stores/loaded'
</script>

<script>
Expand All @@ -8,6 +10,6 @@

<svelte:window bind:innerWidth={width} bind:innerHeight={height} />

{#if width !== undefined && height !== undefined}
{#if width !== undefined && height !== undefined && $wasmLoaded}
<Canvas {width} {height} />
{/if}
4 changes: 2 additions & 2 deletions src/components/Canvas.svelte
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script context="module">
import { onMount } from 'svelte'
import { drawMandelbrot } from 'src/canvas/draw'
import { drawMandelbrot } from 'src/utils/canvas/draw'
</script>

<script>
Expand All @@ -16,7 +16,7 @@
onMount(() => {
gl = canvas.getContext('2d')
gl.rect(0, 0, width, height)
gl.fillStyle = 'white'
gl.fillStyle = 'black'
gl.fill()
field = gl.getImageData(0, 0, width, height)
Expand Down
3 changes: 3 additions & 0 deletions src/stores/loaded.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { writable } from 'svelte/store'

export const wasmLoaded = writable(false)
51 changes: 51 additions & 0 deletions src/utils/canvas/draw.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { wasmLoaded } from 'src/stores/loaded'

import Module from 'src/wasm/mandelbrot.js'

let checkSeries

// https://stackoverflow.com/a/53384917
Module().then(function (mod) {
checkSeries = mod.cwrap('checkSeries', 'boolean', ['number', 'number'])
wasmLoaded.set(true)
})

function coords2complex(x, y /*, sx, sy*/, sw, sh) {
return [x - sw / 2, sh - y - sh / 2]
}

function calcDataPos(x, y, w) {
return (x * w + y) * 4
}

/**
* Draw mandelbrot on image
* @param {ImageData} image Image from canvas
* @return {ImageData} Resulting image
*/
export function drawMandelbrot(image) {
const width = image.width,
height = image.height
let pos, a, b, c

for (let x = 0; x < width; x++) {
for (let y = 0; y < height; y++) {
console.log('i')

c = coords2complex(x, y, width, height)
a = c[0]
b = c[1]

if (checkSeries(a, b)) {
pos = calcDataPos(x, y, width)

// black
image.data[pos] = 0
image.data[pos + 1] = 0
image.data[pos + 2] = 0
}
}
}

return image
}
33 changes: 0 additions & 33 deletions src/utils/math/complex.js

This file was deleted.

27 changes: 0 additions & 27 deletions src/utils/math/mandelbrot.js

This file was deleted.

2 changes: 2 additions & 0 deletions src/wasm/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.js
*.wasm
50 changes: 50 additions & 0 deletions src/wasm/mandelbrot.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#include <complex>
// #include <emscripten/emscripten.h>

using std::complex;
// using namespace std::complex_literals;

// for export with emscripten
// https://stackoverflow.com/a/63879243
extern "C" {
bool checkSeries(double x, double i);
}

/**
* Convert coordinates to complex number
*
* We have canvas with size: sw is width and sh is height,
* zero coordinates of complex plane at center
*/
complex<double> coords2complex(
double x, double y, double sw, double sh) {
return complex<double>(x - sw / 2, sh - y - sh / 2);
}

// EMSCRIPTEN_KEEPALIVE
bool checkSeries(double x, double i) {
complex<double> point = complex<double>(x, i);
const int R = 2, N = 1000;
const complex<double> z0 = 0;

complex<double> num = z0 + point;

for (int i = 0; i < N; i++) {
if (std::abs(num) >= R) {
return false;
}

num = std::pow(num, 2) * point;
}

return true;
}

/*int main() {
const int width = 1600, height = 717;
// left and right x coord
const double lx = -2, rx = 1;
const double xwidth = std::abs(lx) + std::abs(rx);
const double scale = width / xwidth;
const double yheight = height / scale;
}*/

0 comments on commit f9122af

Please sign in to comment.