var cube = {
"vertices": [
0.2, 0.2, 0.2, //0
0.2, 0.2,-0.2, //1
0.2,-0.2, 0.2, //2
0.2,-0.2,-0.2, //3
-0.2, 0.2,-0.2, //4
-0.2, 0.2, 0.2, //2
-0.2,-0.2,-0.2, //6
-0.2,-0.2, 0.2 //7
],
"normals": [
1, 1, 1, //0
1, 1,-1, //1
1,-1, 1, //2
1,-1,-1, //3
-1, 1,-1, //4
-1, 1, 1, //5
-1,-1,-1, //6
-1,-1, 1 //7
],
"indices" : [
0,2,3, 0,3,1,
4,6,7, 4,7,5,
4,5,0, 4,0,1,
7,6,3, 7,3,2,
5,7,2, 5,2,0,
1,3,6, 1,6,4
]
}
var init = function(){
var gl = getGLContext();
var cubeBuffer = new GLBuffer(gl, cube);
var shader;
async.parallel([
function(callback){
var url = document.getElementById("vertexShader").getAttribute("src");
ajax(url, callback);
},
function(callback){
var url = document.getElementById("fragmentShader").getAttribute("src");
ajax(url, callback);
},
], function (err, data){
shader = new GLShader(gl, data[0], data[1]);
gl.useProgram(shader.program);
shader.aVertexPosition = gl.getAttribLocation(shader.program, "aVertexPosition");
shader.aVertexNormal = gl.getAttribLocation(shader.program, "aVertexNormal");
var cam = gl.getUniformLocation(shader.program, "matCamara");
var camMat = mat4.identity(mat4.create());
mat4.translate(camMat, camMat, [0, 0, 0.1]);
mat4.rotate(camMat, camMat, Math.PI/4, [1,0.5,0.5]);
gl.uniformMatrix4fv(cam, false, camMat);
var lightPos = shader.getUniformLocation("lightPos");
gl.uniform3fv(lightPos, [0.1,0.1,0.1]);
var lightDirection = shader.getUniformLocation("lightDirection");
gl.uniform3fv(lightDirection, [-1, -1, -1]);
var materialDiffuse = shader.getUniformLocation("materialDiffuse");
gl.uniform4fv(materialDiffuse, [0.8, 0.2, 0.2, 1.0]);
var lightDiffuse = shader.getUniformLocation("lightDiffuse");
gl.uniform4fv(lightDiffuse, [1,1,1,1]);
var matProject = mat4.identity(mat4.create());//2PI = 360d -> 1d = PI/180
mat4.perspective(matProject, Math.PI/180 * 80, 1, 0, 1);
gl.uniformMatrix4fv(
shader.getUniformLocation("matProject"),
false,
matProject
);
onReady(gl, cubeBuffer, shader);
});
}
setTimeout(init, 0);
function onReady(gl, buffer, shader){
onDraw();
function onDraw(){
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.enable(gl.DEPTH_TEST);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.viewport(0,0,300,300);
gl.enableVertexAttribArray(shader.aVertexPosition);
gl.enableVertexAttribArray(shader.aVertexNormal);
gl.bindBuffer(gl.ARRAY_BUFFER, buffer.vertex);
gl.vertexAttribPointer(shader.aVertexPosition, 3, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, buffer.normal);
gl.vertexAttribPointer(shader.aVertexNormal, 3, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffer.index);
gl.drawElements(gl.TRIANGLES, buffer.index.length, gl.UNSIGNED_SHORT, 0);
}
}
function ajax(url, callback){
var ajax = new XMLHttpRequest();
ajax.onreadystatechange = function(){
if(ajax.readyState === 4){
//complete requset
if(ajax.status === 200){
//not error
callback(null, ajax.responseText);
}
}
}
ajax.open("GET", url, true);//if need Sync method set false;
ajax.send(null);
}
//Lib function
function getGLContext(){
var canvas = document.getElementsByTagName("canvas");
canvas = [].filter.call(canvas, function(element){
if(element.getAttribute("WebGL") != null)
return true;
else
return false;
});
canvas = canvas[0];
return canvas.getContext("experimental-webgl");
}
//Lib Class
function GLBuffer(gl, model){
this.model = model;
try {
//only binded buffer can send data
//vertex is coord of points
var vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(model.vertices), gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
//index is triangle point index of suface
var indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(model.indices), gl.STATIC_DRAW);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
//normals Buffer
var normalBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, normalBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(model.normals), gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
this.vertex = vertexBuffer;
this.index = indexBuffer;
this.index.length = model.indices.length;
this.normal = normalBuffer;
} catch(e){
throw Error("Can not create Buffer");
}
}
function GLShader(gl, vertexSource, fragmentSource){
var shaderProgram = gl.createProgram();
//compile Source
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexSource);
gl.compileShader(vertexShader);
checkCompile(vertexShader);
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentSource);
gl.compileShader(fragmentShader);
checkCompile(fragmentShader);
//attach shader
gl.attachShader(shaderProgram, fragmentShader);
gl.attachShader(shaderProgram, vertexShader);
//link
gl.linkProgram(shaderProgram);
this.program = shaderProgram;
this._private = {
gl : gl
}
function checkCompile(shader){
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
throw Error(gl.getShaderInfoLog(shader));
}
}
}
GLShader.prototype.getUniformLocation = function(name){
return this._private.gl.getUniformLocation(this.program, name);
}
GLShader.prototype.uniform4fv = function(name, arr){
this._private.gl.uniform4fv(this.getUniformLocation(name), arr);
}
GLShader.prototype.uniform3fv = function(name, arr){
this._private.gl.uniform3fv(this.getUniformLocation(name), arr);
}
GLShader.prototype.uniformMatrix4fv = function(name, arr){
this._private.gl.uniformMatrix4fv(this.getUniformLocation(name), false, arr);
}