Skip to content

Instantly share code, notes, and snippets.

@hdf
Created April 24, 2015 10:41
Show Gist options
  • Save hdf/916f19395a19ce48339e to your computer and use it in GitHub Desktop.
Save hdf/916f19395a19ce48339e to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Mandelbrot with GLSL</title>
<style>
html, body {margin: 0; padding: 0;}
canvas {position: absolute; width: 100%; height: 100%;}
</style>
</head>
<body>
<canvas id="mandel"></canvas>
<script id="vertexShader" type="x-shader/x-vertex">
attribute vec2 vertexPos;
uniform float aspectRatio;
varying vec2 pixelPos;
uniform float zoom;
uniform float movx;
uniform float movy;
void main() {
pixelPos = vec2(vertexPos.x / zoom + movx - 0.5, vertexPos.y / aspectRatio / zoom - movy);
gl_Position = vec4(vertexPos, 0.0, 1.0);
}
</script>
<script id="fragmentShader" type="x-shader/x-fragment">
precision highp float;
varying vec2 pixelPos;
uniform int iter;
void main() {
vec2 z = pixelPos;
for (int i = 0; i < 1024; i++) {
z = pixelPos + vec2(
z.x*z.x - z.y*z.y,
2.0*z.x*z.y
);
//gl_FragColor = vec4(0.0, 0.0, 0.0, 0.3);
//if (length(z) > 1.5) {
gl_FragColor = vec4(z, 1.0/abs(length(z)+0.5), 0.7);
//}
if (i >= iter) break;
}
}
</script>
<script>
var width = window.innerWidth - window.pageXOffset;
var height = window.innerHeight - window.pageYOffset;
var zoom = 0.3, movx = 0.275, movy = 0.005, iter = 128;
// Coloring:
// http://nuclear.mutantstargoat.com/articles/sdr_fract/
var canvas = document.getElementById('mandel');
canvas.width = width;
canvas.height = height;
var gl = canvas.getContext('webgl');
//gl.viewportWidth = canvas.width;
//gl.viewportHeight = canvas.height;
//gl.viewport(0, 0, canvas.width, canvas.height);
//gl.clearColor(0.0, 0.0, 0.0, 1.0);
//gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT);
var vertexShader_src = document.getElementById('vertexShader').firstChild.textContent.trim();
var fragmentShader_src = document.getElementById('fragmentShader').firstChild.textContent.trim();
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(vertexShader, vertexShader_src);
gl.shaderSource(fragmentShader, fragmentShader_src);
gl.compileShader(vertexShader);
gl.compileShader(fragmentShader);
var program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);
function setShaderValues() {
gl.uniform1f(gl.getUniformLocation(program, 'aspectRatio'), canvas.clientWidth / canvas.clientHeight);
gl.uniform1f(gl.getUniformLocation(program, 'zoom'), zoom);
gl.uniform1i(gl.getUniformLocation(program, 'iter'), iter);
gl.uniform1f(gl.getUniformLocation(program, 'movx'), movx);
gl.uniform1f(gl.getUniformLocation(program, 'movy'), movy);
}
setShaderValues();
var vertexPositionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexPositionBuffer);
var vertices = [
1.0, 1.0,
-1.0, 1.0,
1.0, -1.0,
-1.0, -1.0
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
var vertPos = gl.getAttribLocation(program, "vertexPos");
gl.enableVertexAttribArray(vertPos);
gl.vertexAttribPointer(vertPos, 2, gl.FLOAT, false, 0, 0);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
canvas.onwheel = function(e) {
if (e.deltaY > 0)
zoom -= zoom / 2;
else {
movx += ((1 / this.clientWidth) * (e.clientX) - 0.5) / zoom;
if (movx > 3.5) movx = 3.5;
if (movx < -3) movx = -3;
movy += ((1 / this.clientHeight) * (e.clientY) - 0.5) / zoom;
if (movy > 1.25) movy = 1.25;
if (movy < -1.25) movy = -1.25;
zoom += zoom;
}
if (zoom < 0.3) zoom = 0.3;
//var tmp = Math.ceil(Math.log2(zoom))*5;
//iter = (tmp > 1)?(tmp+20):20;
}
</script>
<script type="text/javascript" src="https://raw.githubusercontent.com/mrdoob/stats.js/master/build/stats.min.js"></script>
<script>
var stats = new Stats();
stats.setMode(0); // 0: fps, 1: ms
stats.domElement.style.position = 'absolute';
stats.domElement.style.right = '0px';
stats.domElement.style.top = '0px';
document.body.appendChild( stats.domElement );
var update = function(delta) {
stats.begin();
setShaderValues();
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
stats.end();
requestAnimationFrame(update);
};
requestAnimationFrame(update);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment