mirror of
https://github.com/CrispyPin/crispypin.cc.git
synced 2024-11-10 04:00:27 +01:00
add fractal page from old site
This commit is contained in:
parent
a1b500236f
commit
c973cb1aec
7 changed files with 417 additions and 19 deletions
303
docs/fractals/fractals.js
Normal file
303
docs/fractals/fractals.js
Normal file
|
@ -0,0 +1,303 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const gpu = new GPU();
|
||||||
|
|
||||||
|
class FractalTree {
|
||||||
|
constructor(id, iterations, mod) {
|
||||||
|
this.app = document.getElementById(id);
|
||||||
|
this.canvas = this.app.getElementsByTagName("canvas")[0];
|
||||||
|
this.canvas.width = 512;
|
||||||
|
this.canvas.height = 448;
|
||||||
|
this.ctx = this.canvas.getContext("2d");
|
||||||
|
|
||||||
|
this.iterations = iterations;
|
||||||
|
this.mod = mod;
|
||||||
|
this.angle = Math.PI * 0.2;
|
||||||
|
|
||||||
|
this.update = true;
|
||||||
|
|
||||||
|
this.palette = ["#430", "#440", "#450", "#460", "#470", "#480", "#080"];
|
||||||
|
|
||||||
|
this.canvas.addEventListener("mousemove", this.mouseMove.bind(this));
|
||||||
|
this.canvas.addEventListener("mousedown", this.click.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
static vector(l, angle) {
|
||||||
|
return {
|
||||||
|
x: Math.cos(angle) * l,
|
||||||
|
y: Math.sin(angle) * l
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
tree(x, y, length, i, angle) {
|
||||||
|
if (i==0) { return; }
|
||||||
|
|
||||||
|
let dir = FractalTree.vector(length * this.mod, angle + this.angle);
|
||||||
|
|
||||||
|
this.ctx.beginPath();
|
||||||
|
this.ctx.moveTo(x, y);
|
||||||
|
this.ctx.lineWidth = i;
|
||||||
|
this.ctx.strokeStyle = this.palette[this.iterations-i];
|
||||||
|
this.ctx.lineTo(x + dir.x, y - dir.y);
|
||||||
|
this.ctx.stroke();
|
||||||
|
|
||||||
|
this.tree(x + dir.x, y - dir.y, length*this.mod, i-1, angle - this.angle);
|
||||||
|
this.tree(x + dir.x, y - dir.y, length*this.mod, i-1, angle + this.angle);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
||||||
|
this.tree(256, this.canvas.height-64, 128, this.iterations, Math.PI/2 - this.angle);
|
||||||
|
}
|
||||||
|
|
||||||
|
mouseMove(event) {
|
||||||
|
if (this.update) {
|
||||||
|
let x = event.clientX - this.canvas.getBoundingClientRect().left;
|
||||||
|
this.angle = x * Math.PI / this.canvas.width;
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
click(event) {
|
||||||
|
this.update = !this.update;
|
||||||
|
if (this.update) {
|
||||||
|
let x = event.clientX - this.canvas.getBoundingClientRect().left;
|
||||||
|
this.angle = x * Math.PI / this.canvas.width;
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setIter(i) {
|
||||||
|
this.iterations = i;
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
setMod(m) {
|
||||||
|
this.mod = m;
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Mandelbrot {
|
||||||
|
constructor(id, iter=255, width=512, height=512, minX=-2, minY=-1.5, maxX=1, maxY=1.5) {
|
||||||
|
this.app = document.getElementById(id);
|
||||||
|
this.canvas = this.app.getElementsByTagName("canvas")[0];
|
||||||
|
this.canvas.width = width;
|
||||||
|
this.canvas.height = height;
|
||||||
|
this.ctx = this.canvas.getContext("2d");
|
||||||
|
|
||||||
|
this.renderBtn = this.app.getElementsByClassName("controlbar")[0].getElementsByTagName("button")[0];
|
||||||
|
this.renderBtn2 = this.app.getElementsByClassName("controlbar")[0].getElementsByTagName("button")[1];
|
||||||
|
|
||||||
|
this.init(minX, minY, maxX, maxY);
|
||||||
|
this.defaultZoom = [minX, minY, maxX, maxY];
|
||||||
|
this.iter = iter;
|
||||||
|
|
||||||
|
this.palette = [16, 32, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120, 128, 136, 144, 152, 160, 168, 176, 184, 192, 200, 208, 216, 224, 232, 240, 248];
|
||||||
|
|
||||||
|
this.canvas.addEventListener("mousedown", this.zoom.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
zoom(event) {
|
||||||
|
//zoom function
|
||||||
|
let zoomf = 8;
|
||||||
|
let x = this.reScaleX(event.clientX - this.canvas.getBoundingClientRect().left);
|
||||||
|
let y = this.reScaleY(event.clientY - this.canvas.getBoundingClientRect().top);
|
||||||
|
let dx = (this.maxX - this.minX)/zoomf;
|
||||||
|
let dy = (this.maxY - this.minY)/zoomf;
|
||||||
|
this.init(x - dx, y - dy, x + dx, y + dy);
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
reset() {
|
||||||
|
this.init(this.defaultZoom[0], this.defaultZoom[1], this.defaultZoom[2], this.defaultZoom[3]);
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
setIter(x) {
|
||||||
|
this.iter = x;
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
init(minX, minY, maxX, maxY) {
|
||||||
|
this.minX = minX;
|
||||||
|
this.minY = minY;
|
||||||
|
this.maxX = maxX;
|
||||||
|
this.maxY = maxY;
|
||||||
|
|
||||||
|
this.scaleX = (maxX - minX) / this.canvas.width;
|
||||||
|
this.scaleY = (maxY - minY) / this.canvas.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
reScaleX(x) {
|
||||||
|
return x * this.scaleX + this.minX;
|
||||||
|
}
|
||||||
|
|
||||||
|
reScaleY(y) {
|
||||||
|
return y * this.scaleY + this.minY;
|
||||||
|
}
|
||||||
|
|
||||||
|
point(x0, y0) {
|
||||||
|
let x = 0, y = 0;
|
||||||
|
let i = 0;
|
||||||
|
let x2 = 0, y2 = 0;
|
||||||
|
while (x2 + y2 <= 4 && i < this.iter) {
|
||||||
|
y = 2*x*y + y0;
|
||||||
|
x = x2 - y2 + x0;
|
||||||
|
x2 = x*x;
|
||||||
|
y2 = y*y;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
let start = new Date();
|
||||||
|
let result = this.ctx.getImageData(0,0, this.canvas.width, this.canvas.height);
|
||||||
|
let px = 0;
|
||||||
|
let yp;
|
||||||
|
for (let yPos = 0; yPos < this.canvas.height; yPos++) {
|
||||||
|
yp = this.reScaleY(yPos);
|
||||||
|
for (let xPos = 0; xPos < this.canvas.width; xPos++) {
|
||||||
|
let i = this.point(this.reScaleX(xPos), yp);
|
||||||
|
if (i != this.iter) {
|
||||||
|
let col = this.palette[Math.min(i, this.palette.length-1)]
|
||||||
|
result.data[px] = 0;
|
||||||
|
result.data[px+1] = col;
|
||||||
|
result.data[px+2] = col;
|
||||||
|
} else {
|
||||||
|
result.data[px] = 0;
|
||||||
|
result.data[px+1] = 0;
|
||||||
|
result.data[px+2] = 0;
|
||||||
|
}
|
||||||
|
result.data[px+3] = 255;
|
||||||
|
px += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.ctx.putImageData(result, 0, 0);
|
||||||
|
this.renderBtn.textContent = `Reset ${new Date() - start}ms`;
|
||||||
|
}
|
||||||
|
|
||||||
|
gpuRender() {
|
||||||
|
let start = new Date();
|
||||||
|
|
||||||
|
let kernel = gpu.createKernel(function(scaleX, scaleY, minX, minY, iter) {
|
||||||
|
let x0 = this.thread.x * scaleX + minX;
|
||||||
|
let y0 = this.thread.y * scaleY + minY;
|
||||||
|
let x = 0, y = 0;
|
||||||
|
let i = 0;
|
||||||
|
let x2 = 0, y2 = 0;
|
||||||
|
|
||||||
|
while (x2 + y2 < 4 && i < iter) {
|
||||||
|
y = 2*x*y + y0;
|
||||||
|
x = x2 - y2 + x0;
|
||||||
|
x2 = x*x;
|
||||||
|
y2 = y*y;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if (i != iter) {
|
||||||
|
this.color(0, i/iter, i/iter, 1);
|
||||||
|
this.color(0, i/255, i/255, 1);//i is 0?
|
||||||
|
this.color(this.thread.x/512, this.thread.y/512, i/255);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
this.color(1, 0, 0, 1);
|
||||||
|
}
|
||||||
|
//this.color(this.thread.x/512, this.thread.y/512, i/256);
|
||||||
|
//this.color(x0, y0, 0, 1)
|
||||||
|
},
|
||||||
|
{output:[512, 512], graphical:true, loopMaxIterations: this.iter});
|
||||||
|
|
||||||
|
kernel(this.scaleX, this.scaleY, this.minX, this.minY, this.iter);
|
||||||
|
|
||||||
|
//let kernel = gpu.createKernel(function() {this.color(0, 0, 1);}).setOutput([512, 512]).setGraphical(true);
|
||||||
|
//kernel();
|
||||||
|
|
||||||
|
let result = kernel.getPixels();
|
||||||
|
this.ctx.putImageData(new ImageData(result, 512, 512), 0, 0);
|
||||||
|
this.renderBtn.textContent = `Reset ${new Date() - start}ms`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Multibrot extends Mandelbrot {
|
||||||
|
constructor(id, power, iter=255, width=512, height=512, minX=-2, minY=-2, maxX=2, maxY=2) {
|
||||||
|
super(id, iter, width, height, minX, minY, maxX, maxY);
|
||||||
|
this.power = power;
|
||||||
|
}
|
||||||
|
|
||||||
|
point(x0, y0) {
|
||||||
|
let x = 0, y = 0;
|
||||||
|
let i = 0;
|
||||||
|
let xtmp, xxyyn, atn;
|
||||||
|
let n2 = this.power/2;
|
||||||
|
while (x*x + y*y <= 4 && i < this.iter) {
|
||||||
|
xxyyn = (x*x+y*y)**(n2);
|
||||||
|
atn = this.power*Math.atan2(y, x);
|
||||||
|
xtmp = xxyyn * Math.cos(atn) + x0;
|
||||||
|
y = xxyyn * Math.sin(atn) + y0;
|
||||||
|
x = xtmp;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
setPower(x) {
|
||||||
|
this.power = x;
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Julia extends Mandelbrot {
|
||||||
|
constructor(id, iter=255, width=512, height=512, minX=-2, minY=-2, maxX=2, maxY=2) {
|
||||||
|
super(id, iter, width, height, minX, minY, maxX, maxY);
|
||||||
|
this.cx = this.reScaleX(width/2);
|
||||||
|
this.cy = this.reScaleY(height/3.2);
|
||||||
|
|
||||||
|
this.update = true;
|
||||||
|
|
||||||
|
this.canvas.removeEventListener("mousedown", this.zoom);
|
||||||
|
|
||||||
|
this.canvas.addEventListener("mousedown", this.click.bind(this));
|
||||||
|
this.canvas.addEventListener("mousemove", this.mouseMove.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
click(event) {
|
||||||
|
this.update = !this.update;
|
||||||
|
this.mouseMove(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
zoom() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mouseMove(event) {
|
||||||
|
if (this.update) {
|
||||||
|
this.cx = this.reScaleX(event.clientX - this.canvas.getBoundingClientRect().left);
|
||||||
|
this.cy = this.reScaleY(event.clientY - this.canvas.getBoundingClientRect().top);
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
point(zx, zy) {
|
||||||
|
let i = 0, xtmp = 0;
|
||||||
|
let zx2 = zx*zx, zy2 = zy*zy;
|
||||||
|
while (zx2 + zy2 < 4 && i < this.iter) {
|
||||||
|
xtmp = zx2 - zy2;
|
||||||
|
zy = 2*zx*zy + this.cy;
|
||||||
|
zx = xtmp + this.cx;
|
||||||
|
zx2 = zx*zx;
|
||||||
|
zy2 = zy*zy;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let fractalTree = new FractalTree("fractal-tree", 12, 0.75);
|
||||||
|
let mandelbrot = new Mandelbrot("mandelbrot");
|
||||||
|
let multibrot = new Multibrot("multibrot", 4);
|
||||||
|
let juliaSet = new Julia("julia-set", 64, 512, 512);
|
||||||
|
|
||||||
|
fractalTree.render();
|
||||||
|
mandelbrot.render();
|
||||||
|
juliaSet.render();
|
|
@ -22,7 +22,47 @@
|
||||||
</nav>
|
</nav>
|
||||||
<main>
|
<main>
|
||||||
<h1>Fractals</h1>
|
<h1>Fractals</h1>
|
||||||
<p>this is real content i promise</p>
|
<h2>Fractal tree</h2>
|
||||||
|
<p>This is a fractal tree.</p>
|
||||||
|
<p>The tree splits into two parts, with an angle defined by the cursor's x positon. The number of iterations is defined by the first input field (which defaults to 12). Each branch is slightly smaller than its parent, as defined by the second input field. Click the canvas to freeze the image at any moment.</p>
|
||||||
|
<div class="demo-render" id="fractal-tree">
|
||||||
|
<canvas></canvas>
|
||||||
|
<div class="controlbar">
|
||||||
|
<input type="number" min=6 max=15 value=12 onchange="fractalTree.setIter(value)">
|
||||||
|
<input type="number" min=0.65 max=1 step=0.025 value=0.75 onchange="fractalTree.setMod(value)">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<h2>Mandelbrot</h2>
|
||||||
|
<p>The mandelbrot set is defined as the set of complex numbers for which a specific function (<i>F<sub>c</sub>(z) = z<sup>2</sup> + c</i>) stays within distance 2 from the origin when iterated from z=0.</p>
|
||||||
|
<div class="demo-render" id="mandelbrot">
|
||||||
|
<canvas></canvas>
|
||||||
|
<div class="controlbar">
|
||||||
|
<button type="button" onclick="mandelbrot.reset()">Reset</button>
|
||||||
|
<button type="button" onclick="mandelbrot.gpuRender()">GPU</button>
|
||||||
|
<input type="number" min=1 max=1000 value=256 onchange="mandelbrot.setIter(value)">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<h2>Multibrot set</h2>
|
||||||
|
<p>A multibrot set is a variant of the mandelbrot set where the functions exponent can be anything. If the exponent (third input field) is 2, you get the regular mandelbrot set.</p>
|
||||||
|
<div class="demo-render" id="multibrot">
|
||||||
|
<canvas></canvas>
|
||||||
|
<div class="controlbar">
|
||||||
|
<button type="button" onclick="multibrot.reset()">Reset</button>
|
||||||
|
<input type="number" min=1 max=1000 value=256 onchange="multibrot.setIter(value)">
|
||||||
|
<input type="number" min=0 max=32 step=0.1 value=4 onchange="multibrot.setPower(value)">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<h2>Julia set</h2>
|
||||||
|
<p>The julia set is similar to the mandelbrot set.</p>
|
||||||
|
<div class="demo-render" id="julia-set">
|
||||||
|
<canvas></canvas>
|
||||||
|
<div class="controlbar">
|
||||||
|
<button type="button" onclick="juliaSet.reset()">Reset</button>
|
||||||
|
<input type="number" min=8 max=1000 value=80 step=8 onchange="juliaSet.setIter(value)">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script src="/libraries/gpu-browser.min.js"></script>
|
||||||
|
<script src="fractals.js"></script>
|
||||||
</main>
|
</main>
|
||||||
<footer>
|
<footer>
|
||||||
<p>crispypin.cc</p>
|
<p>crispypin.cc</p>
|
||||||
|
|
14
docs/libraries/gpu-browser.min.js
vendored
Normal file
14
docs/libraries/gpu-browser.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
|
@ -52,17 +52,22 @@ header h1 {
|
||||||
|
|
||||||
footer {
|
footer {
|
||||||
grid-column: 1 / -1;
|
grid-column: 1 / -1;
|
||||||
margin: 25px;
|
margin-top: 5px;
|
||||||
|
margin-bottom: 10px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
footer p {
|
||||||
|
margin: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
main {
|
main {
|
||||||
padding: 0 20px;
|
padding: 0 20px;
|
||||||
grid-column: 2 / -2;
|
grid-column: 2 / -2;
|
||||||
background-color: #282828;
|
background-color: #282828;
|
||||||
}
|
}
|
||||||
|
|
||||||
.render {
|
.demo-render {
|
||||||
margin: 20px;
|
margin: 20px;
|
||||||
width: -webkit-min-content;
|
width: -webkit-min-content;
|
||||||
width: -moz-min-content;
|
width: -moz-min-content;
|
||||||
|
@ -148,6 +153,7 @@ main {
|
||||||
}
|
}
|
||||||
|
|
||||||
.clickable, nav li, .controlbar button, .controlbar input, .scroll-reset {
|
.clickable, nav li, .controlbar button, .controlbar input, .scroll-reset {
|
||||||
|
border-radius: 4px;
|
||||||
background-color: #4a4;
|
background-color: #4a4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,12 +178,7 @@ main {
|
||||||
bottom: 20px;
|
bottom: 20px;
|
||||||
width: 40px;
|
width: 40px;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
border-radius: 25%;
|
|
||||||
background-image: url("uparrow.png");
|
background-image: url("uparrow.png");
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.img-right {
|
|
||||||
float: right;
|
|
||||||
}
|
|
||||||
/*# sourceMappingURL=style.css.map */
|
/*# sourceMappingURL=style.css.map */
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"version": 3,
|
"version": 3,
|
||||||
"mappings": "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",
|
"mappings": "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",
|
||||||
"sources": [
|
"sources": [
|
||||||
"style.scss"
|
"style.scss"
|
||||||
],
|
],
|
||||||
|
|
|
@ -59,8 +59,12 @@ header {
|
||||||
|
|
||||||
footer {
|
footer {
|
||||||
grid-column: 1 / -1;
|
grid-column: 1 / -1;
|
||||||
margin: 25px;
|
margin-top: 5px;
|
||||||
|
margin-bottom: 10px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
p {
|
||||||
|
margin: 5px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
main {
|
main {
|
||||||
|
@ -69,7 +73,7 @@ main {
|
||||||
background-color: $main-page-bg;
|
background-color: $main-page-bg;
|
||||||
}
|
}
|
||||||
|
|
||||||
.render {
|
.demo-render {
|
||||||
margin: 20px;
|
margin: 20px;
|
||||||
width: min-content;
|
width: min-content;
|
||||||
background-color: #000;
|
background-color: #000;
|
||||||
|
@ -84,7 +88,7 @@ main {
|
||||||
justify-content: space-evenly;
|
justify-content: space-evenly;
|
||||||
align-content: stretch;
|
align-content: stretch;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
|
||||||
button, input {
|
button, input {
|
||||||
@extend .clickable;
|
@extend .clickable;
|
||||||
padding: 4px 6px;
|
padding: 4px 6px;
|
||||||
|
@ -105,7 +109,7 @@ main {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 2px;
|
margin: 2px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
&::-webkit-slider-thumb {
|
&::-webkit-slider-thumb {
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
appearance: none;
|
appearance: none;
|
||||||
|
@ -141,6 +145,7 @@ main {
|
||||||
}
|
}
|
||||||
|
|
||||||
.clickable {
|
.clickable {
|
||||||
|
border-radius: 4px;
|
||||||
background-color: $main-item;
|
background-color: $main-item;
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: $main-item-hover;
|
background-color: $main-item-hover;
|
||||||
|
@ -163,11 +168,6 @@ main {
|
||||||
bottom: 20px;
|
bottom: 20px;
|
||||||
width: 40px;
|
width: 40px;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
border-radius: 25%;
|
|
||||||
background-image: url("uparrow.png");
|
background-image: url("uparrow.png");
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.img-right {
|
|
||||||
float: right;
|
|
||||||
}
|
|
|
@ -11,7 +11,47 @@
|
||||||
<include header.html/>
|
<include header.html/>
|
||||||
<main>
|
<main>
|
||||||
<h1>Fractals</h1>
|
<h1>Fractals</h1>
|
||||||
<p>this is real content i promise</p>
|
<h2>Fractal tree</h2>
|
||||||
|
<p>This is a fractal tree.</p>
|
||||||
|
<p>The tree splits into two parts, with an angle defined by the cursor's x positon. The number of iterations is defined by the first input field (which defaults to 12). Each branch is slightly smaller than its parent, as defined by the second input field. Click the canvas to freeze the image at any moment.</p>
|
||||||
|
<div class="demo-render" id="fractal-tree">
|
||||||
|
<canvas></canvas>
|
||||||
|
<div class="controlbar">
|
||||||
|
<input type="number" min=6 max=15 value=12 onchange="fractalTree.setIter(value)">
|
||||||
|
<input type="number" min=0.65 max=1 step=0.025 value=0.75 onchange="fractalTree.setMod(value)">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<h2>Mandelbrot</h2>
|
||||||
|
<p>The mandelbrot set is defined as the set of complex numbers for which a specific function (<i>F<sub>c</sub>(z) = z<sup>2</sup> + c</i>) stays within distance 2 from the origin when iterated from z=0.</p>
|
||||||
|
<div class="demo-render" id="mandelbrot">
|
||||||
|
<canvas></canvas>
|
||||||
|
<div class="controlbar">
|
||||||
|
<button type="button" onclick="mandelbrot.reset()">Reset</button>
|
||||||
|
<button type="button" onclick="mandelbrot.gpuRender()">GPU</button>
|
||||||
|
<input type="number" min=1 max=1000 value=256 onchange="mandelbrot.setIter(value)">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<h2>Multibrot set</h2>
|
||||||
|
<p>A multibrot set is a variant of the mandelbrot set where the functions exponent can be anything. If the exponent (third input field) is 2, you get the regular mandelbrot set.</p>
|
||||||
|
<div class="demo-render" id="multibrot">
|
||||||
|
<canvas></canvas>
|
||||||
|
<div class="controlbar">
|
||||||
|
<button type="button" onclick="multibrot.reset()">Reset</button>
|
||||||
|
<input type="number" min=1 max=1000 value=256 onchange="multibrot.setIter(value)">
|
||||||
|
<input type="number" min=0 max=32 step=0.1 value=4 onchange="multibrot.setPower(value)">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<h2>Julia set</h2>
|
||||||
|
<p>The julia set is similar to the mandelbrot set.</p>
|
||||||
|
<div class="demo-render" id="julia-set">
|
||||||
|
<canvas></canvas>
|
||||||
|
<div class="controlbar">
|
||||||
|
<button type="button" onclick="juliaSet.reset()">Reset</button>
|
||||||
|
<input type="number" min=8 max=1000 value=80 step=8 onchange="juliaSet.setIter(value)">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script src="/libraries/gpu-browser.min.js"></script>
|
||||||
|
<script src="fractals.js"></script>
|
||||||
</main>
|
</main>
|
||||||
<include footer.html/>
|
<include footer.html/>
|
||||||
</body>
|
</body>
|
||||||
|
|
Loading…
Reference in a new issue