Skip to content

Instantly share code, notes, and snippets.

@ikr7
Created April 20, 2016 14:53
Show Gist options
  • Save ikr7/6a2b153cf3f907ee7b483929047d18b6 to your computer and use it in GitHub Desktop.
Save ikr7/6a2b153cf3f907ee7b483929047d18b6 to your computer and use it in GitHub Desktop.
WebGL でマンデルブロくん
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>WebGL でマンデルブロくん</title>
<style>
body {
margin:0;
overflow:hidden
}
div {
position: fixed;
width: 100%;
background: rgba(255, 255, 255, 0.2);
color: white;
}
</style>
</head>
<body>
<div>左/右クリックでその辺りにズームイン/アウトするよ  WebGL サポートのある新しいめのブラウザで見てね!</div>
<canvas></canvas>
<script id="fs" type="x-shader/x-fragment">
precision highp float;
uniform vec2 res;
uniform vec2 view_pos;
uniform vec2 view_size;
const int MAX = 512;
float mand (vec2 p) {
vec2 z = vec2(0, 0);
vec2 z1 = vec2(0, 0);
for (int n = 0; n < MAX; n++) {
z1.x = pow(z.x, 2.0) - pow(z.y, 2.0);
z1.y = z.x * z.y * 2.0;
z1 -= p;
if (length(z1.xy) > 2.0) {
return float(n) / float(MAX);
}
z = z1;
}
return 0.0;
}
void main(void) {
vec2 pos = gl_FragCoord.xy * (view_size.xy / res.xy) + view_pos.xy - view_size.xy / 2.0;
float b = mand(pos);
gl_FragColor = vec4(b, b, b, 1);
}
</script>
<script>
var canvas = document.querySelector('canvas');
var W = Math.max(
document.body.clientWidth,
document.body.scrollWidth,
document.documentElement.scrollWidth,
document.documentElement.clientWidth
);
var H = Math.max(
document.body.clientHeight,
document.body.scrollHeight,
document.documentElement.scrollHeight,
document.documentElement.clientHeight
);
canvas.width = W;
canvas.height = H;
var gl = canvas.getContext('experimental-webgl', { preserveDrawingBuffer: true });
var vShaderSource = 'attribute vec2 a_position;void main(){gl_Position = vec4(a_position, 1.0, 1.0);}';
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vShaderSource);
gl.compileShader(vertexShader);
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, document.getElementById('fs').textContent);
gl.compileShader(fragmentShader);
var program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);
var vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0]), gl.STATIC_DRAW);
var a_position = gl.getAttribLocation(program, 'a_position');
gl.vertexAttribPointer(a_position, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(a_position);
var res = gl.getUniformLocation(program, 'res');
var view_pos = gl.getUniformLocation(program, 'view_pos');
var view_size = gl.getUniformLocation(program, 'view_size');
var z = 4;
var view_w;
var view_h;
var view_x = 0;
var view_y = 0;
var update = function (clickX, clickY, zin) {
clickY = H - clickY;
if (zin) {
z *= (7 / 10);
} else {
z *= (10 / 7);
}
view_w = z;
view_h = z * (H / W);
view_x = view_x + clickX * (view_w / W) - view_w / 2;
view_y = view_y + clickY * (view_h / H) - view_h / 2;
gl.uniform2fv(res, new Float32Array([
W,
H
]));
gl.uniform2fv(view_pos, new Float32Array([
view_x,
view_y
]));
gl.uniform2fv(view_size, new Float32Array([
view_w,
view_h
]));
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLES, 0, 6);
};
canvas.addEventListener('click', function (e) {
var x = e.clientX;
var y = e.clientY;
update(x, y, true);
});
canvas.addEventListener('contextmenu', function (e) {
e.preventDefault();
var x = e.clientX;
var y = e.clientY;
update(x, y, false);
});
update(W / 2 + 400, H / 2, true);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment