開発環境 メモ帳
実行環境 Microsoft Edge


cube2.html
<!doctype html>
<head>
<title>cube2</title>
<script src="minMatrix.js"></script>
</head>
 
<body>
<canvas id="canvas" width="640" height="480"></canvas>
<div id="msg"></div>
<script id="vs" type="text/x-vertex">
 
// 頂点シェイダー
attribute vec3 position;
attribute vec3 normal;
attribute vec4 color;
uniform mat4 mvpMatrix;
uniform mat4 invMatrix;
uniform vec3 lightDirection;
uniform vec4 ambientColor;
varying vec4 vColor;
 
void main(void) {
	vec3 invLight = normalize(invMatrix * vec4(lightDirection, 0.0)).xyz;
	float diffuse = clamp(dot(normal, invLight), 0.0, 1.0);
	vColor = color * vec4(vec3(diffuse), 1.0) + ambientColor;
	gl_Position = mvpMatrix * vec4(position, 1.0);
}
 
</script>
<script id="fs" type="text/x-fragment">
 
// 断片シェイダー
precision mediump float;
 
varying vec4 vColor;
 
void main(void) {
	gl_FragColor = vColor;
}
 
</script>
<script>
 
var gl;	// webgl context
var mat = new matIV();
var pMatrix = mat.create();	// perspective
var indexCount;
var loc = {};
var angle = 0;
 
var fps;
var fpsCount;
var secSave;
 
onload = function() {
	gl = canvas.getContext("experimental-webgl");
 
	var vShader = createShader("vs");
	var fShader = createShader("fs");
	var program = createProgram(vShader, fShader);
	gl.useProgram(program);
 
	var model = cube();
 
	var vbo = createVbo(model.positions);
	setAttribute(program, "position", vbo, 3);
	var vbo = createVbo(model.normals);
	setAttribute(program, "normal", vbo, 3);
	var vbo = createVbo(model.colors);
	setAttribute(program, "color", vbo, 4);
 
	var ibo = gl.createBuffer();
	gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ibo);
	gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Int16Array(model.indices), gl.STATIC_DRAW);
	indexCount = model.indices.length;
 
	loc.mvpMatrix = gl.getUniformLocation(program, "mvpMatrix");
	loc.invMatrix = gl.getUniformLocation(program, "invMatrix");
	loc.lightDirection = gl.getUniformLocation(program, "lightDirection");
	loc.ambientColor = gl.getUniformLocation(program, "ambientColor");
 
	gl.enable(gl.CULL_FACE);
	gl.frontFace(gl.CW);
	gl.enable(gl.DEPTH_TEST);
	gl.depthFunc(gl.LEQUAL);
 
	var ambientColor = [0.1, 0.1, 0.1, 1.0];
	gl.uniform4fv(loc.ambientColor, ambientColor);
	mat.perspective(45, canvas.width / canvas.height, 0.1, 10, pMatrix);
	draw();
};
 
function draw() {
	var sec = (new Date()).getSeconds();
	if (secSave != sec) {
		fps = fpsCount;
		fpsCount = 0;
		secSave = sec;
	}
	fpsCount++;
	msg.innerHTML = "fps=" + fps + " angle=" + angle;
 
	gl.clearColor(0x64 / 0xff, 0x95 / 0xff, 0xed / 0xff, 1.0);
	gl.clearDepth(1.0);
	gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
 
	// camera
	var vMatrix = mat.create();
	var vpMatrix = mat.create();
	var mvpMatrix = mat.create();
	mat.lookAt([0, 1, 3], [0, 0, 0], [0, 1, 0], vMatrix);
	mat.multiply(pMatrix, vMatrix, vpMatrix);
 
	// light
	var lightDirection = [1, 1, 1];
	gl.uniform3fv(loc.lightDirection, lightDirection);
 
	// model
	angle = (angle + 2) % 360;
	var rad = angle * Math.PI / 180;
	var mMatrix = mat.identity(mat.create());
	mat.rotate(mMatrix, rad, [0, 1, 0], mMatrix);
	var invMatrix = mat.create();
	mat.inverse(mMatrix, invMatrix);
 
	mat.multiply(vpMatrix, mMatrix, mvpMatrix);
	gl.uniformMatrix4fv(loc.mvpMatrix, false, mvpMatrix);
	gl.uniformMatrix4fv(loc.invMatrix, false, invMatrix);
	gl.drawElements(gl.TRIANGLES, indexCount, gl.UNSIGNED_SHORT, 0);
 
	gl.flush();
	setTimeout(draw, 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;
	}
	return program;
}
 
function createVbo(data) {
	var vbo = gl.createBuffer();
	gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
	gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data), gl.STATIC_DRAW);
	gl.bindBuffer(gl.ARRAY_BUFFER, null);
	return vbo;
}
 
function setAttribute(program, name, vbo, stride) {
	var location = gl.getAttribLocation(program, name);
	gl.enableVertexAttribArray(location);
	gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
	gl.vertexAttribPointer(location, stride, gl.FLOAT, false, 0, 0);
	gl.bindBuffer(gl.ARRAY_BUFFER, null);
}
 
function cube() {
	var x = 0.5;
	var positions = [
		 x, -x,  x,	// x+
		 x,  x,  x,
		 x,  x, -x,
		 x, -x, -x,
 
		 x,  x, -x,	// y+
		 x,  x,  x,
		-x,  x,  x,
		-x,  x, -x,
 
		-x,  x,  x,	// z+
		 x,  x,  x,
		 x, -x,  x,
		-x, -x,  x,
 
		-x,  x,  x,	// x-
		-x, -x,  x,
		-x, -x, -x,
		-x,  x, -x,
 
		 x, -x,  x,	// y-
		 x, -x, -x,
		-x, -x, -x,
		-x, -x,  x,
 
		 x,  x, -x,	// z-
		-x,  x, -x,
		-x, -x, -x,
		 x, -x, -x,
	];
 
	var normals = [];
	var colors = [];
	for (var i = 0; i < 4; i++) {		// x+
		normals.push(1, 0, 0);
		colors.push(1, 0, 0, 1);
	}
	for (var i = 0; i < 4; i++) {		// y+
		normals.push(0, 1, 0);
		colors.push(0, 1, 0, 1);
	}
	for (var i = 0; i < 4; i++) {		// z+
		normals.push(0, 0, 1);
		colors.push(0, 0, 1, 1);
	}
	for (var i = 0; i < 4; i++) {		// x-
		normals.push(-1, 0, 0);
		colors.push(0, 1, 1, 1);
	}
	for (var i = 0; i < 4; i++) {		// y-
		normals.push(0, -1, 0);
		colors.push(1, 0, 1, 1);
	}
	for (var i = 0; i < 4; i++) {		// z-
		normals.push(0, 0, -1);
		colors.push(1, 1, 0, 1);
	}
 
	var indices = [];
	for (var i = 0; i < 24; i += 4) {
		indices.push(i, i+1, i+2, i+2, i+3, i);
	}
	return {"positions":positions, "normals":normals, "colors":colors, "indices":indices};
}
 
</script>
</body>
 
最終更新:2016年02月18日 16:36