Last active
November 1, 2015 15:13
-
-
Save Garciat/53e9405a69ad5922c3ed to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<body style="margin:0"></body> | |
<script> | |
var CLICKZOOM = 3; | |
var NUMWORKERS = 8; | |
var workers = (function () { | |
var w = []; | |
for (var i = 0; i < NUMWORKERS; ++i) | |
w.push(new Worker('worker.js')); | |
return w; | |
})(); | |
function sendWorkerDraw(i /* args */) { | |
var args = [].slice.call(arguments, 1); | |
return new Promise(function (resolve) { | |
var worker = workers[i]; | |
worker.addEventListener('message', function done(ev) { | |
worker.removeEventListener('message', done); | |
resolve(ev.data.buf); | |
}); | |
worker.postMessage({ | |
args: args | |
}); | |
}); | |
} | |
function draw(i, ctx, drawX, drawY, screenX, screenY, screenW, screenH, scale, maxiter) { | |
sendWorkerDraw(i, screenX, screenY, screenW, screenH, scale, maxiter) | |
.then(function (buf) { | |
var arr = new Uint8ClampedArray(buf); | |
var data = new ImageData(arr, screenW, screenH); | |
ctx.putImageData(data, drawX, drawY); | |
}); | |
} | |
function mandelbrot(canvas, planeX, planeY, scale, maxiter) { | |
var SCALE = scale; | |
var MAXITER = maxiter; | |
var ISCALE = 1 / scale; | |
var PLANEX = planeX; | |
var PLANEY = planeY; | |
var SCREENX = PLANEX * SCALE; | |
var SCREENY = PLANEY * SCALE; | |
var SCREENW = canvas.width; | |
var SCREENH = canvas.height; | |
var PLANEW = SCREENW * ISCALE; | |
var PLANEH = SCREENH * ISCALE; | |
var ctx = canvas.getContext('2d'); | |
canvas.addEventListener('click', function zoom(ev) { | |
canvas.removeEventListener('click', zoom); | |
var px = ev.offsetX; | |
var py = ev.offsetY; | |
var scale_ = CLICKZOOM * SCALE; | |
var maxiters_ = 1.4 * MAXITER; | |
var planeW_ = SCREENW / scale_; | |
var planeH_ = SCREENH / scale_; | |
var planeX_ = PLANEX + px * ISCALE - planeW_ / 2; | |
var planeY_ = PLANEY + py * ISCALE - planeH_ / 2; | |
planeX_ += (SCREENW / 2 - px) / scale_; | |
planeY_ += (SCREENH / 2 - py) / scale_; | |
var copyW = SCREENW / CLICKZOOM; | |
var copyH = SCREENH / CLICKZOOM; | |
var copyX = px - copyW / 2; | |
var copyY = py - copyH / 2; | |
copyX += (SCREENW / 2 - px) / CLICKZOOM; | |
copyY += (SCREENH / 2 - py) / CLICKZOOM; | |
ctx.drawImage( | |
canvas, | |
copyX, copyY, copyW, copyH, | |
0, 0, SCREENW, SCREENH | |
); | |
mandelbrot(canvas, planeX_, planeY_, scale_, maxiters_); | |
}); | |
var BLOCKY = Math.ceil(SCREENH / NUMWORKERS); | |
for (var i = 0; i < NUMWORKERS; ++i) { | |
draw( | |
i, | |
ctx, | |
0, | |
i * SCREENH / NUMWORKERS, | |
SCREENX, | |
SCREENY + i * BLOCKY, | |
SCREENW, | |
BLOCKY, | |
SCALE, | |
MAXITER | |
); | |
} | |
return canvas; | |
} | |
window.addEventListener('load', function () { | |
var SCREENW = document.body.clientWidth | |
var SCREENH = document.body.clientHeight; | |
var canvas = document.createElement('canvas'); | |
canvas.width = SCREENW; | |
canvas.height = SCREENH; | |
canvas.style.background = 'black'; | |
document.body.appendChild(canvas); | |
var DOMAINX = -2.5; | |
var DOMAINY = -1.1; | |
var DOMAINW = 3.5; | |
var DOMAINH = 2.2; | |
var scale = Math.min( | |
SCREENW / DOMAINW, | |
SCREENH / DOMAINH | |
); | |
var startX = DOMAINX - (SCREENW - DOMAINW * scale) / 2 / scale; | |
var startY = DOMAINY - (SCREENH - DOMAINH * scale) / 2 / scale; | |
mandelbrot(canvas, startX, startY, scale, 100); | |
}); | |
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var last = 0; | |
onmessage = function (ev) { | |
var result = draw.apply(null, ev.data.args); | |
var buf = result.buffer; | |
postMessage({ | |
buf: buf | |
}, [buf]); | |
}; | |
// inspired by https://www.shadertoy.com/view/4df3Rn | |
function draw(screenX, screenY, screenW, screenH, scale, maxiter) { | |
var SCALE = scale; | |
var MAXITER = maxiter; | |
var ISCALE = 1 / scale; | |
var SCREENX = screenX; | |
var SCREENY = screenY; | |
var SCREENW = screenW; | |
var SCREENH = screenH; | |
var PLANEX = screenX * ISCALE; | |
var PLANEY = screenY * ISCALE; | |
var PLANEW = screenW * ISCALE; | |
var PLANEH = screenH * ISCALE; | |
var output = new Uint8ClampedArray(4 * SCREENW * SCREENH); | |
for (var py = 0; py < SCREENH; ++py) { | |
for (var px = 0; px < SCREENW; ++px) { | |
var x0 = PLANEX + px * ISCALE; | |
var y0 = PLANEY + py * ISCALE; | |
var x = 0; | |
var y = 0; | |
var it = 0; | |
var runaway = false; | |
var dot = 0; | |
for (var i = 0; i < MAXITER; ++i) { | |
var x2 = x * x; | |
var y2 = y * y; | |
dot = x2 + y2; | |
if (dot > 4.0) { | |
it = i; | |
runaway = true; | |
break; | |
} | |
var xtmp = x2 - y2 + x0; | |
y = 2*x*y + y0; | |
x = xtmp; | |
} | |
var ix = 4 * (py * SCREENW + px); | |
if (runaway) { | |
var ip = i - Math.log2(Math.log2(dot * dot)) + 4.0; | |
output[ix + 0] = 255 * (0.5 + 0.5 * Math.cos(3.0 + ip*0.15 + 0.0)); | |
output[ix + 1] = 255 * (0.5 + 0.5 * Math.cos(3.0 + ip*0.15 + 0.6)); | |
output[ix + 2] = 255 * (0.5 + 0.5 * Math.cos(3.0 + ip*0.15 + 1.0)); | |
output[ix + 3] = 255; | |
} else { | |
output[ix + 0] = 0; | |
output[ix + 1] = 0; | |
output[ix + 2] = 0; | |
output[ix + 3] = 255; | |
} | |
} | |
} | |
return output; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment