<!doctyp html>
<head>
<meta charset="utf-8">
<title>webgl2</title>
<script src="minMatrix.js"></script>
<script id="vs" type="text/x-vertex">
// 頂点シェイダー
attribute vec3 position;
attribute vec4 color;
uniform mat4 mvpMatrix;
varying vec4 vColor;
void main(void) {
vColor = color;
gl_Position = mvpMatrix * vec4(position, 1);
}
</script>
<script id="fs" type="text/x-fragment">
// 断片シェイダー
precision mediump float;
varying vec4 vColor;
void main(void) {
gl_FragColor = vColor;
}
</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 uniLocation; // uniform mvpMatrix
var m = new matIV();
var mMatrix = m.identity(m.create()); // model
var pMatrix = m.identity(m.create()); // perspective
var lat = 0; // 緯度
var lon = 90; // 経度
var dist = 3; // 距離
var fps;
var fpsCount;
var secSav;
onload = function() {
canvas.width = 640;
canvas.height = 480;
gl = canvas.getContext("experimental-webgl");
const params = ["RENDERER", "VENDOR", "VERSION", "SHADING_LANGUAGE_VERSION"];
var str = "";
for (var i = 0; i < params.length; i++) {
var param = params[i];
str += param + "=[" + gl.getParameter(gl[param]) + "]<br>";
}
log.innerHTML = str;
var vPosition = [
0, 0, 0,
0, 1, 0,
1, 1, 0,
1, 0, 0,
];
var vColor = [
1, 0, 0, 1,
0, 1, 0, 1,
1, 1, 1, 1,
0, 0, 1, 1,
];
var vIndex = [
0, 1, 2,
2, 3, 0,
];
var vShader = createShader("vs");
var fShader = createShader("fs");
var program = createProgram(vShader, fShader);
setAttribute(program, "position", vPosition, 3);
setAttribute(program, "color", vColor, 4);
uniLocation = gl.getUniformLocation(program, "mvpMatrix");
var ibo = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ibo);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Int16Array(vIndex), gl.STATIC_DRAW);
gl.enable(gl.CULL_FACE);
gl.frontFace(gl.CW);
gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.LEQUAL);
m.perspective(45, canvas.width / canvas.height, 0.1, 10, pMatrix);
// setInterval(draw, 1000 / 30);
draw();
};
function draw() {
if (keyboard.isKeyDown(65)) lon = (lon + 2) % 360; // A
if (keyboard.isKeyDown(68)) lon = (lon + 358) % 360; // D
if (keyboard.isKeyDown(87)) lat = Math.min(lat + 1, 89); // W
if (keyboard.isKeyDown(83)) lat = Math.max(lat - 1, -89); // S
if (keyboard.isKeyDown(33)) dist = Math.max(dist - 0.1, 0.1); // PageUp
if (keyboard.isKeyDown(34)) dist += 0.1; // PageDown
var rad = lat * Math.PI / 180;
var y = Math.sin(rad) * dist;
var r = Math.cos(rad) * dist;
var rad = lon * Math.PI / 180;
var x = Math.cos(rad) * r;
var z = Math.sin(rad) * r;
var sec = (new Date()).getSeconds();
if (secSav != sec) {
fps = fpsCount;
fpsCount = 0;
secSav = sec;
}
fpsCount++;
disp.innerHTML = "lon=" + lon + " lat=" + lat + " dist=" + dist.toFixed(1) +
" fps=" + fps;
gl.clearColor(0x64 / 0xff, 0x95 / 0xff, 0xed / 0xff, 1);
gl.clearDepth(1);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
var vMatrix = m.identity(m.create());
var mvpMatrix = m.identity(m.create());
m.lookAt([x, y, z], [0, 0, 0], [0, 1, 0], vMatrix);
m.multiply(pMatrix, vMatrix, mvpMatrix);
m.multiply(mvpMatrix, mMatrix, mvpMatrix);
gl.uniformMatrix4fv(uniLocation, false, mvpMatrix);
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
// gl.drawElements(gl.LINE_STRIP, 6, 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;
}
gl.useProgram(program);
return program;
}
function setAttribute(program, name, data, stride) {
var location = gl.getAttribLocation(program, name);
var vbo = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data), gl.STATIC_DRAW);
gl.enableVertexAttribArray(location);
gl.vertexAttribPointer(location, stride, gl.FLOAT, false, 0, 0);
}
</script>
</head>
<body>
<div id="disp"></div>
<canvas id="canvas"></canvas>
<p>
Move camera [A]:left [D]:right [W]:up [S]:down [PageUp]:front [PageDown]:back
</p>
<div id="log"></div>
</body>