-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathindex.html
123 lines (110 loc) · 4 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
<!DOCTYPE html>
<html>
<head>
<title>Mandelbrot set - AssemblyScript</title>
<link rel="icon" href="http://assemblyscript.org/favicon.ico" type="image/x-icon" />
<style>
html, body { height: 100%; margin: 0; overflow: hidden; color: #111; background: #fff; font-family: sans-serif; }
h1 { padding: 20px; font-size: 12pt; margin: 0; }
a { color: #111; text-decoration: none; }
a:hover { color: #0074C1; text-decoration: underline; }
canvas { position: absolute; top: 60px; left: 20px; width: calc(100% - 40px); height: calc(100% - 80px); background: #eee; }
canvas.gradient { left: 0; top: 0px; height: 2px; width: 100%; }
</style>
</head>
<body>
<h1>
<a href="https://en.wikipedia.org/wiki/Mandelbrot_set">Mandelbrot set</a> in
<a href="http://assemblyscript.org">AssemblyScript</a>
( <a href="https://github.com/AssemblyScript/assemblyscript/blob/master/examples/mandelbrot/assembly/index.ts">source</a> )
</h1>
<canvas></canvas>
<script>"use strict";
// Set this to false if you prefer a plain image instead.
var animate = true;
// Set up the canvas with a 2D rendering context
var cnv = document.getElementsByTagName("canvas")[0];
var ctx = cnv.getContext("2d");
var bcr = cnv.getBoundingClientRect();
// Compute the size of the viewport
var width = bcr.width | 0;
var height = bcr.height | 0;
var size = width * height;
var byteSize = size << 1; // discrete color indices in range [0, 2047] (here: 2b per pixel)
cnv.width = width;
cnv.height = height;
// Compute the size of and instantiate the module's memory
var memory = new WebAssembly.Memory({ initial: ((byteSize + 0xffff) & ~0xffff) >>> 16 });
var mem = new Uint16Array(memory.buffer);
var imageData = ctx.createImageData(width, height);
var argb = new Uint32Array(imageData.data.buffer);
// Fetch and instantiate the module
fetch("build/optimized.wasm")
.then(response => response.arrayBuffer())
.then(buffer => WebAssembly.instantiate(buffer, {
env: { memory: memory },
JSMath: Math
}))
.then(module => {
var exports = module.instance.exports;
var computeLine = exports.computeLine;
var updateLine = function(y) {
var yx = y * width;
for (let x = 0; x < width; ++x) argb[yx + x] = colors[mem[yx + x]];
};
// Compute an initial balanced version of the set.
const limit = 40;
for (let y = 0; y < height; ++y) {
computeLine(y, width, height, limit);
updateLine(y);
}
// Keep rendering the image buffer.
(function render() {
if (animate) requestAnimationFrame(render);
ctx.putImageData(imageData, 0, 0);
})();
if (animate) {
// Let it glow a bit by occasionally shifting the limit...
var currentLimit = limit;
var shiftRange = 10;
(function updateShift() {
currentLimit = limit + (2 * Math.random() * shiftRange - shiftRange) | 0
setTimeout(updateShift, 1000 + (1500 * Math.random()) | 0);
})();
// ...while continously recomputing a subset of it.
var flickerRange = 3;
(function updateFlicker() {
for (let i = 0, k = (0.05 * height) | 0; i < k; ++i) {
let ry = (Math.random() * height) | 0;
let rl = (2 * Math.random() * flickerRange - flickerRange) | 0;
computeLine(ry, width, height, currentLimit + rl);
updateLine(ry);
}
setTimeout(updateFlicker, 1000 / 30);
})();
}
}).catch(err => {
alert("Failed to load WASM: " + err.message + " (ad blocker, maybe?)");
console.log(err.stack);
});
// Compute a nice set of colors using a gradient
var colors = (() => {
var cnv = document.createElement("canvas");
cnv.width = 2048;
cnv.height = 1;
var ctx = cnv.getContext("2d");
var grd = ctx.createLinearGradient(0, 0, 2048, 0);
grd.addColorStop(0.00, "#000764");
grd.addColorStop(0.16, "#2068CB");
grd.addColorStop(0.42, "#EDFFFF");
grd.addColorStop(0.6425, "#FFAA00");
grd.addColorStop(0.8575, "#000200");
ctx.fillStyle = grd;
ctx.fillRect(0, 0, 2048, 1);
cnv.className = "gradient";
setTimeout(() => document.body.appendChild(cnv));
return new Uint32Array(ctx.getImageData(0, 0, 2048, 1).data.buffer);
})();
</script>
</body>
</html>