Skip to content

Instantly share code, notes, and snippets.

@lubosz
Last active October 14, 2016 15:42
Show Gist options
  • Save lubosz/6a7b87da400d5bc0f41c to your computer and use it in GitHub Desktop.
Save lubosz/6a7b87da400d5bc0f41c to your computer and use it in GitHub Desktop.
Simple Mandelbrot Set WebGL
<html>
<head>
<title>Mandelbrot WebGL</title>
<style>
body, canvas {
margin: 0px;
width: 100%;
height: 100%;
overflow: hidden;
}
</style>
<script src="https://www.khronos.org/registry/webgl/sdk/demos/common/webgl-utils.js"></script>
<script src="https://www.khronos.org/registry/webgl/sdk/demos/webkit/resources/J3DI.js"> </script>
<script src="https://www.khronos.org/registry/webgl/sdk/demos/webkit/resources/J3DIMath.js"></script>
<script id="vshader" type="x-shader/x-vertex">
uniform mat4 projection_matrix;
attribute vec4 position;
varying vec2 fractal_position;
void main() {
gl_Position = projection_matrix * position;
fractal_position = vec2(-position.y, position.x);
fractal_position -= vec2(0.50, 0);
fractal_position *= 1.5;
}
</script>
<script id="fshader" type="x-shader/x-fragment">
precision highp float;
uniform float time;
varying vec2 fractal_position;
const vec4 K = vec4(1.0, 0.66, 0.33, 3.0);
vec4 hsv_to_rgb(float hue, float saturation, float value) {
vec4 p = abs(fract(vec4(hue) + K) * 6.0 - K.wwww);
return vec4(value * mix(K.xxx, clamp(p.xyz - K.xxx, 0.0, 1.0), saturation), 1.0);
}
vec4 i_to_rgb(int i) {
float hue = float(i) / 100.0 + sin(time);
return hsv_to_rgb(hue, 0.5, 0.8);
}
vec2 pow_2_complex(vec2 c) {
//return vec2(c.x*c.x - c.y*c.y, sin(time) * 2.0 * c.x * c.y);
return vec2(c.x*c.x - c.y*c.y, 2.0 * c.x * c.y);
}
vec2 mandelbrot(vec2 c, vec2 c0) {
return pow_2_complex(c) + c0;
}
vec4 iterate_pixel(vec2 position) {
vec2 c = vec2(0);
for (int i=0; i < 100; i++) {
if (c.x*c.x + c.y*c.y > 2.0*2.0) {
return i_to_rgb(i);
}
c = mandelbrot(c, position);
}
return vec4(0, 0, 0, 1);
}
void main() {
gl_FragColor = iterate_pixel(fractal_position);
}
</script>
<script>
var g = {};
var gl;
var canvas;
function init() {
gl = initWebGL("mandelbrot");
if (!gl) return;
g.program = simpleSetup(
gl,
"vshader", "fshader",
["position"],
[ 0, 0, 0, 1 ], 10000);
g.box = makeBox(gl);
g.projection_matrix_loc =
gl.getUniformLocation(g.program, "projection_matrix");
gl.enableVertexAttribArray(0);
gl.bindBuffer(gl.ARRAY_BUFFER, g.box.vertexObject);
gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, g.box.indexObject);
canvas = document.getElementById("mandelbrot");
g.starttime = Date.now();
reshape();
window.onresize = reshape;
draw();
}
function reshape() {
canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;
gl.viewport(0, 0, canvas.clientWidth, canvas.clientHeight);
g.projection_matrix = new J3DIMatrix4();
var aspect = canvas.clientWidth / canvas.clientHeight;
g.projection_matrix.ortho(-1.0, 1.0,
-1.0 / aspect, 1.0 / aspect,
0.1, 1000.0);
}
function draw() {
gl.clear(gl.COLOR_BUFFER_BIT);
gl.uniform1f(gl.getUniformLocation(g.program,
"time"), (Date.now() - g.starttime) / 5000.0);
g.projection_matrix.setUniform(gl, g.projection_matrix_loc, false);
gl.drawElements(gl.TRIANGLES, g.box.numIndices, gl.UNSIGNED_BYTE, 0);
window.requestAnimFrame(draw, canvas);
}
</script>
</head>
<body onload="init()">
<canvas id="mandelbrot"></canvas>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment