下面的代码编写紧接着上一篇来进行扩展。
目录
视图矩阵
- maxtrix.js
//视图矩阵计算
Matrix4.prototype.setLookAt = function (eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ) {
var e, fx, fy,fz, rlf, sx, sy, sz, rls, ux, uy, uz;
fx = centerY - eyeX;
fy = centerY - eyeY;
fz = centerZ - eyeZ;
rlf = 1 / Math.sqrt(fx * fx + fy * fy + fz * fz);//归一化
fx *= rlf;
fy *= rlf;
fz *= rlf;
//叉乘计算
sx = fy * upZ - fz * upY;
sy = fz * upX - fx * upZ;
sz = fx * upY - fy * upX;
rls = 1 / Math.sqrt(sx*sx + sy*sy + sz*sz);//归一化
sx *= rls;
sy *= rls;
sz *= rls;
//叉乘
ux = sy * fz - sz * fy;
uy = sz * fy - sx * fz;
uz = sx * fy - sy * fx;
e = this.elements;
e[0] = sx; e[4] = sy; e[8] = sz; e[12] = 0;
e[1] = ux; e[5] = uy; e[9] = uz; e[13] = 0;
e[2] = -fx; e[6] = -fy; e[10] = -fz; e[14] = 0;
e[3] = 0; e[7] = 0; e[11] = 0; e[15] = 1;
return this.translate(-eyeX, -eyeY, -eyeZ);//乘以平移矩阵的转置矩阵
}
- demo.js:添加视图矩阵
顶点着色器
VSHADER_SOURCE =
'attribute vec4 a_Position;\n'+
'uniform mat4 u_ModelMatrix;\n' +//旋转
'uniform mat4 u_ViewMatrix;\n' +//视图矩阵
'void main (){\n'+
'gl_Position = u_ViewMatrix*u_ModelMatrix*a_Position;\n'+//视图矩阵*旋转角度*位置
'}\n'
定义矩阵:(看向位置,自己位置,头部朝向)
//视图矩阵
var u_ViewMatrix = gl.getUniformLocation(gl.program, 'u_ViewMatrix')
var viewMatrix = new Matrix4()
viewMatrix.lookAt(0,0,0,0,0,-1,0,1,0)
draw方法中
//设置传递视图矩阵
gl.uniformMatrix4fv(u_ViewMatrix, false, viewMatrix.elements)
投影矩阵
透视矩阵
- matrix.js
//透视投影矩阵计算
Matrix4.prototype.perspective = function (fovy, aspect, near, far) {
return this.concat(new Matrix4().setPerspective(fovy, aspect, near, far));
}
Matrix4.prototype.setPerspective = function (fovy, aspect, near, far) {
var e, s, ct;
if (near === far || aspect == 0) {
throw 'null frustum';
}
if (near <= 0) {
throw 'near <= 0';
}
if (far <= 0) {
throw 'far <= 0';
}
fovy = Math.PI * fovy / 180 / 2;
s = Math.sin(fovy);
if (s === 0) {
throw 'null frustum';
}
rd = 1 / (far - near);
ct = Math.cos(fovy) / s;
e = this.elements;
e[0] = ct / aspect; e[4] = 0; e[8] = 0; e[12] = 0;
e[1] = 0; e[5] = ct; e[9] = 0; e[13] = 0;
e[2] = 0; e[6] = 0; e[10] = -(far + near) / (far - near); e[14] = -2 * near * far / (far - near);
e[3] = 0; e[7] = 0; e[11] = -1; e[15] = 0;
return this;
}
- demo.js
顶点着色器
VSHADER_SOURCE =
'attribute vec4 a_Position;\n'+
'uniform mat4 u_ModelMatrix;\n' +//旋转
'uniform mat4 u_ViewMatrix;\n' +//视图矩阵
'uniform mat4 u_ProjectionMatrix;\n' +//投影矩阵
'void main (){\n'+
'gl_Position = u_ProjectionMatrix*u_ViewMatrix*u_ModelMatrix*a_Position;\n'+//投影矩阵*视图矩阵*旋转角度*位置
'}\n'
定义投影矩阵
//投影矩阵
var u_ProjectionMatrix = gl.getUniformLocation(gl.program, 'u_ProjectionMatrix')
var projectionMatrix = new Matrix4()
projectionMatrix.perspective(120,1,0.1,1000)
draw方法中
//设置传递投影矩阵
gl.uniformMatrix4fv(u_ProjectionMatrix, false, projectionMatrix.elements)
正交矩阵
- maxtrix.js
//正交投影
Matrix4.prototype.ortho = function(left, right, bottom, top, near, far) {
return this.concat(new Matrix4().setOrtho(left, right, bottom, top, near, far));
}
Matrix4.prototype.setOrtho = function(left, right, bottom, top, near, far) {
if (left === right || bottom === top || near === far) {
throw 'null frustum';
}
e = this.elements;
e[0] = 2 / (right - left); e[4] = 0; e[8] = 0; e[12] = - (right + left) / (right - left);
e[1] = 0; e[5] = 2 / (top - bottom); e[9] = 0; e[13] = - (top + bottom ) / (top - bottom);
e[2] = 0; e[6] = 0; e[10] = -2 / (far - near); e[14] = - (far + near) / (far - near);
e[3] = 0; e[7] = 0; e[11] = 0; e[15] = 1;
console.log(e)
return this;
}
- demo.js(其他与透视一致)
//投影矩阵
var u_ProjectionMatrix = gl.getUniformLocation(gl.program, 'u_ProjectionMatrix')
var projectionMatrix = new Matrix4()
//projectionMatrix.perspective(120,1,0.1,1000)
projectionMatrix.ortho(-5,5,-5,5,0.1,1000)//正交
绘制Cude
- demo_cude.js
var canvas = document.getElementById('myCanvas')//获取canvas
var gl = canvas.getContext('webgl')//获取webGL上下文
var program = gl.createProgram()//创建程序
var VSHADER_SOURCE, FSHADER_SOURCE
//定义顶点着色器、片元着色器源码
VSHADER_SOURCE =
'attribute vec4 a_Position;\n' +
'attribute vec4 a_Color;\n' +
'attribute vec4 a_Normal;\n' +
'uniform mat4 u_MvpMatrix;\n' +//视图投影矩阵
'void main() {\n' +
' gl_Position = u_MvpMatrix * a_Position;\n' +//计算位置
'}\n';
FSHADER_SOURCE =
'void main() {\n' +
' gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);\n' +//颜色渲染
'}\n';
var vertexShader, fragmentShader
//创建着色器(gl上下文、着色器源码,着色器类型)
function createShader (gl, sourceCode,type) {
// create shader
var shader = gl.createShader(type)
gl.shaderSource(shader, sourceCode)
gl.compileShader(shader)
return shader
}
// define vertex shader
vertexShader = createShader(gl, VSHADER_SOURCE, gl.VERTEX_SHADER)
// define frament shader
fragmentShader = createShader(gl, FSHADER_SOURCE, gl.FRAGMENT_SHADER)
// attach shader to program
gl.attachShader(program, vertexShader)
gl.attachShader(program, fragmentShader)
// link program to context
gl.linkProgram(program)
gl.useProgram(program)
gl.program = program
var tick = function () {
draw()
requestAnimationFrame(tick)//循环tick
}
function initVertexBuffers (gl) {//加载顶点数据
// Create a cube(下面的图差不多就是那意思,文章里显示,对不准)
// v6----- v5
// /| --------/|
// v1------v0|
// | | ------| |
// | |v7-----|v4
// |/------- |/
// v2------v3
var vertices = new Float32Array([ // Vertex coordinates(点坐标)
1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0,-1.0, 1.0, 1.0,-1.0, 1.0, // v0-v1-v2-v3 front
1.0, 1.0, 1.0, 1.0,-1.0, 1.0, 1.0,-1.0,-1.0, 1.0, 1.0,-1.0, // v0-v3-v4-v5 right
1.0, 1.0, 1.0, 1.0, 1.0,-1.0, -1.0, 1.0,-1.0, -1.0, 1.0, 1.0, // v0-v5-v6-v1 up
-1.0, 1.0, 1.0, -1.0, 1.0,-1.0, -1.0,-1.0,-1.0, -1.0,-1.0, 1.0, // v1-v6-v7-v2 left
-1.0,-1.0,-1.0, 1.0,-1.0,-1.0, 1.0,-1.0, 1.0, -1.0,-1.0, 1.0, // v7-v4-v3-v2 down
1.0,-1.0,-1.0, -1.0,-1.0,-1.0, -1.0, 1.0,-1.0, 1.0, 1.0,-1.0 // v4-v7-v6-v5 back
]);
// 每个顶点的法向量
var normals = new Float32Array([
0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0,
1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0,
-1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0,
0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0,
0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0
]);
var colors = new Float32Array([ // Colors
1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, // v0-v1-v2-v3 front(white)
1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, // v0-v3-v4-v5 right(white)
1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, // v0-v5-v6-v1 up(white)
1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, // v1-v6-v7-v2 left(white)
1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, // v7-v4-v3-v2 down(white)
1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 // v4-v7-v6-v5 back(white)
]);
var indices = new Uint8Array([ // Indices of the vertices,三角面绘制规则
0, 1, 2, 0, 2, 3, // front
4, 5, 6, 4, 6, 7, // right
8, 9,10, 8,10,11, // up
12,13,14, 12,14,15, // left
16,17,18, 16,18,19, // down
20,21,22, 20,22,23 // back
]);
// Create a buffer object
var indexBuffer = gl.createBuffer();
initArrayBuffer(gl, vertices, 3, gl.FLOAT, 'a_Position')
initArrayBuffer(gl, colors, 3, gl.FLOAT, 'a_Color')
initArrayBuffer(gl, normals, 3, gl.FLOAT, 'a_Normal')
// Write the indices to the buffer object
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
return indices.length;//返回点数
}
//(gl上下文,ArrayBuffer数据,以几组数据为一点,数据类型,着色器中对应变量名)
function initArrayBuffer(gl, data, num, type, attribute) {
// Create a buffer object
var buffer = gl.createBuffer();
if (!buffer) {
console.log('Failed to create the buffer object');
return false;
}
// Write date into the buffer object
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
// Assign the buffer object to the attribute variable
var a_attribute = gl.getAttribLocation(gl.program, attribute);
if (a_attribute < 0) {
console.log('Failed to get the storage location of ' + attribute);
return false;
}
//将当前绑定到gl.ARRAY_BUFFER的缓冲区到顶点缓存区
gl.vertexAttribPointer(a_attribute, num, type, false, 0, 0);
// Enable the assignment of the buffer object to the attribute variable
gl.enableVertexAttribArray(a_attribute);//许可缓冲区分配变量
gl.bindBuffer(gl.ARRAY_BUFFER, null);//清空bindBuffer中的gl.ARRAY_BUFFER缓存区
return true;
}
function normalizeVector (vector) {
var len = Math.sqrt(vector[0]**2 + vector[1]**2 + vector[2]**2)
return [vector[0] / len, vector[1] / len, vector[2] / len]
}
// write the positions of vertices to a vertex shader
var n = initVertexBuffers(gl)//加载顶点
gl.clearColor(0, 0, 0, 1)//背景色
gl.enable(gl.DEPTH_TEST);//深度检测
//摄像机视图
// Get the storage location of u_MvpMatrix
var u_MvpMatrix = gl.getUniformLocation(gl.program, 'u_MvpMatrix');
// Set the eye point and the viewing volume
var mvpMatrix = new Matrix4();
mvpMatrix.setPerspective(30, 1, 1, 100);
mvpMatrix.lookAt(3, 3, 7, 0, 0, 0, 0, 1,0);
//关联gl设置视图
gl.uniformMatrix4fv(u_MvpMatrix, false, mvpMatrix.elements);
function draw () {
// Clear color and depth buffer
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
// Draw the cube索引方式绘制(三角面,绘制点数,前面的数据类型,偏移)
gl.drawElements(gl.TRIANGLES, n, gl.UNSIGNED_BYTE, 0);
}
tick()
源代码,等写完基础随笔就上传拉。