Last active
October 14, 2016 15:42
-
-
Save lubosz/6a7b87da400d5bc0f41c to your computer and use it in GitHub Desktop.
Simple Mandelbrot Set WebGL
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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