您的位置:首页 > 其它

webgl模型矩阵

2018-03-28 09:27 162 查看
模型矩阵在webgl中表示 模型的缩放 旋转 平移的
所以模型矩阵包含了 
旋转矩阵:



缩放矩阵:



平移矩阵:



下面给出一份演示:<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
body{
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<canvas id="cvs" width="800" height="800"></canvas>
<div></div>
<button onclick="move('a')">右移动</button>
<button onclick="move('b')">左移动</button>
<button onclick="move('c')">上移动</button>
<button onclick="move('d')">下移动</button>
<button onclick="move('f')">放大</button>
<button onclick="move('e')">缩小</button>
<script id="vertex" type="text/v-shader">
precision highp float;
attribute vec3 position;
uniform mat4 mat;
varying vec4 color;
void main(){
gl_Position=mat*vec4(position,1.0);

color=vec4(gl_Position.x,gl_Position.y,gl_Position.z,0.8);}
</script>
<script id="fragment" type="text/f-shader">
#ifdef GL_ES
precision mediump float;
#endif
varying vec4 color;
void main(){
gl_FragColor=color;
}
</script>

<script type="text/javascript">
var xInt = 0.0;
function move(num){
if(num=="a"){

moveX(0.05);
}else if(num=="b"){

moveX(-0.05);
}else if(num=="c"){
moveY(0.05);
}else if(num=="d"){
moveY(-0.05);
}else if(num=="e"){
scaleFun(0.9);
}else if(num=="f"){
scaleFun(1.1);
}
}
(function(global){
var cvs = document.getElementById("cvs");
var gl = cvs.getContext("experimental-webgl");
var vertex = gl.createShader(gl.VERTEX_SHADER);
var fragment = gl.createShader(gl.FRAGMENT_SHADER);
var paogram = gl.createProgram();

gl.shaderSource(vertex,document.getElementById("vertex").text);
gl.shaderSource(fragment,document.getElementById("fragment").text);
gl.compileShader(vertex);
gl.compileShader(fragment);
gl.attachShader(paogram,vertex);
gl.attachShader(paogram,fragment);
gl.linkProgram(paogram);
gl.useProgram(paogram);

var data = [
0.5,0.5,0.5,
0.5,-0.5,0.5,
-0.5,0.5,0.5,
-0.5,0.5,0.5,
-0.5,-0.5,0.5,
0.5,-0.5,0.5,

0.5,0.5,-0.5,
0.5,-0.5,-0.5,
-0.5,0.5,-0.5,
-0.5,0.5,-0.5,
-0.5,-0.5,-0.5,
0.5,-0.5,-0.5,

0.5,0.5,0.5,
0.5,0.5,-0.5,
0.5,-0.5,-0.5,
0.5,0.5,0.5,
0.5,-0.5,0.5,
0.5,-0.5,-0.5,

-0.5,0.5,0.5,
-0.5,0.5,-0.5,
-0.5,-0.5,-0.5,
-0.5,0.5,0.5,
-0.5,-0.5,0.5,
-0.5,-0.5,-0.5,

0.5,0.5,0.5,
-0.5,0.5,0.5,
-0.5,0.5,-0.5,
0.5,0.5,0.5,
0.5,0.5,-0.5,
-0.5,0.5,-0.5,

0.5,-0.5,0.5,
-0.5,-0.5,0.5,
-0.5,-0.5,-0.5,
0.5,-0.5,0.5,
0.5,-0.5,-0.5,
-0.5,-0.5,-0.5

];
var positionIndex = gl.getAttribLocation(paogram,"position");
var matIndex = gl.getUniformLocation(paogram,"mat");
console.log(gl.getShaderInfoLog(vertex));
var mM=[
1,0,0,0,
0,1,0,0,
0,0,1,0,
0,0,0,1
];
console.log(gl.getShaderInfoLog(fragment));

global.rotateX=function (angle){
var c = Math.cos(Math.PI/180*angle);
var s = Math.sin(Math.PI/180*angle);
var mM1=mM[1],mM5=mM[5],mM9=mM[9];
mM[1] = c*mM[1] - s*mM[2];
mM[5] = c*mM[5] - s*mM[6];
mM[9] = c*mM[9] - s*mM[10];

mM[2]=s*mM1+c*mM[2];
mM[6]=s*mM5+c*mM[6];
mM[10]=s*mM9+c*mM[10];

};
global.rotateY=function (angle){
var c = Math.cos(Math.PI/180*angle);
var s = Math.sin(Math.PI/180*angle);
var mM0=mM[0],mM8=mM[8],mM4=mM[4];
mM[0] = c*mM[0] + s*mM[2];
mM[4] = c*mM[4] + s*mM[6];
mM[8] = c*mM[8] + s*mM[10];

mM[2] = c*mM[2]-s*mM0;
mM[6] = c*mM[6]-s*mM4;
mM[10] = c*mM[10]-s*mM8;
};
global.rotateZ=function (angle){
var c = Math.cos(Math.PI/180*angle);
var s = Math.sin(Math.PI/180*angle);
var mM0=mM[0],mM4=mM[4],mM8=mM[8];
mM[0] = c*mM[0]-s*mM[1];
mM[4] = c*mM[4]-s*mM[5];
mM[8] = c*mM[8]-s*mM[9];

mM[1]=s*mM0+c*mM[1];
mM[5]=s*mM4+c*mM[5];
mM[9]=s*mM8+c*mM[9];
};
global.moveX= function(distance){
mM[0]=mM[0]+distance*mM[3];
mM[4]=mM[4]+distance*mM[7];
mM[8]=mM[8]+distance*mM[11];
mM[12]=mM[12]+distance*mM[15];
};
global.moveY= function(distance){
mM[1]=distance*mM[3]+mM[1];
mM[5]=distance*mM[7]+mM[5];
mM[9]=distance*mM[11]+mM[9];
mM[13]=distance*mM[15]+mM[13];
};
global.moveZ= function(distance){
mM[2]=distance*mM[3]+mM[2];
mM[6]=distance*mM[7]+mM[6];
mM[10]=distance*mM[11]+mM[10];
mM[14]=distance*mM[15]+mM[14];
};
global.scaleFun=function(scale){
mM[0]=scale*mM[0];
mM[4]=scale*mM[4];
mM[8]=scale*mM[8];
mM[12]=scale*mM[12];
mM[1]=scale*mM[1];
mM[5]=scale*mM[5];
mM[9]=scale*mM[9];
mM[13]=scale*mM[13];
mM[2]=scale*mM[2];
mM[6]=scale*mM[6];
mM[10]=scale*mM[10];
mM[14]=scale*mM[14];
};
var buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,buffer);
gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(data),gl.STATIC_DRAW);
gl.vertexAttribPointer(positionIndex,3,gl.FLOAT,false,0,0);

gl.enableVertexAttribArray(positionIndex);
var dis= 0.05;
var angle=0.5;
function fun(){

rotateX(angle);
rotateY(angle);
rotateZ(angle);

gl.uniformMatrix4fv(matIndex,false,new Float32Array(mM));
gl.clearColor(0.5, 0.5, 0.5, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLES,0,30);
requestAnimationFrame(fun);
}
fun();

})(window);
</script>
</body>
</html>上面的演示演示了 模型矩阵的一些使用
我们知道模型矩阵*vec4这个表示顶点的信息

变量mM在上面的列子中表示模型矩阵

在学习之前应该先了解一下矩阵相乘的概念:



可以看到是行乘以列得到新的行和列

webgl中我们采用一维数组表示矩阵.
那么问题来了 这个一维数组的前四个元素是表示列还是行啦?
在webgl中前四个元素表示列

设模型矩阵的位置关系是这样的
[
0,1,2,3,
4,5,6,7,
8,9,10,11,
12,13,14,15
]

下面来逐一介绍各个函数:

rotateX 沿着X轴旋转的旋转矩阵
其实就是沿着X轴旋转的矩阵乘以 模型矩阵最后得到一个新的矩阵
因为webgl中前四个元素表示列所以我们用X轴旋转矩阵乘以模型矩阵的前四个元素就表示行乘以列了
最终得到mM[0] =c*mM[1] - s*mM[2];
因为webgl中前四个元素表示列所以mM[1]就不是第一行的元素了 mM[4]才是第一行的第二个元素 所以得到
 mM[5] = c*mM[5] - s*mM[6];

还是同上面的理由可以得到
mM[9] = c*mM[9] - s*mM[10];

rotateX旋转的方法就到这里介绍完毕了 
rotateY和rotateZ都可以经过上面的原理进行推理得到结果

下面介绍moveX方法
moveX方法其实是平移矩阵乘以模型矩阵然后得到一个新的矩阵
根据上面平移矩阵的信息可以知道
我们如果以X轴移动那么就有这样的矩阵
[
    1,0,0,x,

    0,1,0,0,
    0,0,1,0,

    0,0,0,1

]
根据矩阵相乘的原理和webgl数组前四个元素表示列的原理可以知道
mM[0]=mM[0]+distance*mM[3];
mM[4]=mM[4]+distance*mM[7];
mM[8]=mM[8]+distance*mM[11];
mM[12]=mM[12]+distance*mM[15];矩阵相乘的结果

moveY 方法:
moveY其实是矩阵

[
    1,0,0,0,

    0,1,0,y,
    0,0,1,0,

    0,0,0,1

]
乘以模型矩阵得到结果
以此类推可以知道moveZ的结果了吧

下面介绍scaleFun的原理
缩放函数其实是缩放矩阵乘以模型矩阵然后得到一个新的矩阵
[
    x,0,0,0,
    0,y,0,0,

    0,0,z,0,

    0,0,0,1

]
为什么缩放矩阵X Y Z都是在一个方法里面执行的拉 是因为楼主在写的时候 写了scaleX 和scaleY ,scaleZ 但是发现模型变形了所以就将缩放矩阵放到一起 就得到上面的结果 原来缩放要一起缩放 

下面说下为什么在执行了方法过后 即mM数组改变了 模型为什么会改变
是因为楼主在演示的最后加一个requestAnimationFrame方法 让模型一直在更新 并把mM数组赋值到着色器语言的mat变量里面
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息