Skip to content

test 123 #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions combo.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
importScripts('fractal.js');

class ComboFractal extends Mandelbrot {
constructor() {
super();

// TODO(mime): move out of web worker
document.getElementById('julia-map').innerHTML = '<canvas id="julia-canvas" />';
this.julia = new Julia('julia-canvas');
}

setCanvas(canvas, height) {
super.setCanvas(canvas, height);

postMessage(this.variables);
}

setOptionsAndDraw(options, opt_mouseX, opt_mouseY) {
super.setOptionsAndDraw(options);

Expand All @@ -25,6 +34,20 @@ class ComboFractal extends Mandelbrot {
}

dispose() {
// TODO(mime): hook up to webworker
document.getElementById('julia-map').innerHTML = '';
}
}


const instance = new ComboFractal();
onmessage = (e) => {
switch (e.data.msg) {
case 'init':
instance.setCanvas(e.data.canvas, e.data.height);
break;
default:
instance.setOptionsAndDraw(e.data.options, e.data.mouseX, e.data.mouseY);
break;
}
};
18 changes: 11 additions & 7 deletions fractal.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
class Fractal {
constructor(canvasId) {
constructor() {
this.variables = {};
this.variableLocations = {};
}

this.canvas = document.getElementById(canvasId || 'canvas');
this.canvas.width = this.canvas.height = this.canvas.clientHeight;
setCanvas(canvas, height) {
this.canvas = canvas;
this.canvas.width = this.canvas.height = height;

this.gl = this.canvas.getContext('webgl');
this.gl.viewport(0, 0, this.canvas.clientHeight, this.canvas.clientHeight);
this.gl.viewport(0, 0, height, height);

this.glDrawArraysMode = this.gl.TRIANGLE_FAN;

Expand Down Expand Up @@ -46,13 +49,14 @@ class Fractal {
}

dispose() {

}

setOptionsAndDraw(options, opt_mouseX, opt_mouseY) {
for (const key in options) {
this.variables[key].value = options[key];
}
postMessage(this.variables);

this.draw();
}
Expand All @@ -64,7 +68,7 @@ class Fractal {

for (const key in this.variables) {
const variable = this.variables[key];
this.gl['uniform' + variable.type](variable.location, variable.value);
this.gl['uniform' + variable.type](this.variableLocations[key], variable.value);
}
this.gl.drawArrays(this.glDrawArraysMode, 0, 4);
}
Expand Down Expand Up @@ -92,7 +96,7 @@ class Fractal {

for (const key in this.variables) {
const variable = this.variables[key];
variable.location = this.gl.getUniformLocation(prog, key);
this.variableLocations[key] = this.gl.getUniformLocation(prog, key);
}
}

Expand Down
4 changes: 0 additions & 4 deletions fractals.html
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,6 @@ <h4>inspiration</h4>
</div>
</aside>

<script src="fractal.js"></script>
<script src="julia.js"></script>
<script src="mandelbrot.js"></script>
<script src="combo.js"></script>
<script src="ui.js"></script>
</body>
</html>
24 changes: 22 additions & 2 deletions julia.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
// adapted and greatly modified from http://universefactory.net/test/julia/

importScripts('fractal.js');

class Julia extends Fractal {
constructor(canvasId) {
super(canvasId);
constructor() {
super();

this.variables = {
antiAlias: { type: '1i', value: 1 },
Expand All @@ -15,9 +17,15 @@ class Julia extends Fractal {
zoom: { type: '1f', value: 1.5 },
};
this.buffer = [-1, -1, 1, -1, 1, 1, -1, 1];
}

setCanvas(canvas, height) {
super.setCanvas(canvas, height);

this.buildProgram(this.vertexShader, this.fragmentShader);
this.assignAttribOffsets(0, 2, { p: 0 });

postMessage(this.variables);
}

get vertexShader() {
Expand Down Expand Up @@ -82,3 +90,15 @@ class Julia extends Fractal {
`
}
}

const instance = new Julia();
onmessage = (e) => {
switch (e.data.msg) {
case 'init':
instance.setCanvas(e.data.canvas, e.data.height);
break;
default:
instance.setOptionsAndDraw(e.data.options);
break;
}
};
33 changes: 27 additions & 6 deletions mandelbrot.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@
// http://hvidtfeldts.net/WebGL-DP/webgl.html (code is out-of-date but works if you tweak it)
// http://hvidtfeldts.net/WebGL/webgl.html

class Mandelbrot extends Fractal {
constructor(canvasId) {
super(canvasId);
importScripts('fractal.js');

const w = this.canvas.width * 0.5;
const h = this.canvas.height * 0.5;
class Mandelbrot extends Fractal {
constructor() {
super();

this.variables = {
antiAlias: { type: '1i', value: 1 },
Expand All @@ -18,7 +17,7 @@ class Mandelbrot extends Fractal {
iterations: { type: '1i', value: 128 },
offsetX: { type: '1f', value: 0.0 },
offsetY: { type: '1f', value: 0.0 },
pixelSize: { type: '2fv', value: [1.0 / w, 1.0 / h] },
pixelSize: { type: '2fv', value: [1.0, 1.0] },
time: { type: '1f', value: Date.now() / 1000 },
zoom: { type: '1f', value: 1.5 },
};
Expand All @@ -29,11 +28,21 @@ class Mandelbrot extends Fractal {
1.0, -1.0, 0.0,
-1.0, -1.0, 0.0,
];
}

setCanvas(canvas, height) {
super.setCanvas(canvas, height);

const w = height * 0.5;
const h = height * 0.5;
this.variables.pixelSize = { type: '2fv', value: [1.0 / w, 1.0 / h] };

this.glDrawArraysMode = this.gl.TRIANGLE_STRIP;

this.buildProgram(this.vertexShader, this.doublePrecisionMath + this.fragmentShader);
this.assignAttribOffsets(0, 3, { position: 0 });

postMessage(this.variables);
}

preDraw() {
Expand Down Expand Up @@ -192,3 +201,15 @@ class Mandelbrot extends Fractal {
`;
}
}

const instance = new Mandelbrot();
onmessage = (e) => {
switch (e.data.msg) {
case 'init':
instance.setCanvas(e.data.canvas, e.data.height);
break;
default:
instance.setOptionsAndDraw(e.data.options);
break;
}
};
80 changes: 52 additions & 28 deletions ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,19 @@ class FractalUI {
this.altPressed = false;
this.ctrlPressed = false;

this.fractalOptions = [Julia, Mandelbrot, ComboFractal];
this.currentFractalIndex = 0;
this.currentFractal = new this.fractalOptions[this.currentFractalIndex];
this.fractalOptions = ['julia', 'mandelbrot', 'combo'];
this.currentFractalIndex = -1;
this.domCanvas = null;
this.offscreenCanvas = null;
this.currentFractalWorker = null;
this.currentVariables = {};

this.changeFractal();

this.bindEventListeners();

this.currentFractal.setOptionsAndDraw({
zoom: 1.5,
this.currentFractalWorker.postMessage({
options: { zoom: 1.5 },
});

setTimeout(() => {
Expand All @@ -42,11 +47,25 @@ class FractalUI {
}

changeFractal() {
this.currentFractal.dispose();
this.currentFractalWorker && this.currentFractalWorker.terminate();

document.getElementById('container').innerHTML = '<canvas id="canvas" />';
this.domCanvas = document.getElementById('canvas');
this.offscreenCanvas = this.domCanvas.transferControlToOffscreen();

document.getElementById('container').innerHtml = '<canvas id="canvas" />';
this.currentFractalIndex = (this.currentFractalIndex + 1) % this.fractalOptions.length;
this.currentFractal = new this.fractalOptions[this.currentFractalIndex];
this.currentFractalWorker = new Worker(`${this.fractalOptions[this.currentFractalIndex]}.js`);
this.currentFractalWorker.postMessage(
{
msg: 'init',
canvas: this.offscreenCanvas,
height: this.domCanvas.clientHeight,
},
[this.offscreenCanvas]
);
this.currentFractalWorker.onmessage = (e) => {
this.currentVariables = e.data;
};
}

bindEventListeners() {
Expand All @@ -70,7 +89,7 @@ class FractalUI {
}

getVarValue(variable) {
return this.currentFractal.variables[variable].value;
return this.currentVariables[variable].value;
}

onMouseMove(evt) {
Expand All @@ -88,7 +107,7 @@ class FractalUI {
this.mouseX = canvasCenterX;
this.mouseY = canvasCenterY;

const isComboFractal = this.currentFractal instanceof ComboFractal;
const isComboFractal = this.fractalOptions[this.currentFractalIndex] === 'combo';
const zoom = this.getVarValue('zoom');
if (!isComboFractal && !this.isMousePressed) {
if (this.ZOOM_LIMIT != this.ZOOM_MAX && Date.now() < this.latestMouseWheelEvent + 1000) {
Expand All @@ -113,24 +132,27 @@ class FractalUI {
const PAN_INTERVAL = zoom * this.PANNING_SPEED * 0.1;
offsetX += deltaX * PAN_INTERVAL;
offsetY += -1 * deltaY * PAN_INTERVAL;
this.currentFractal.setOptionsAndDraw({ offsetX, offsetY });
this.currentFractalWorker.postMessage({ options: { offsetX, offsetY } });
} else if (this.altPressed) {
blobSize += directionX * 0.01;
blobSize = Math.max(Math.min(blobSize, 2.0), 0);
this.currentFractal.setOptionsAndDraw({ blobSize });
this.currentFractalWorker.postMessage({ options: { blobSize } });
} else if (this.ctrlPressed) {
colorControl += directionX * 0.1;
colorControl = Math.max(Math.min(colorControl, 1000.0), 0);
this.currentFractal.setOptionsAndDraw({ colorControl });
this.currentFractalWorker.postMessage({ options: { colorControl } });
} else if (shiftPressed && zoom < 1.0) {
this.x += directionX * this.x * zoom * 0.005; // x is more sensitive so dampen it more
this.y += directionY * this.y * zoom * 0.01;
this.currentFractal.setOptionsAndDraw({ center: [this.x, this.y] });
this.currentFractalWorker.postMessage({ options: { center: [this.x, this.y] } });
} else if (!shiftPressed && (zoom >= this.ZOOM_LIMIT || isComboFractal)) {
this.x = (canvasCenterX * this.RETINA_RATIO / canvas.width * 2 - 1) / this.MORPHING_SPEED;
this.y = (1 - canvasCenterY * this.RETINA_RATIO / canvas.height * 2) / this.MORPHING_SPEED;
this.currentFractal.setOptionsAndDraw({ center: [this.x, this.y] },
this.mouseX * this.RETINA_RATIO, this.mouseY * this.RETINA_RATIO);
this.currentFractalWorker.postMessage({
options: { center: [this.x, this.y] },
mouseX: this.mouseX * this.RETINA_RATIO,
mouseY: this.mouseY * this.RETINA_RATIO
});
}
});
}
Expand All @@ -149,12 +171,12 @@ class FractalUI {
if (this.altPressed) {
blobSize += -1 * evt.deltaY * 0.001;
blobSize = Math.max(Math.min(blobSize, 2.0), 0);
this.currentFractal.setOptionsAndDraw({ blobSize });
this.currentFractalWorker.postMessage({ options: { blobSize } });
return;
} else if (this.ctrlPressed) {
colorControl += evt.deltaY * 0.1;
colorControl = Math.max(Math.min(colorControl, 1000.0), 0);
this.currentFractal.setOptionsAndDraw({ colorControl });
this.currentFractalWorker.postMessage({ options: { colorControl } });
return;
}

Expand Down Expand Up @@ -184,12 +206,14 @@ class FractalUI {
antiAlias = 2;
}

this.currentFractal.setOptionsAndDraw({
antiAlias,
zoom,
iterations,
offsetX,
offsetY,
this.currentFractalWorker.postMessage({
options: {
antiAlias,
zoom,
iterations,
offsetX,
offsetY,
}
});
});
}
Expand All @@ -212,19 +236,19 @@ class FractalUI {
break;
case 'ArrowLeft':
offsetX -= PAN_INTERVAL;
this.currentFractal.setOptionsAndDraw({ offsetX });
this.currentFractalWorker.postMessage({ options: { offsetX } });
break;
case 'ArrowRight':
offsetX += PAN_INTERVAL;
this.currentFractal.setOptionsAndDraw({ offsetX });
this.currentFractalWorker.postMessage({ options: { offsetX } });
break;
case 'ArrowDown':
offsetY -= PAN_INTERVAL;
this.currentFractal.setOptionsAndDraw({ offsetY });
this.currentFractalWorker.postMessage({ options: { offsetY } });
break;
case 'ArrowUp':
offsetY += PAN_INTERVAL;
this.currentFractal.setOptionsAndDraw({ offsetY });
this.currentFractalWorker.postMessage({ options: { offsetY } });
break;
case ' ':
this.changeFractal();
Expand Down