開発環境 メモ帳
実行環境 Internet Explorer 11
Mozilla Firefox 38


mandelbrot.html
<!doctype html>
<head>
<meta charset="utf-8">
<title>mandelbrot</title>
<script id="vs" type="text/x-vertex">
 
attribute vec2 xy;
attribute vec2 uv;
varying vec2 v_uv;
 
void main(void) {
	v_uv = uv;
	gl_Position = vec4(xy, 0, 1);
}
 
</script>
<script id="fs" type="text/x-fragment">
 
precision mediump float;
varying vec2 v_uv;
uniform float aspect;
uniform float zoom;
uniform vec2 offset;
 
void main(void) {
	vec2 c = (v_uv - 0.5) * vec2(aspect, 1) * zoom + offset;
	vec2 p = vec2(0);
	for (int i = 0; i < 256; i++) {
		p = vec2(p.x * p.x - p.y * p.y, 2.0 * p.x * p.y) + c;
		if (2.0 < length(p)) {
			int n = i - i / 2 * 2;
			gl_FragColor = vec4(0, n, 1, 1);
			return;
		}
	}
	gl_FragColor = vec4(0, 0, 0, 1);
}
 
</script>
<script>
 
function Keyboard() {
	var _keys = [];
	this.isKeyDown = function(keyCode) {
		return _keys[keyCode];
	};
	document.addEventListener("keydown", function(event) {
		_keys[event.keyCode] = true;
	});
	document.addEventListener("keyup", function(event) {
		_keys[event.keyCode] = false;
	});
}
var keyboard = new Keyboard();
 
var gl;	// webgl context
var locZoom;
var locOffset;
 
var zoom = 4;
var x = 0;
var y = 0;
 
onload = function() {
	canvas.width = 640;
	canvas.height = 480;
 
	gl = canvas.getContext("experimental-webgl");
 
	var vShader = createShader("vs");
	var fShader = createShader("fs");
	var program = createProgram(vShader, fShader);
 
	const vertices = [
	//	 x,  y, u, v,
		-1, -1, 0, 0,	// LD
		 1, -1, 1, 0,	// RD
		-1,  1, 0, 1,	// LU
		 1,  1, 1, 1,	// RU
	];
	const stride = 4;
 
	var vertexBuffer = gl.createBuffer();
	gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
	gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
 
	vertexAttribPointer(program, "xy", stride, 0, 2);
	vertexAttribPointer(program, "uv", stride, 2, 2);
 
	gl.uniform1f(gl.getUniformLocation(program, "aspect"), canvas.width / canvas.height);
	locZoom = gl.getUniformLocation(program, "zoom");
	locOffset = gl.getUniformLocation(program, "offset");
 
	draw();
	loop();
};
 
function draw() {
	gl.uniform1f(locZoom, zoom);
	gl.uniform2f(locOffset, x, y);
	gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
	gl.flush();
}
 
function loop() {
	var dx = 0, dy = 0, dz = 0;
 
	if (keyboard.isKeyDown(65)) dx = -1;	// A
	if (keyboard.isKeyDown(68)) dx = +1;	// D
	if (keyboard.isKeyDown(87)) dy = +1;	// W
	if (keyboard.isKeyDown(83)) dy = -1;	// S
	if (keyboard.isKeyDown(38)) dz = -1;	// Up
	if (keyboard.isKeyDown(40)) dz = +1;	// Down
 
	if (dx || dy || dz) {
		x += dx * zoom / 16;
		y += dy * zoom / 16;
		zoom *= 1 + dz / 16;
		draw();
	}
	setTimeout(loop, 1000 / 30);
}
 
function createShader(id) {
	var element = document.getElementById(id);
	if (! element) return;
 
	const types = {
		"text/x-vertex": gl.VERTEX_SHADER,
		"text/x-fragment": gl.FRAGMENT_SHADER,
	};
	var shader = gl.createShader(types[element.type]);
	gl.shaderSource(shader, element.text);
	gl.compileShader(shader);
 
	if (! gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
		alert(gl.getShaderInfoLog(shader));
		return;
	}
	return shader;
}
 
function createProgram(vs, fs) {
	var program = gl.createProgram();
	gl.attachShader(program, vs);
	gl.attachShader(program, fs);
	gl.linkProgram(program);
 
	if (! gl.getProgramParameter(program, gl.LINK_STATUS)) {
		alert(gl.getProgramInfoLog(program));
		return;
	}
	gl.useProgram(program);
	return program;
}
 
function vertexAttribPointer(program, name, stride, offset, size) {
	var index = gl.getAttribLocation(program, name);
	gl.enableVertexAttribArray(index);
	gl.vertexAttribPointer(index, size, gl.FLOAT, false, 4 * stride, 4 * offset);
}
 
</script>
</head>
 
<body>
<canvas id="canvas"></canvas>
<p>[A]:left [D]:right [W]:up [S]:down [Up]:zoom in [Down]:zoom out</p>
</body>
 
最終更新:2015年06月03日 17:21