1 DOCTYPE html> 2 3 <html lang="en"> 4 <head> 5 <meta charset="utf-8" /> 6 <title>TypeScript HTML Apptitle> 7 <link rel="stylesheet" href="app.css" type="text/css" /> 8 <script src="lib/cuon-matrix.js">script> 9 <script src="app_sanjiao.js">script> 10 <script src="js.d.js">script> 11 <style> 12 .showWindow { 13 width: 400px; 14 height: 400px; 15 background-color: silver; 16 } 17 style> 18 head> 19 <body> 20 <canvas id="showWindow" class="showWindow">canvas> 21 body> 22 html>
HTML部分,主要引入了逻辑代码块的TS代码及现成的矩阵JS库还有自己写的TS的JS声明文件d.ts
1 class Greeter { 2 element: HTMLElement; 3 canvas: HTMLCanvasElement; 4 VSHADER_SOURCE: string; 5 FSHADER_SOURCE: string; 6 obj: WebGLProgram; 7 g_Points: vec3[]; 8 9 constructor(element: HTMLElement) { 10 this.element = element; 11 this.canvas = element.getElementsByClassName("showWindow")[0] as HTMLCanvasElement; 12 this.canvas.width = this.canvas.clientWidth; 13 this.canvas.height = this.canvas.clientHeight; 14 console.log(this.canvas); 15 } 16 17 public DrawRectangle(): string { 18 this.VSHADER_SOURCE = "attribute vec4 a_Position;\n " + 19 "uniform mat4 u_xformMatrix;\n" + //变换矩阵 20 // "uniform vec4 u_Translation;\n"+ //平移用偏移量 21 //attribute float a_PointSize;// 绘点才用。 点的大小 22 "\n void main(){\n " + 23 "gl_Position = a_Position * u_xformMatrix;" + 24 " \n } \n"; 25 this.FSHADER_SOURCE = "precision mediump float;\n uniform vec4 u_FragColor; \n void main(){\n gl_FragColor=u_FragColor;\n}\n"; 26 let tx = 0.5, ty = 0.5, tz = 0.0; //偏移量 mh 27 28 let gl: WebGLRenderingContext = this.canvas.getContext("webgl") as WebGLRenderingContext; 29 gl.viewport(0, 0, this.canvas.width, this.canvas.height); 30 31 if (!this.InitShaders(gl, this.VSHADER_SOURCE, this.FSHADER_SOURCE)) { 32 console.log("error"); 33 } 34 let n: number = this.initVertezBuffers(gl); 35 if (n < 0) { 36 return; 37 } 38 39 40 //gl.clearColor(0, 0, 0, 1); 41 //gl.clear(gl.COLOR_BUFFER_BIT); 42 //gl.drawArrays(gl.POINTS, 0, n); 43 44 //var a_Position = gl.getAttribLocation(this.obj, 'a_Position'); 45 //if (a_Position < 0) { 46 // console.log("获取变量地址失败"); 47 // return; 48 //} 49 //gl.vertexAttrib2f(a_Position, 0.0, 0.0); 50 //var a_PointSize = gl.getAttribLocation(this.obj, 'a_PointSize'); 51 //if (a_PointSize < 0) { 52 // console.log("获取变量地址失败"); 53 // return; 54 //} 55 //gl.vertexAttrib1f(a_PointSize, 5.0); 56 let angle: number = 10.0; 57 58 //let radian: number = Math.PI * angle / 180.0; 59 //let cosB: number = Math.cos(radian); 60 //let sinB: number = Math.sin(radian); 61 62 //var xformMatrix = new Float32Array([ //行主序矩阵(每一行与相乘数的4个分量分别相乘再相加) 63 // 0.5, 0.0, 0.0, 0.5, //各项相乘和对应新X 64 // 0.0, 0.5, 0.0, 0.5,//各项相乘和对应新Y 65 // 0.0, 0.0, 0.5, 0.5,//各项相乘和对应新Z 66 // 0.0, 0.0, 0.0, 1.0//各项相乘和对应新W 67 // //1.0, 0.0, 0.0, 0.0, 68 // //0.0, 1.0, 0.0, 0.0, 69 // //0.0, 0.0, 1.0, 0.0, 70 // //1.0, 1.0, 0.0, 1.0 71 //]); 72 var u_xformMatrix = gl.getUniformLocation(this.obj, 'u_xformMatrix'); 73 if (u_xformMatrix < 0) { 74 console.log("获取偏移量地址失败"); 75 return; 76 } 77 var xformMatrix = new Matrix4(); 78 xformMatrix.scale(0.5, 0.1, 1); 79 xformMatrix.rotate(10, 0.0, 0.0, -1.0); 80 gl.uniformMatrix4fv(u_xformMatrix, false, xformMatrix.elements); 81 82 //xformMatrix = new Float32Array([ //列主序矩阵(每一列与相乘数的4个分量分别相乘再相加) 83 // 1.0, 0.0, 0.0, 0.0, 84 // 0.0, 1.0, 0.0, 0.0, 85 // 0.0, 0.0, 1.0, 0.0, 86 // 1.0, 1.0, 1.0, 1.0 87 //]); 88 89 90 //var glTranslaTion = gl.getUniformLocation(this.obj, 'u_Translation'); 91 //if (glTranslaTion < 0) { 92 // console.log("获取偏移量地址失败"); 93 // return; 94 //} 95 //gl.uniform4f(glTranslaTion, tx, ty, tz, 0.0); 96 97 var gl_FragColor = gl.getUniformLocation(this.obj, 'u_FragColor'); 98 if (gl_FragColor < 0) { 99 console.log("获取颜色变量地址失败"); 100 return; 101 } 102 gl.uniform4f(gl_FragColor, 0.0, 1.0, 1.0, 1.0); 103 104 //this.g_Points = []; //需要先初始化数组 不然会报错未找到 105 //this.canvas.onmousedown = (e) => { 106 // this.click(e, gl, this.canvas, a_Position); 107 //}; 108 109 110 gl.clearColor(0.0, 0.0, 0.0, 1.0); //设置默认颜色 111 gl.clear(gl.COLOR_BUFFER_BIT); //用默认颜色清除画布 112 gl.drawArrays(gl.TRIANGLE_STRIP, 0, n); //第一个参数表示绘制类型 (点 图形 ) 113 114 //console.log(gl); 115 return ""; 116 } 117 118 initVertezBuffers(gl: WebGLRenderingContext) { 119 let vertices: Float32Array = new Float32Array([-0.5, 0.5, -0.5, -0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5, -0.5, -0.5]); 120 let n: number = 4; 121 122 let vertexBuffer: WebGLBuffer = gl.createBuffer(); 123 if (!vertexBuffer) { 124 console.log('Failed to Create the buffer object'); 125 return -1; 126 } 127 128 gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); 129 gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW); 130 let a_Position: number = gl.getAttribLocation(this.obj, 'a_Position'); 131 132 gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0); 133 134 gl.enableVertexAttribArray(a_Position); 135 return n; 136 } 137 138 //准备着色器 139 InitShaders(gl: WebGLRenderingContext, vshadersource, fshadersource): boolean { 140 let vshader = gl.createShader(gl.VERTEX_SHADER); 141 let fshader = gl.createShader(gl.FRAGMENT_SHADER); 142 gl.shaderSource(vshader, vshadersource); 143 gl.shaderSource(fshader, fshadersource); 144 145 gl.compileShader(vshader); 146 gl.compileShader(fshader); 147 if (!gl.getShaderParameter(vshader, gl.COMPILE_STATUS) || !gl.getShaderParameter(fshader, gl.COMPILE_STATUS)) { 148 console.log(gl.getShaderInfoLog(vshader)); 149 console.log(gl.getShaderInfoLog(fshader)); 150 return false; 151 } 152 let shaderobj = gl.createProgram(); 153 if (shaderobj != null) { 154 gl.attachShader(shaderobj, fshader); 155 gl.attachShader(shaderobj, vshader); 156 gl.linkProgram(shaderobj); 157 if (!gl.getProgramParameter(shaderobj, gl.LINK_STATUS)) { 158 console.log(gl.getProgramInfoLog(shaderobj)); 159 } 160 gl.useProgram(shaderobj); 161 this.obj = shaderobj; //TS里面未将WEBGL程序对象暴露出来,通过自己保存对象来使用。 162 console.log(gl); 163 164 } 165 return true; 166 } 167 168 public click(e, gl, canvas, a_Position) { 169 let x = e.clientX; 170 let y = e.clientY; 171 let rect = e.target.getBoundingClientRect(); 172 x = ((x - rect.left) - canvas.height / 2) / (canvas.height / 2); 173 y = (canvas.width / 2 - (y - rect.top)) / (canvas.width / 2); 174 this.g_Points.push(new vec3(x, y, 0)); 175 176 gl.clear(gl.COLOR_BUFFER_BIT); 177 178 let len = this.g_Points.length; 179 for (let i = 0; i < len; i++) { 180 gl.vertexAttrib3f(a_Position, this.g_Points[i].x, this.g_Points[i].y, this.g_Points[i].z); 181 182 gl.drawArrays(gl.POINTS, 0, 1); 183 } 184 } 185 } 186 187 class vec3 { 188 x: number; 189 y: number; 190 z: number; 191 192 constructor(x: number, y: number, z: number) { 193 this.x = x; 194 this.y = y; 195 this.z = z; 196 } 197 } 198 199 200 window.onload = () => { 201 let m = new Greeter(document.getElementsByTagName("body")[0] as HTMLElement); 202 console.log(m.DrawRectangle()); 203 204 }
TS逻辑代码部分代码有点混乱,主要之前刚开始学的时候没有写,现在开始随着学习深入会从现有代码上面修改.
1 declare class Matrix4 { 2 3 new(): any; 4 elements: Float32Array; 5 setIdentity(): Matrix4; 6 set(src: Matrix4): Matrix4; 7 concat(other: Matrix4): Matrix4; 8 multiplyVector3(pos: Matrix4): Matrix4; 9 multiplyVector4(pos: Matrix4): Matrix4; 10 transpose(): Matrix4; 11 setInverseOf(other: Matrix4): Matrix4; 12 invert(): Matrix4; 13 setOrtho(left: number, right: number, bottom: number, top: number, near: number, far: number): Matrix4; 14 ortho(left: number, right: number, bottom: number, top: number, near: number, far: number): Matrix4; 15 setFrustum(left: number, right: number, bottom: number, top: number, near: number, far: number): Matrix4; 16 frustum(left: number, right: number, bottom: number, top: number, near: number, far: number): Matrix4; 17 setPerspective(fovy: number, aspect: number, near: number, far: number): Matrix4; 18 perspective(fovy: number, aspect: number, near: number, far: number): Matrix4; 19 setScale(x: number, y: number, z: number): Matrix4; 20 scale(x: number, y: number, z: number): Matrix4; 21 setTranslate(x: number, y: number, z: number): Matrix4; 22 translate(x: number, y: number, z: number): Matrix4; 23 setRotate(angle: number, x: number, y: number, z: number): Matrix4; 24 rotate(angle: number, x: number, y: number, z: number): Matrix4; 25 setLookAt(eyeX: number, eyeY: number, eyeZ: number, centerX: number, centerY: number, centerZ: number, upX: number, upY: number, upZ: number): Matrix4; 26 lookAt(eyeX: number, eyeY: number, eyeZ: number, centerX: number, centerY: number, centerZ: number, upX: number, upY: number, upZ: number): Matrix4; 27 dropShadow(plane: Float32Array, light: Float32Array): Matrix4; //传入参数类型不一定准确 到时候调整 28 dropShadowDirectionally(normX: number, normY: number, normZ: number, planeX: number, planeY: number, planeZ: number, lightX: number, lightY: number, lightZ: number): Matrix4; 29 }
针对引入的矩阵类库写的声明文件d.ts。
不知道是由于webgl版本不同还是书本原有错误。书本中写说的wegbl矩阵是列主序,经过观察测试发现webgl矩阵是行主序。已经将矩阵类库的JS文件修改过以满足现学功能。
1 // cuon-matrix.js (c) 2012 kanda and matsuda 2 /** 3 * This is a class treating 4x4 matrix. 4 * This class contains the function that is equivalent to OpenGL matrix stack. 5 * The matrix after conversion is calculated by multiplying a conversion matrix from the right. 6 * The matrix is replaced by the calculated result. 7 */ 8 9 /** 10 * Constructor of Matrix4 11 * If opt_src is specified, new matrix is initialized by opt_src. 12 * Otherwise, new matrix is initialized by identity matrix. 13 * @param opt_src source matrix(option) 14 */ 15 var Matrix4 = function(opt_src) { 16 var i, s, d; 17 if (opt_src && typeof opt_src === 'object' && opt_src.hasOwnProperty('elements')) { 18 s = opt_src.elements; 19 d = new Float32Array(16); 20 for (i = 0; i < 16; ++i) { 21 d[i] = s[i]; 22 } 23 this.elements = d; 24 } else { 25 this.elements = new Float32Array([1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1]); 26 } 27 }; 28 29 /** 30 * Set the identity matrix. 31 * @return this 32 */ 33 Matrix4.prototype.setIdentity = function() { 34 var e = this.elements; 35 e[0] = 1; e[4] = 0; e[8] = 0; e[12] = 0; 36 e[1] = 0; e[5] = 1; e[9] = 0; e[13] = 0; 37 e[2] = 0; e[6] = 0; e[10] = 1; e[14] = 0; 38 e[3] = 0; e[7] = 0; e[11] = 0; e[15] = 1; 39 return this; 40 }; 41 42 /** 43 * Copy matrix. 44 * @param src source matrix 45 * @return this 46 */ 47 Matrix4.prototype.set = function(src) { 48 var i, s, d; 49 50 s = src.elements; 51 d = this.elements; 52 53 if (s === d) { 54 return; 55 } 56 57 for (i = 0; i < 16; ++i) { 58 d[i] = s[i]; 59 } 60 61 return this; 62 }; 63 64 /** 65 * Multiply the matrix from the right. 66 * @param other The multiply matrix 67 * @return this 68 */ 69 Matrix4.prototype.concat = function(other) { 70 var i, e, a, b, ai0, ai1, ai2, ai3; 71 72 // Calculate e = a * b 73 e = this.elements; 74 a = this.elements; 75 b = other.elements; 76 77 // If e equals b, copy b to temporary matrix. 78 if (e === b) { 79 b = new Float32Array(16); 80 for (i = 0; i < 16; ++i) { 81 b[i] = e[i]; 82 } 83 } 84 85 for (i = 0; i < 4; i++) { 86 ai0=a[i]; ai1=a[i+4]; ai2=a[i+8]; ai3=a[i+12]; 87 e[i] = ai0 * b[0] + ai1 * b[1] + ai2 * b[2] + ai3 * b[3]; 88 e[i+4] = ai0 * b[4] + ai1 * b[5] + ai2 * b[6] + ai3 * b[7]; 89 e[i+8] = ai0 * b[8] + ai1 * b[9] + ai2 * b[10] + ai3 * b[11]; 90 e[i+12] = ai0 * b[12] + ai1 * b[13] + ai2 * b[14] + ai3 * b[15]; 91 } 92 93 return this; 94 }; 95 Matrix4.prototype.multiply = Matrix4.prototype.concat; 96 97 /** 98 * Multiply the three-dimensional vector. 99 * @param pos The multiply vector 100 * @return The result of multiplication(Float32Array) 101 */ 102 Matrix4.prototype.multiplyVector3 = function(pos) { 103 var e = this.elements; 104 var p = pos.elements; 105 var v = new Vector3(); 106 var result = v.elements; 107 108 result[0] = p[0] * e[0] + p[1] * e[4] + p[2] * e[ 8] + e[11]; 109 result[1] = p[0] * e[1] + p[1] * e[5] + p[2] * e[ 9] + e[12]; 110 result[2] = p[0] * e[2] + p[1] * e[6] + p[2] * e[10] + e[13]; 111 112 return v; 113 }; 114 115 /** 116 * Multiply the four-dimensional vector. 117 * @param pos The multiply vector 118 * @return The result of multiplication(Float32Array) 119 */ 120 Matrix4.prototype.multiplyVector4 = function(pos) { 121 var e = this.elements; 122 var p = pos.elements; 123 var v = new Vector4(); 124 var result = v.elements; 125 126 result[0] = p[0] * e[0] + p[1] * e[4] + p[2] * e[ 8] + p[3] * e[12]; 127 result[1] = p[0] * e[1] + p[1] * e[5] + p[2] * e[ 9] + p[3] * e[13]; 128 result[2] = p[0] * e[2] + p[1] * e[6] + p[2] * e[10] + p[3] * e[14]; 129 result[3] = p[0] * e[3] + p[1] * e[7] + p[2] * e[11] + p[3] * e[15]; 130 131 return v; 132 }; 133 134 /** 135 * Transpose the matrix. 136 * @return this 137 */ 138 Matrix4.prototype.transpose = function() { 139 var e, t; 140 141 e = this.elements; 142 143 t = e[ 1]; e[ 1] = e[ 4]; e[ 4] = t; 144 t = e[ 2]; e[ 2] = e[ 8]; e[ 8] = t; 145 t = e[ 3]; e[ 3] = e[12]; e[12] = t; 146 t = e[ 6]; e[ 6] = e[ 9]; e[ 9] = t; 147 t = e[ 7]; e[ 7] = e[13]; e[13] = t; 148 t = e[11]; e[11] = e[14]; e[14] = t; 149 150 return this; 151 }; 152 153 /** 154 * Calculate the inverse matrix of specified matrix, and set to this. 155 * @param other The source matrix 156 * @return this 157 */ 158 Matrix4.prototype.setInverseOf = function(other) { 159 var i, s, d, inv, det; 160 161 s = other.elements; 162 d = this.elements; 163 inv = new Float32Array(16); 164 165 inv[0] = s[5]*s[10]*s[15] - s[5] *s[11]*s[14] - s[9] *s[6]*s[15] 166 + s[9]*s[7] *s[14] + s[13]*s[6] *s[11] - s[13]*s[7]*s[10]; 167 inv[4] = - s[4]*s[10]*s[15] + s[4] *s[11]*s[14] + s[8] *s[6]*s[15] 168 - s[8]*s[7] *s[14] - s[12]*s[6] *s[11] + s[12]*s[7]*s[10]; 169 inv[8] = s[4]*s[9] *s[15] - s[4] *s[11]*s[13] - s[8] *s[5]*s[15] 170 + s[8]*s[7] *s[13] + s[12]*s[5] *s[11] - s[12]*s[7]*s[9]; 171 inv[12] = - s[4]*s[9] *s[14] + s[4] *s[10]*s[13] + s[8] *s[5]*s[14] 172 - s[8]*s[6] *s[13] - s[12]*s[5] *s[10] + s[12]*s[6]*s[9]; 173 174 inv[1] = - s[1]*s[10]*s[15] + s[1] *s[11]*s[14] + s[9] *s[2]*s[15] 175 - s[9]*s[3] *s[14] - s[13]*s[2] *s[11] + s[13]*s[3]*s[10]; 176 inv[5] = s[0]*s[10]*s[15] - s[0] *s[11]*s[14] - s[8] *s[2]*s[15] 177 + s[8]*s[3] *s[14] + s[12]*s[2] *s[11] - s[12]*s[3]*s[10]; 178 inv[9] = - s[0]*s[9] *s[15] + s[0] *s[11]*s[13] + s[8] *s[1]*s[15] 179 - s[8]*s[3] *s[13] - s[12]*s[1] *s[11] + s[12]*s[3]*s[9]; 180 inv[13] = s[0]*s[9] *s[14] - s[0] *s[10]*s[13] - s[8] *s[1]*s[14] 181 + s[8]*s[2] *s[13] + s[12]*s[1] *s[10] - s[12]*s[2]*s[9]; 182 183 inv[2] = s[1]*s[6]*s[15] - s[1] *s[7]*s[14] - s[5] *s[2]*s[15] 184 + s[5]*s[3]*s[14] + s[13]*s[2]*s[7] - s[13]*s[3]*s[6]; 185 inv[6] = - s[0]*s[6]*s[15] + s[0] *s[7]*s[14] + s[4] *s[2]*s[15] 186 - s[4]*s[3]*s[14] - s[12]*s[2]*s[7] + s[12]*s[3]*s[6]; 187 inv[10] = s[0]*s[5]*s[15] - s[0] *s[7]*s[13] - s[4] *s[1]*s[15] 188 + s[4]*s[3]*s[13] + s[12]*s[1]*s[7] - s[12]*s[3]*s[5]; 189 inv[14] = - s[0]*s[5]*s[14] + s[0] *s[6]*s[13] + s[4] *s[1]*s[14] 190 - s[4]*s[2]*s[13] - s[12]*s[1]*s[6] + s[12]*s[2]*s[5]; 191 192 inv[3] = - s[1]*s[6]*s[11] + s[1]*s[7]*s[10] + s[5]*s[2]*s[11] 193 - s[5]*s[3]*s[10] - s[9]*s[2]*s[7] + s[9]*s[3]*s[6]; 194 inv[7] = s[0]*s[6]*s[11] - s[0]*s[7]*s[10] - s[4]*s[2]*s[11] 195 + s[4]*s[3]*s[10] + s[8]*s[2]*s[7] - s[8]*s[3]*s[6]; 196 inv[11] = - s[0]*s[5]*s[11] + s[0]*s[7]*s[9] + s[4]*s[1]*s[11] 197 - s[4]*s[3]*s[9] - s[8]*s[1]*s[7] + s[8]*s[3]*s[5]; 198 inv[15] = s[0]*s[5]*s[10] - s[0]*s[6]*s[9] - s[4]*s[1]*s[10] 199 + s[4]*s[2]*s[9] + s[8]*s[1]*s[6] - s[8]*s[2]*s[5]; 200 201 det = s[0]*inv[0] + s[1]*inv[4] + s[2]*inv[8] + s[3]*inv[12]; 202 if (det === 0) { 203 return this; 204 } 205 206 det = 1 / det; 207 for (i = 0; i < 16; i++) { 208 d[i] = inv[i] * det; 209 } 210 211 return this; 212 }; 213 214 /** 215 * Calculate the inverse matrix of this, and set to this. 216 * @return this 217 */ 218 Matrix4.prototype.invert = function() { 219 return this.setInverseOf(this); 220 }; 221 222 /** 223 * Set the orthographic projection matrix. 224 * @param left The coordinate of the left of clipping plane. 225 * @param right The coordinate of the right of clipping plane. 226 * @param bottom The coordinate of the bottom of clipping plane. 227 * @param top The coordinate of the top top clipping plane. 228 * @param near The distances to the nearer depth clipping plane. This value is minus if the plane is to be behind the viewer. 229 * @param far The distances to the farther depth clipping plane. This value is minus if the plane is to be behind the viewer. 230 * @return this 231 */ 232 Matrix4.prototype.setOrtho = function(left, right, bottom, top, near, far) { 233 var e, rw, rh, rd; 234 235 if (left === right || bottom === top || near === far) { 236 throw 'null frustum'; 237 } 238 239 rw = 1 / (right - left); 240 rh = 1 / (top - bottom); 241 rd = 1 / (far - near); 242 243 e = this.elements; 244 245 e[0] = 2 * rw; 246 e[1] = 0; 247 e[2] = 0; 248 e[3] = 0; 249 250 e[4] = 0; 251 e[5] = 2 * rh; 252 e[6] = 0; 253 e[7] = 0; 254 255 e[8] = 0; 256 e[9] = 0; 257 e[10] = -2 * rd; 258 e[11] = 0; 259 260 e[12] = -(right + left) * rw; 261 e[13] = -(top + bottom) * rh; 262 e[14] = -(far + near) * rd; 263 e[15] = 1; 264 265 return this; 266 }; 267 268 /** 269 * Multiply the orthographic projection matrix from the right. 270 * @param left The coordinate of the left of clipping plane. 271 * @param right The coordinate of the right of clipping plane. 272 * @param bottom The coordinate of the bottom of clipping plane. 273 * @param top The coordinate of the top top clipping plane. 274 * @param near The distances to the nearer depth clipping plane. This value is minus if the plane is to be behind the viewer. 275 * @param far The distances to the farther depth clipping plane. This value is minus if the plane is to be behind the viewer. 276 * @return this 277 */ 278 Matrix4.prototype.ortho = function(left, right, bottom, top, near, far) { 279 return this.concat(new Matrix4().setOrtho(left, right, bottom, top, near, far)); 280 }; 281 282 /** 283 * Set the perspective projection matrix. 284 * @param left The coordinate of the left of clipping plane. 285 * @param right The coordinate of the right of clipping plane. 286 * @param bottom The coordinate of the bottom of clipping plane. 287 * @param top The coordinate of the top top clipping plane. 288 * @param near The distances to the nearer depth clipping plane. This value must be plus value. 289 * @param far The distances to the farther depth clipping plane. This value must be plus value. 290 * @return this 291 */ 292 Matrix4.prototype.setFrustum = function(left, right, bottom, top, near, far) { 293 var e, rw, rh, rd; 294 295 if (left === right || top === bottom || near === far) { 296 throw 'null frustum'; 297 } 298 if (near <= 0) { 299 throw 'near <= 0'; 300 } 301 if (far <= 0) { 302 throw 'far <= 0'; 303 } 304 305 rw = 1 / (right - left); 306 rh = 1 / (top - bottom); 307 rd = 1 / (far - near); 308 309 e = this.elements; 310 311 e[ 0] = 2 * near * rw; 312 e[ 1] = 0; 313 e[ 2] = 0; 314 e[ 3] = 0; 315 316 e[ 4] = 0; 317 e[ 5] = 2 * near * rh; 318 e[ 6] = 0; 319 e[ 7] = 0; 320 321 e[ 8] = (right + left) * rw; 322 e[ 9] = (top + bottom) * rh; 323 e[10] = -(far + near) * rd; 324 e[11] = -1; 325 326 e[12] = 0; 327 e[13] = 0; 328 e[14] = -2 * near * far * rd; 329 e[15] = 0; 330 331 return this; 332 }; 333 334 /** 335 * Multiply the perspective projection matrix from the right. 336 * @param left The coordinate of the left of clipping plane. 337 * @param right The coordinate of the right of clipping plane. 338 * @param bottom The coordinate of the bottom of clipping plane. 339 * @param top The coordinate of the top top clipping plane. 340 * @param near The distances to the nearer depth clipping plane. This value must be plus value. 341 * @param far The distances to the farther depth clipping plane. This value must be plus value. 342 * @return this 343 */ 344 Matrix4.prototype.frustum = function(left, right, bottom, top, near, far) { 345 return this.concat(new Matrix4().setFrustum(left, right, bottom, top, near, far)); 346 }; 347 348 /** 349 * Set the perspective projection matrix by fovy and aspect. 350 * @param fovy The angle between the upper and lower sides of the frustum. 351 * @param aspect The aspect ratio of the frustum. (width/height) 352 * @param near The distances to the nearer depth clipping plane. This value must be plus value. 353 * @param far The distances to the farther depth clipping plane. This value must be plus value. 354 * @return this 355 */ 356 Matrix4.prototype.setPerspective = function(fovy, aspect, near, far) { 357 var e, rd, s, ct; 358 359 if (near === far || aspect === 0) { 360 throw 'null frustum'; 361 } 362 if (near <= 0) { 363 throw 'near <= 0'; 364 } 365 if (far <= 0) { 366 throw 'far <= 0'; 367 } 368 369 fovy = Math.PI * fovy / 180 / 2; 370 s = Math.sin(fovy); 371 if (s === 0) { 372 throw 'null frustum'; 373 } 374 375 rd = 1 / (far - near); 376 ct = Math.cos(fovy) / s; 377 378 e = this.elements; 379 380 e[0] = ct / aspect; 381 e[1] = 0; 382 e[2] = 0; 383 e[3] = 0; 384 385 e[4] = 0; 386 e[5] = ct; 387 e[6] = 0; 388 e[7] = 0; 389 390 e[8] = 0; 391 e[9] = 0; 392 e[10] = -(far + near) * rd; 393 e[11] = -1; 394 395 e[12] = 0; 396 e[13] = 0; 397 e[14] = -2 * near * far * rd; 398 e[15] = 0; 399 400 return this; 401 }; 402 403 /** 404 * Multiply the perspective projection matrix from the right. 405 * @param fovy The angle between the upper and lower sides of the frustum. 406 * @param aspect The aspect ratio of the frustum. (width/height) 407 * @param near The distances to the nearer depth clipping plane. This value must be plus value. 408 * @param far The distances to the farther depth clipping plane. This value must be plus value. 409 * @return this 410 */ 411 Matrix4.prototype.perspective = function(fovy, aspect, near, far) { 412 return this.concat(new Matrix4().setPerspective(fovy, aspect, near, far)); 413 }; 414 415 /** 416 * Set the matrix for scaling. 417 * @param x The scale factor along the X axis 418 * @param y The scale factor along the Y axis 419 * @param z The scale factor along the Z axis 420 * @return this 421 */ 422 Matrix4.prototype.setScale = function(x, y, z) { 423 var e = this.elements; 424 e[0] = x; e[1] = 0; e[2] = 0; e[3] = 0; 425 e[4] = 0; e[5] = y; e[6] = 0; e[7] = 0; 426 e[8] = 0; e[9] = 0; e[10] = z; e[11] = 0; 427 e[12] = 0; e[13] = 0; e[14] = 0; e[15] = 1; 428 return this; 429 }; 430 431 /** 432 * Multiply the matrix for scaling from the right. 433 * @param x The scale factor along the X axis 434 * @param y The scale factor along the Y axis 435 * @param z The scale factor along the Z axis 436 * @return this 437 */ 438 Matrix4.prototype.scale = function(x, y, z) { 439 var e = this.elements; 440 e[0] *= x; e[1] *= y; e[2] *= z; 441 e[4] *= x; e[5] *= y; e[6] *= z; 442 e[8] *= x; e[9] *= y; e[10] *= z; 443 e[12] *= x; e[13] *= y; e[14] *= z; 444 return this; 445 }; 446 447 /** 448 * Set the matrix for translation. 449 * @param x The X value of a translation. 450 * @param y The Y value of a translation. 451 * @param z The Z value of a translation. 452 * @return this 453 */ 454 Matrix4.prototype.setTranslate = function(x, y, z) { 455 var e = this.elements; 456 e[0] = 1; e[4] = 0; e[8] = 0; e[12] = x; 457 e[1] = 0; e[5] = 1; e[9] = 0; e[13] = y; 458 e[2] = 0; e[6] = 0; e[10] = 1; e[14] = z; 459 e[3] = 0; e[7] = 0; e[11] = 0; e[15] = 1; 460 return this; 461 }; 462 463 /** 464 * Multiply the matrix for translation from the right. 465 * @param x The X value of a translation. 466 * @param y The Y value of a translation. 467 * @param z The Z value of a translation. 468 * @return this 469 */ 470 Matrix4.prototype.translate = function(x, y, z) { 471 var e = this.elements; 472 e[12] += e[0] * x + e[4] * y + e[8] * z; 473 e[13] += e[1] * x + e[5] * y + e[9] * z; 474 e[14] += e[2] * x + e[6] * y + e[10] * z; 475 e[15] += e[3] * x + e[7] * y + e[11] * z; 476 return this; 477 }; 478 479 /** 480 * Set the matrix for rotation. 481 * The vector of rotation axis may not be normalized. 482 * @param angle The angle of rotation (degrees) 483 * @param x The X coordinate of vector of rotation axis. 484 * @param y The Y coordinate of vector of rotation axis. 485 * @param z The Z coordinate of vector of rotation axis. 486 * @return this 487 */ 488 Matrix4.prototype.setRotate = function(angle, x, y, z) {//webgl矩阵系统是行主序 489 var e, s, c, len, rlen, nc, xy, yz, zx, xs, ys, zs; 490 491 angle = Math.PI * angle / 180; 492 e = this.elements; 493 494 s = Math.sin(angle); 495 c = Math.cos(angle); 496 497 if (0 !== x && 0 === y && 0 === z) { 498 // Rotation around X axis 499 if (x < 0) { 500 s = -s; 501 } 502 e[0] = 1; e[1] = 0; e[ 2] = 0; e[3] = 0; 503 e[4] = 0; e[5] = c; e[ 6] =-s; e[7] = 0; 504 e[8] = 0; e[9] = s; e[10] = c; e[11] = 0; 505 e[12] = 0; e[13] = 0; e[14] = 0; e[15] = 1; 506 } else if (0 === x && 0 !== y && 0 === z) { 507 // Rotation around Y axis 508 if (y < 0) { 509 s = -s; 510 } 511 e[0] = c; e[1] = 0; e[ 2] = s; e[3] = 0; 512 e[4] = 0; e[5] = 1; e[ 5] = 0; e[7] = 0; 513 e[8] =-s; e[9] = 0; e[10] = c; e[11] = 0; 514 e[12] = 0; e[13] = 0; e[14] = 0; e[15] = 1; 515 } else if (0 === x && 0 === y && 0 !== z) { 516 // Rotation around Z axis 517 if (z < 0) { 518 s = -s; 519 } 520 e[0] = c; e[1] =-s; e[ 2] = 0; e[3] = 0; 521 e[4] = s; e[5] = c; e[ 6] = 0; e[7] = 0; 522 e[8] = 0; e[9] = 0; e[10] = 1; e[11] = 0; 523 e[12] = 0; e[13] = 0; e[14] = 0; e[15] = 1; 524 } else { 525 // Rotation around another axis 526 len = Math.sqrt(x*x + y*y + z*z); 527 if (len !== 1) { 528 rlen = 1 / len; 529 x *= rlen; 530 y *= rlen; 531 z *= rlen; 532 } 533 nc = 1 - c; 534 xy = x * y; 535 yz = y * z; 536 zx = z * x; 537 xs = x * s; 538 ys = y * s; 539 zs = z * s; 540 541 e[ 0] = x*x*nc + c; 542 e[ 1] = xy *nc + zs; 543 e[ 2] = zx *nc - ys; 544 e[ 3] = 0; 545 546 e[ 4] = xy *nc - zs; 547 e[ 5] = y*y*nc + c; 548 e[ 6] = yz *nc + xs; 549 e[ 7] = 0; 550 551 e[ 8] = zx *nc + ys; 552 e[ 9] = yz *nc - xs; 553 e[10] = z*z*nc + c; 554 e[11] = 0; 555 556 e[12] = 0; 557 e[13] = 0; 558 e[14] = 0; 559 e[15] = 1; 560 } 561 562 return this; 563 }; 564 565 /** 566 * Multiply the matrix for rotation from the right. 567 * The vector of rotation axis may not be normalized. 568 * @param angle The angle of rotation (degrees) 569 * @param x The X coordinate of vector of rotation axis. 570 * @param y The Y coordinate of vector of rotation axis. 571 * @param z The Z coordinate of vector of rotation axis. 572 * @return this 573 */ 574 Matrix4.prototype.rotate = function(angle, x, y, z) { 575 return this.concat(new Matrix4().setRotate(angle, x, y, z)); 576 }; 577 578 /** 579 * Set the viewing matrix. 580 * @param eyeX, eyeY, eyeZ The position of the eye point. 581 * @param centerX, centerY, centerZ The position of the reference point. 582 * @param upX, upY, upZ The direction of the up vector. 583 * @return this 584 */ 585 Matrix4.prototype.setLookAt = function(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ) { 586 var e, fx, fy, fz, rlf, sx, sy, sz, rls, ux, uy, uz; 587 588 fx = centerX - eyeX; 589 fy = centerY - eyeY; 590 fz = centerZ - eyeZ; 591 592 // Normalize f. 593 rlf = 1 / Math.sqrt(fx*fx + fy*fy + fz*fz); 594 fx *= rlf; 595 fy *= rlf; 596 fz *= rlf; 597 598 // Calculate cross product of f and up. 599 sx = fy * upZ - fz * upY; 600 sy = fz * upX - fx * upZ; 601 sz = fx * upY - fy * upX; 602 603 // Normalize s. 604 rls = 1 / Math.sqrt(sx*sx + sy*sy + sz*sz); 605 sx *= rls; 606 sy *= rls; 607 sz *= rls; 608 609 // Calculate cross product of s and f. 610 ux = sy * fz - sz * fy; 611 uy = sz * fx - sx * fz; 612 uz = sx * fy - sy * fx; 613 614 // Set to this. 615 e = this.elements; 616 e[0] = sx; 617 e[1] = ux; 618 e[2] = -fx; 619 e[3] = 0; 620 621 e[4] = sy; 622 e[5] = uy; 623 e[6] = -fy; 624 e[7] = 0; 625 626 e[8] = sz; 627 e[9] = uz; 628 e[10] = -fz; 629 e[11] = 0; 630 631 e[12] = 0; 632 e[13] = 0; 633 e[14] = 0; 634 e[15] = 1; 635 636 // Translate. 637 return this.translate(-eyeX, -eyeY, -eyeZ); 638 }; 639 640 /** 641 * Multiply the viewing matrix from the right. 642 * @param eyeX, eyeY, eyeZ The position of the eye point. 643 * @param centerX, centerY, centerZ The position of the reference point. 644 * @param upX, upY, upZ The direction of the up vector. 645 * @return this 646 */ 647 Matrix4.prototype.lookAt = function(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ) { 648 return this.concat(new Matrix4().setLookAt(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ)); 649 }; 650 651 /** 652 * Multiply the matrix for project vertex to plane from the right. 653 * @param plane The array[A, B, C, D] of the equation of plane "Ax + By + Cz + D = 0". 654 * @param light The array which stored coordinates of the light. if light[3]=0, treated as parallel light. 655 * @return this 656 */ 657 Matrix4.prototype.dropShadow = function(plane, light) { 658 var mat = new Matrix4(); 659 var e = mat.elements; 660 661 var dot = plane[0] * light[0] + plane[1] * light[1] + plane[2] * light[2] + plane[3] * light[3]; 662 663 e[ 0] = dot - light[0] * plane[0]; 664 e[ 1] = - light[1] * plane[0]; 665 e[ 2] = - light[2] * plane[0]; 666 e[ 3] = - light[3] * plane[0]; 667 668 e[ 4] = - light[0] * plane[1]; 669 e[ 5] = dot - light[1] * plane[1]; 670 e[ 6] = - light[2] * plane[1]; 671 e[ 7] = - light[3] * plane[1]; 672 673 e[ 8] = - light[0] * plane[2]; 674 e[ 9] = - light[1] * plane[2]; 675 e[10] = dot - light[2] * plane[2]; 676 e[11] = - light[3] * plane[2]; 677 678 e[12] = - light[0] * plane[3]; 679 e[13] = - light[1] * plane[3]; 680 e[14] = - light[2] * plane[3]; 681 e[15] = dot - light[3] * plane[3]; 682 683 return this.concat(mat); 684 } 685 686 /** 687 * Multiply the matrix for project vertex to plane from the right.(Projected by parallel light.) 688 * @param normX, normY, normZ The normal vector of the plane.(Not necessary to be normalized.) 689 * @param planeX, planeY, planeZ The coordinate of arbitrary points on a plane. 690 * @param lightX, lightY, lightZ The vector of the direction of light.(Not necessary to be normalized.) 691 * @return this 692 */ 693 Matrix4.prototype.dropShadowDirectionally = function(normX, normY, normZ, planeX, planeY, planeZ, lightX, lightY, lightZ) { 694 var a = planeX * normX + planeY * normY + planeZ * normZ; 695 return this.dropShadow([normX, normY, normZ, -a], [lightX, lightY, lightZ, 0]); 696 }; 697 698 /** 699 * Constructor of Vector3 700 * If opt_src is specified, new vector is initialized by opt_src. 701 * @param opt_src source vector(option) 702 */ 703 var Vector3 = function(opt_src) { 704 var v = new Float32Array(3); 705 if (opt_src && typeof opt_src === 'object') { 706 v[0] = opt_src[0]; v[1] = opt_src[1]; v[2] = opt_src[2]; 707 } 708 this.elements = v; 709 } 710 711 /** 712 * Normalize. 713 * @return this 714 */ 715 Vector3.prototype.normalize = function() { 716 var v = this.elements; 717 var c = v[0], d = v[1], e = v[2], g = Math.sqrt(c*c+d*d+e*e); 718 if(g){ 719 if(g == 1) 720 return this; 721 } else { 722 v[0] = 0; v[1] = 0; v[2] = 0; 723 return this; 724 } 725 g = 1/g; 726 v[0] = c*g; v[1] = d*g; v[2] = e*g; 727 return this; 728 }; 729 730 /** 731 * Constructor of Vector4 732 * If opt_src is specified, new vector is initialized by opt_src. 733 * @param opt_src source vector(option) 734 */ 735 var Vector4 = function(opt_src) { 736 var v = new Float32Array(4); 737 if (opt_src && typeof opt_src === 'object') { 738 v[0] = opt_src[0]; v[1] = opt_src[1]; v[2] = opt_src[2]; v[3] = opt_src[3]; 739 } 740 this.elements = v; 741 }
上面是修改过的矩阵类库文件。
因为齐次坐标W=1时 X,Y,Z 表示坐标中的一个点。所以目前只考虑W=1 因此变换矩阵的[3][1-2]都为0.0 [3][3]为1 以后除非涉及到W不为1 不然不在做出说明
如果将矩阵视作二维数组 point=matrix*oldpint ; 则 point.x=matrix[0][0]*oldpint.x+matrix[0][1]*oldpint.y+matrix[0][2]*oldpint.z+ matrix[0][3] *W
point.y ,point.z ,point.w 同上式相同第一纬度依次+1 第二纬度不变;
假设旋转P角度
从坐标系中可得 x=rcosa;y=rsina x2=rcos(a+b); y2=rsin(a+b)
根据三角函数:sin(a+b)=sinacosb-cosasinb
cos(a+b)=cosacosb-sinasinb
可以得出x2=r(cosacosb-sinasinb)
y2=r(sinacosb+cosasinb)
最终得到:x2=xcosp-ysinp;y2=xsinp+ycosp; 目前只绘制平面图形所以z2=z;
由上式可知道。如果需要平移只需要在矩阵第二纬度的3号索引处根据第一纬度索引0=X ,1=Y,2=Z 的原则增加平移量 而[0][0],[1][1],[2][2]设置为1.0。 其余为0.0即可
如果需要进行缩放 只需将 而[0][0],[1][1],[2][2]设置为对应的缩放比例(0为X,1为Y,2为Z)
注意:不要应该在一个矩阵中进行多个变换操作,如果需要平移再缩放应该用 缩放矩阵×平移矩阵(注意矩阵不符合乘法交换律,一般矩阵相乘顺序与你需要进行的变换操作顺序相反)用得到的矩阵去进行变换
另外GLSE中为FLOAT的值必须赋值为浮点型的值(主要是着色器声明那一块)