webgl模型矩阵

模型矩阵在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 οnclick="move('a')">右移动</button>
<button οnclick="move('b')">左移动</button>
<button οnclick="move('c')">上移动</button>
<button οnclick="move('d')">下移动</button>
<button οnclick="move('f')">放大</button>
<button οnclick="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变量里面






  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值