-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathindex.ts
48 lines (42 loc) · 1.8 KB
/
index.ts
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
// see: https://en.wikipedia.org/wiki/Mandelbrot_set
/** Number of discrete color values on the JS side. */
const NUM_COLORS = 2048;
/** Computes a single line in the rectangle `width` x `height`. */
export function computeLine(y: u32, width: u32, height: u32, limit: u32): void {
var translateX = width / 1.6;
var translateY = height / 2.0;
var scale = 10.0 / min(3 * width, 4 * height);
var imaginary = (y - translateY) * scale;
for (let x: u32 = 0; x < width; ++x) {
let real = (x - translateX) * scale;
// Iterate until either the escape radius or iteration limit is exceeded
let ix = 0.0, iy = 0.0, ixSq: f64, iySq: f64;
let iteration: u32 = 0;
while ((ixSq = ix * ix) + (iySq = iy * iy) <= 4.0) {
let ixNew = ixSq - iySq + real;
iy = 2.0 * ix * iy + imaginary;
ix = ixNew;
if (iteration >= limit) break;
++iteration;
}
// Do a few extra iterations for quick escapes to reduce error margin
for (let minIterations = min(8, limit); iteration < minIterations; ++iteration) {
let ixNew = ix * ix - iy * iy + real;
iy = 2.0 * ix * iy + imaginary;
ix = ixNew;
}
// Iteration count is a discrete value in the range [0, limit] here, but we'd like it to be
// normalized in the range [0, 2047] so it maps to the gradient computed in JS.
// see also: http://linas.org/art-gallery/escape/escape.html
let frac = Math.log(Math.log(Math.sqrt(ix * ix + iy * iy))) / Math.LN2;
let icol = isFinite(frac)
? <u32>((NUM_COLORS - 1) * clamp((iteration + 1 - frac) / limit, 0.0, 1.0))
: NUM_COLORS - 1;
store<u16>((y * width + x) << 1, icol);
}
}
/** Clamps a value between the given minimum and maximum. */
@inline
function clamp<T>(value: T, minValue: T, maxValue: T): T {
return min(max(value, minValue), maxValue);
}