【WebGL初学系列之五】旋转,平移,缩放

nbcoder.com地址:http://nbcoders.com/webgl-chu-xue-xi-lie-zhi-wu-ai.html

    最近把WebGL做的相关Demo已经放在 http://www.nbcoders.com 上了,这样就可以直观的进行看效果。
    地址:    http://lab.nbcoders.com/ixshells/ 
    本文旋转平移缩放Demo的地址: http://lab.nbcoders.com/ixshells/Html/ScaleRotateTranslate.html 
    好吧,回到本文。从Demo中我们可以看出,这里画出了三个三角形,也就是三个模型。让后对这三个模型分别进行旋转,平移,缩放。所以,在从上几篇文章的内容来看,这里增加了多模型操作和旋转,平移,缩放操作。所以,文章从以下的步骤进行总结讲解:
    1. 初步了解矩阵操作(因为多模型和平移旋转缩放操作都需要用到矩阵操作,矩阵操作很重要,在WebGL中用处相当大)。
    2. 建立多个模型。
    3. 进行旋转,平移,缩放操作。

1 : 了解矩阵的基本操作
    矩阵的计算,其实也不复杂。在WebGL中重要的不是具体的计算方法,而是使用方法,在WebGL中最关心的是矩阵操作中最后所得到的结果。这里为了让自己印象深刻一些,还是简单的介绍一下对于WebGL相关的矩阵计算操作,。
    因为我们在后面不会直接用到矩阵计算相关,所以这里就简单举一个平移的例子,如果要了解更多矩阵计算的相关操作,可以去看看线性代数相关内容。平移是说的对象的每一个顶点都移动一个相同的距离。平移矩阵和某点p的表示如下:
这里将平移矩阵和点p的矩阵矩阵相乘,结果如下:
矩阵的计算已经知道了,但是在WebGL中,我们并不是关心的矩阵计算的过程。  所以矩阵计算的操作用了glMatrix-0.9.5.js,它提供了矩阵向量和矩阵类,封装了一些矩阵和相关的一些操作。具体glMatrix-0.9.5.js相关函数就不具体讲解了,用到的时候可以去查阅相关资料。

2. 建立多个模型
    前面我们已经绘制出了单个模型,要绘制多个模型。首先得让多个模型绘制在不同的位置上,所以要操作模型变换矩阵的坐标变换矩阵。视口矩阵和投影变换矩阵都可以不用变,只要我们绘制在多个模型都看得到的范围内就行了。这里将每个三角形进行了缩放,这样让每个模型都能够显示出来。最后,分别绘制出每个模型,多个模型就绘制出来了。代码如下:
  <span style="white-space:pre">		</span>/*一个模型*/
                //创建第一个模型矩阵
                var m4Rotate = mat4.create();
                //置为单位矩阵
                mat4.identity(m4Rotate);
                //缩放
                mat4.scale(m4Rotate, [0.5, 0.5, 1.0], m4Rotate);
                webgl.uniformMatrix4fv(uniformIndex, false, m4Rotate);
                webgl.drawArrays(webgl.TRIANGLES, 0, 3);
                /*第二个模型*/
                //创建第二个模型矩阵
                var translate = mat4.create();
                //置为单位矩阵
                mat4.identity(translate);
                //移动第二个模型的位置
                mat4.translate(translate, [0.5, 0.5, 0.0], translate);
                //缩放
                mat4.scale(translate, [0.5, 0.5, 0.0], translate);
                webgl.uniformMatrix4fv(uniformIndex, false, translate);
                webgl.drawArrays(webgl.TRIANGLES, 0, 3);
               
                /*第三个模型*/
                //创建第三个模型矩阵
                var scaleM = mat4.create();
                //置为单位矩阵
                mat4.identity(scaleM);
                //移动第三个模型位置
                mat4.translate(scaleM, [-0.5, 0.5, 0.0], scaleM);
                //缩放
                mat4.scale(scaleM, [0.5, 0.5, 0.0], scaleM);
                webgl.uniformMatrix4fv(uniformIndex, false, scaleM);
                webgl.drawArrays(webgl.TRIANGLES, 0, 3);
 当然,shader代码也有所改变:
 <span style="white-space:pre">	</span><script id="shader-vs" type="x-shader/x-vertex">
            attribute vec3 v3Position;
            uniform mat4 umMatrix;
            attribute vec3 av3Color;
            varying vec3 vv3Color;
            void main(void)
            {
                vec4 v4pos = umMatrix * vec4(v3Position, 1.0);
                vv3Color = av3Color;
                gl_Position = v4pos;
            }
        </script>

3. 旋转,平移,缩放
    从上面绘制出了多个模型后,这里的步骤其实就已经算简单了。我们要让每个模型动起来,这里设置一个定时器来定时渲染。
 <span style="white-space:pre">	</span>   window.setInterval("changeData()", 10);

             function changeData()
            {
                angle += 10;
                angle %= 360;
                xPos <= 1.0 ? xPos += 0.005 : xPos = -1;
                yPos <= 1.0 ? yPos += 0.005 : yPos = -1;
                scale >= 0.0 ? scale -= 0.005 : scale = 0.5;
                renderScene(webglCanvas);
            }
 让后在每一帧改变每个模型的数据。即旋转角度,平移坐标,缩放大小值等数据。红色部分是与上面不同部分,给出代码如下:
                 /*一个模型*/
                //创建第一个模型矩阵
                var m4Rotate = mat4.create();
                //置为单位矩阵
                mat4.identity(m4Rotate);
                //绕Z轴旋转
                <span style="color:#ff0000;">mat4.rotateZ(m4Rotate, angle * Math.PI / 180);</span>
                //缩放
                mat4.scale(m4Rotate, [0.5, 0.5, 1.0], m4Rotate);
                webgl.uniformMatrix4fv(uniformIndex, false, m4Rotate);
                webgl.drawArrays(webgl.TRIANGLES, 0, 3);
                /*第二个模型*/
                //创建第二个模型矩阵
                var translate = mat4.create();
                //置为单位矩阵
                mat4.identity(translate);
                //移动第二个模型的位置
                <span style="color:#ff0000;">mat4.translate(translate, [xPos, yPos, 0.0], translate);</span>
                //缩放
                mat4.scale(translate, [0.5, 0.5, 0.0], translate);
                webgl.uniformMatrix4fv(uniformIndex, false, translate);
                webgl.drawArrays(webgl.TRIANGLES, 0, 3);
               
                /*第三个模型*/
                //创建第三个模型矩阵
                var scaleM = mat4.create();
                //置为单位矩阵
                mat4.identity(scaleM);
                //移动第三个模型位置
                mat4.translate(scaleM, [-0.5, 0.5, 0.0], scaleM);
                //缩放
               <span style="color:#ff0000;"> mat4.scale(scaleM, [scale, scale, 0.0], scaleM);</span>
                webgl.uniformMatrix4fv(uniformIndex, false, scaleM);
                webgl.drawArrays(webgl.TRIANGLES, 0, 3);

4. 完整代码:
<html>
 <head>
        <script type="text/javascript" src="../Js/InitWebGL.js"></script>
        <script type="text/javascript" src ="../3dPart/glMatrix-0.9.5.js"></script>
        <script id="shader-vs" type="x-shader/x-vertex">
            attribute vec3 v3Position;
            uniform mat4 umMatrix;
            attribute vec3 av3Color;
            varying vec3 vv3Color;
            void main(void)
            {
                vec4 v4pos = umMatrix * vec4(v3Position, 1.0);
                vv3Color = av3Color;
                gl_Position = v4pos;
            }
        </script>
           
        <script id ="shader-fs" type ="x-shader/x-fragment">
            #ifdef GL_FRAGMENT_PRECISION_HIGH
                precision highp float;
            #else
                precision mediump float;
            #endif
            varying vec3 vv3Color;
            void main(void)
            {
               gl_FragColor = vec4(vv3Color, 1.0);
            }
        </script>
        <script>
            var v3PositionIndex = 0;
            var sampleTexIndex = -1;
            var triangleBuffer = null;
            var triangleBuffer = null;
            var textObj = null;
            var angle = 0;
            var scale = 0.5;
            var xPos = -1.0;
            var yPos = -1.0;
            var webglCanvas = null;
            var uniformIndex = -1;
            var v3ColorIndex = 1;
            var triangleColorBuffer = null;
            function initData(webgl)
            {
                //顶点坐标
                var jsArrayData = [
                     0.0, 1.0, 0.0,
                    -1.0, 0.0, -1.0,
                     1.0, 0.0, 0.0
                ]
                //创建一个webgl能够访问的缓冲
                triangleBuffer = webgl.createBuffer();
                //绑定buffer
                webgl.bindBuffer(webgl.ARRAY_BUFFER, triangleBuffer);
                //将js数据拷贝到buffer上
                webgl.bufferData(webgl.ARRAY_BUFFER, new Float32Array(jsArrayData), webgl.STATIC_DRAW);
                var jsArrayColor = [
                   1.0, 0.0, 0.0,//上顶点
                   0.0, 1.0, 0.0,//左顶点
                   0.0, 0.0, 1.0 //右顶点
                ];
                triangleColorBuffer = webgl.createBuffer();
                webgl.bindBuffer(webgl.ARRAY_BUFFER, triangleColorBuffer);
                webgl.bufferData(webgl.ARRAY_BUFFER, new Float32Array(jsArrayColor), webgl.STATIC_DRAW);
            }
            function renderScene(webgl)
            {
                //清空屏幕
                webgl.clearColor(0.0, 0.0, 0.0, 1.0);
                webgl.clear(webgl.COLOR_BUFFER_BIT);
                //绑定顶点数据
                webgl.bindBuffer(webgl.ARRAY_BUFFER, triangleBuffer);
                //启动开关
                webgl.enableVertexAttribArray(v3PositionIndex);
                //制定数据索引原则
                webgl.vertexAttribPointer(v3PositionIndex, 3, webgl.FLOAT, false, 0, 0);
                webgl.bindBuffer(webgl.ARRAY_BUFFER, triangleColorBuffer);
                webgl.enableVertexAttribArray(v3ColorIndex);
                webgl.vertexAttribPointer(v3ColorIndex, 3, webgl.FLOAT, false, 0, 0);
                /*一个模型*/
                //创建第一个模型矩阵
                var m4Rotate = mat4.create();
                //置为单位矩阵
                mat4.identity(m4Rotate);
                //绕Z轴旋转
                mat4.rotateZ(m4Rotate, angle * Math.PI / 180);
                //缩放
                mat4.scale(m4Rotate, [0.5, 0.5, 1.0], m4Rotate);
                webgl.uniformMatrix4fv(uniformIndex, false, m4Rotate);
                webgl.drawArrays(webgl.TRIANGLES, 0, 3);
                /*第二个模型*/
                //创建第二个模型矩阵
                var translate = mat4.create();
                //置为单位矩阵
                mat4.identity(translate);
                //移动第二个模型的位置
                mat4.translate(translate, [xPos, yPos, 0.0], translate);
                //缩放
                mat4.scale(translate, [0.5, 0.5, 0.0], translate);
                webgl.uniformMatrix4fv(uniformIndex, false, translate);
                webgl.drawArrays(webgl.TRIANGLES, 0, 3);
               
                /*第三个模型*/
                //创建第三个模型矩阵
                var scaleM = mat4.create();
                //置为单位矩阵
                mat4.identity(scaleM);
                //移动第三个模型位置
                mat4.translate(scaleM, [-0.5, 0.5, 0.0], scaleM);
                //缩放
                mat4.scale(scaleM, [scale, scale, 0.0], scaleM);
                webgl.uniformMatrix4fv(uniformIndex, false, scaleM);
                webgl.drawArrays(webgl.TRIANGLES, 0, 3);
                webgl.flush();
            }
            function init()
            {
                //获取webgl canvas
                var canvas = initCanvas("webglCanvas");
                //初始化shader程序
                var bind1 = [v3PositionIndex, "v3Position"];
                var bind2 = [v3ColorIndex, "av3Color"];
                var bindData = new Array();
                bindData.push(bind1);
                var shaderProgramObject = initShaders(canvas, "shader-vs", "shader-fs", bindData);
                //获取Uniform变量在链接时生成的索引
                //sampleTexIndex = canvas.getUniformLocation(shaderProgramObject, "sTexture");
                uniformIndex = canvas.getUniformLocation(shaderProgramObject, "umMatrix");
                canvas.useProgram(shaderProgramObject);
                //初始化顶点数据
                initData(canvas);
                webglCanvas = canvas;
                window.setInterval("changeData()", 10);
            }
            function changeData()
            {
                angle += 10;
                angle %= 360;
                xPos <= 1.0 ? xPos += 0.005 : xPos = -1;
                yPos <= 1.0 ? yPos += 0.005 : yPos = -1;
                scale >= 0.0 ? scale -= 0.005 : scale = 0.5;
                renderScene(webglCanvas);
            }
        </script>
 </head>
 <body onload ="init()">
  <canvas id="webglCanvas" style="border:1px solid red" width="600" height="600"></canvas>
 </body>
</html>
    

5.效果展示





郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。