function torus(row, column, irad, orad)
{
var pos = new Array(), nor = new Array(),
col = new Array(), idx = new Array();
for(var i = 0; i <= row; i++){
var r = Math.PI * 2 / row * i;
var rr = Math.cos(r);
var ry = Math.sin(r);
for(var ii = 0; ii <= column; ii++){
var tr = Math.PI * 2 / column * ii;
var tx = (rr * irad + orad) * Math.cos(tr);
var ty = ry * irad;
var tz = (rr * irad + orad) * Math.sin(tr);
var rx = rr * Math.cos(tr);
var rz = rr * Math.sin(tr);
pos.push(tx, ty, tz);
nor.push(rx, ry, rz);
var tc = hsva(360 / column * ii, 1, 1, 1);
col.push(tc[0], tc[1], tc[2], tc[3]);
}
}
for(i = 0; i < row; i++){
for(ii = 0; ii < column; ii++){
r = (column + 1) * i + ii;
idx.push(r, r + column + 1, r + 1);
idx.push(r + column + 1, r + column + 2, r + 1);
}
}
return {
"position" : pos,
"color" : col,
"index" : idx,
"normal" : nor
};
}
function cube(size)
{
var len = size * 0.5;
var pos = [
-len, len, len,
len, len, len,
len, -len, len,
-len, -len, len,
-len, len, -len,
len, len, -len,
len, -len, -len,
-len, -len, -len
];
var index = [
0, 1, 3,
1, 2, 3,
1, 5, 2,
5, 6, 2,
4, 0,7,
0, 3, 7,
5, 4, 6,
4, 7, 6,
0, 4, 5,
1, 0, 5,
3, 2, 7,
2, 6, 7
];
var color = [
1, 1, 1, 1,
1, 0, 0, 1,
0, 1, 0, 1,
0, 0, 1, 1,
0, 1, 0, 1,
0, 0, 1, 1,
1, 1, 1, 1,
1, 0, 0, 1
];
return {
"position":pos,
"index" : index,
"color" : color,
"normal" : pos
};
}
// HSVカラー取得用関数
function hsva(h, s, v, a){
if(s > 1 || v > 1 || a > 1){return;}
var th = h % 360;
var i = Math.floor(th / 60);
var f = th / 60 - i;
var m = v * (1 - s);
var n = v * (1 - s * f);
var k = v * (1 - s * (1 - f));
var color = new Array();
if(!s > 0 && !s < 0){
color.push(v, v, v, a);
} else {
var r = new Array(v, n, m, m, k, v);
var g = new Array(k, v, v, n, m, m);
var b = new Array(m, m, k, v, v, n);
color.push(r[i], g[i], b[i], a);
}
return color;
}
<!DOCTYPE html>
<html>
<head>
<title>鏡面反射</title>
<meta charset="UTF-8">
<script src="mesh.js"></script>
<script src="minMatrix.js"></script>
<script src="specular.js"></script>
<script id="vs" type="x-shader/vertex">
attribute vec3 pos;
attribute vec3 normal;
uniform mat4 mvpMatrix;
varying vec3 vNormal;
void main()
{
vNormal = normal;
gl_Position = mvpMatrix * vec4(pos, 1.0);
}
</script>
<script id="fs" type="x-shader/fragment">
precision mediump float;
uniform vec3 lightPos;
uniform vec3 eyePos;
uniform mat4 invMMatrix;
varying vec3 vNormal;
void main()
{
vec3 nInvLightDir = normalize(invMMatrix * vec4(normalize(lightPos), 0)).xyz;
vec3 nInvEyeDir = normalize(invMMatrix * vec4(normalize(eyePos), 0)).xyz;
float diffuse = dot(nInvLightDir, normalize(vNormal));
vec3 halfVec = normalize(nInvLightDir + nInvEyeDir);
float specular = pow(clamp(dot(halfVec, vNormal), 0.1, 1.0), 50.0);
vec3 color = vec3(diffuse) + specular;
gl_FragColor = vec4(color, 1.0);
}
</script>
</head>
<body>
<canvas id="canvas"></canvas>
</body>
</html>
window.onload = function()
{
var canvas = document.getElementById('canvas');
canvas.width = canvas.height = 300;
var gl = canvas.getContext('webgl');
var vs = gl.createShader(gl.VERTEX_SHADER);
var fs = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(vs, document.getElementById('vs').text);
gl.shaderSource(fs, document.getElementById('fs').text);
gl.compileShader(vs);
gl.compileShader(fs);
var prog = gl.createProgram();
gl.attachShader(prog, vs);
gl.attachShader(prog, fs);
gl.linkProgram(prog);
if (gl.getProgramParameter(prog, gl.LINK_STATUS))
{
gl.useProgram(prog);
}else{
console.log(gl.getProgramInfoLog(prog));
return;
}
var attrList = [];
var strideList = [];
var uniformList = [];
attrList[0] = gl.getAttribLocation(prog, 'pos');
attrList[1] = gl.getAttribLocation(prog, 'normal');
console.log(attrList);
strideList[0] = 3;
strideList[1] = 3;
uniformList[0] = gl.getUniformLocation(prog, 'mvpMatrix');
uniformList[1] = gl.getUniformLocation(prog, 'invMMatrix');
uniformList[2] = gl.getUniformLocation(prog, 'lightPos');
uniformList[3] = gl.getUniformLocation(prog, 'eyePos');
var mesh = new torus(30, 30, 0.5, 1.0);
// position
var vbo = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
gl.enableVertexAttribArray(attrList[0]);
gl.vertexAttribPointer(attrList[0], strideList[0], gl.FLOAT, false, 0, 0);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(mesh['position']), gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
// normal
vbo = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(mesh['normal']), gl.STATIC_DRAW);
gl.enableVertexAttribArray(attrList[1]);
gl.vertexAttribPointer(attrList[1], strideList[1], gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
// ibo
var ibo = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ibo);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Int16Array(mesh['index']), gl.STATIC_DRAW);
// matrix
var m = new matIV();
var mMatrix = m.identity(m.create());
var vMatrix = m.identity(m.create());
var pMatrix = m.identity(m.create());
var vpMatrix = m.identity(m.create());
var mvpMatrix = m.identity(m.create());
var invMMatrix = m.identity(m.create());
var eyePos =[0, 0, 3];
var lightPos = [0, 3, 0];
m.lookAt(eyePos, [0,0,0], [0,1,0], vMatrix);
m.perspective(90, 1, 0.1, 100, pMatrix);
m.multiply(pMatrix, vMatrix, vpMatrix);
gl.enable(gl.DEPTH_TEST);
draw();
var count = 0;
function draw()
{
gl.clearColor(0,0,0,1);
gl.clear(gl.COLOR_BUFFER_BIT);
m.identity(mMatrix);
m.rotate(mMatrix, 2*count++*Math.PI/180, [1,0.5,-0.3],mMatrix);
m.multiply(vpMatrix, mMatrix, mvpMatrix);
gl.uniformMatrix4fv(uniformList[0], false, mvpMatrix);
// ワールド座標変換逆行列
m.inverse(mMatrix, invMMatrix);
gl.uniformMatrix4fv(uniformList[1], false, invMMatrix);
gl.uniform3fv(uniformList[2], lightPos);
gl.uniform3fv(uniformList[3], eyePos);
gl.drawElements(gl.TRIANGLES, mesh['index'].length, gl.UNSIGNED_SHORT, false, 0);
setTimeout(draw, 1000/30);
}
};