Skip to content

Instantly share code, notes, and snippets.

@equalent
Created September 15, 2020 14:18
Show Gist options
  • Select an option

  • Save equalent/d9f8d727a502292cf47b7af0eb0e07fc to your computer and use it in GitHub Desktop.

Select an option

Save equalent/d9f8d727a502292cf47b7af0eb0e07fc to your computer and use it in GitHub Desktop.
Simple JS + WebGL Mandelbrot set implementation
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MANDELBROT</title>
</head>
<body style="font-family: sans-serif;">
<canvas id="cnv" style="width: 100%; height: 100%; position: fixed; top: 0; left: 0;"></canvas>
<div style="position: fixed; z-index: 100; top: 20px; left: 20px; color: white; background-color: rgba(100, 100, 100, 0.2);">
<h3>Mandelbrot set</h3>
<label for="volume">Iteration count</label>
<input type="range" id="inIter" min="5" max="500" value="100">
</div>
<script id="vertexShader" type="x-shader/x-vertex">
attribute vec2 vPos;
attribute vec2 vUv;
varying highp vec2 uv;
void main(void){
gl_Position = vec4(vPos, 0.0, 1.0);
uv = vUv;
}
</script>
<script id="fragShader" type="x-shader/x-fragment">
varying highp vec2 uv;
uniform int inIter;
highp float cmulRe(highp float Re1, highp float Im1, highp float Re2, highp float Im2){
return (Re1 * Re2) - (Im1 * Im2);
}
highp float cmulIm(highp float Re1, highp float Im1, highp float Re2, highp float Im2){
return (Re1 * Im2) + (Im1 * Re2);
}
highp float cabs(highp float Re, highp float Im){
return sqrt(Re*Re + Im*Im);
}
highp float getGray(highp float cRe, highp float cIm){
highp float zRe, zIm, tRe, tIm;
zRe = 0.0;
zIm = 0.0;
tRe = 0.0;
tIm = 0.0;
for(int i = 0; i < 500; i++){
if(i >= inIter)break;
if(cabs(zRe, zIm) > 2.0){
return (float(i) / float(inIter));
}
tRe = zRe;
tIm = zIm;
zRe = cmulRe(tRe, tIm, tRe, tIm);
zIm = cmulIm(tRe, tIm, tRe, tIm);
zRe += cRe;
zIm += cIm;
}
return 1.0;
}
void main(void){
highp float gray = getGray(uv.x, uv.y);
gl_FragColor = vec4(gray, gray, gray, 1.0);
}
</script>
<script>
var ibo, vbo;
var ps, fs, prog;
var posId, uvId;
var iterUid;
let elInIter = document.getElementById("inIter");
function update(cnv, gl) {
cnv.width = window.innerWidth;
cnv.height = window.innerHeight;
gl.viewport(0, 0, cnv.width, cnv.height);
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.viewport(0, 0, cnv.width, cnv.height);
gl.uniform1i(iterUid, parseInt(elInIter.value));
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
}
function main(cnv) {
let gl = cnv.getContext('webgl');
console.log(gl);
var vertices = [
-1, -1, -2, -1.1,
-1, 1, -2, 1.1,
1, 1, 1, 1.1,
1, -1, 1, -1.1,
];
var indices = [
0, 1, 2, 0, 2, 3
];
vbo = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
ibo = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ibo);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
let vsCode = document.getElementById('vertexShader').innerHTML;
vs = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vs, vsCode);
gl.compileShader(vs);
let fsCode = document.getElementById('fragShader').innerHTML;
fs = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fs, fsCode);
gl.compileShader(fs);
console.log(gl.getShaderInfoLog(fs));
prog = gl.createProgram();
gl.attachShader(prog, vs);
gl.attachShader(prog, fs);
gl.linkProgram(prog);
console.log(gl.getProgramInfoLog(prog));
gl.useProgram(prog);
posId = gl.getAttribLocation(prog, 'vPos');
uvId = gl.getAttribLocation(prog, 'vUv');
iterUid = gl.getUniformLocation(prog, 'inIter');
gl.vertexAttribPointer(posId, 2, gl.FLOAT, false, 16, 0);
gl.vertexAttribPointer(uvId, 2, gl.FLOAT, false, 16, 8);
gl.enableVertexAttribArray(posId);
gl.enableVertexAttribArray(uvId);
gl.enable(gl.DEPTH_TEST);
setInterval(() => { update(cnv, gl); }, 50);
}
window.addEventListener("load", () => {
let cnv = document.getElementById('cnv');
main(cnv);
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment