首页 > 代码库 > 04 绘制正方体和位移矩阵

04 绘制正方体和位移矩阵

    我们首先绘制一个正方体,它有8个顶点,6个面。每个面由2个三角形组成,一共12个三角形,所以顶点索引是12个。为了保证所有的面向外,三角形顶点顺序由前面介绍的右手定则确定。

    生成正方体后,我们给它加一个位移矩阵。使用矩阵表示位移是非常不直观的,所以我们借助THREEJS,将欧拉角转换为矩阵,然后传递给着色器程序。着色器程序只要简单左乘顶点坐标就好了。借助上一节贴图的知识,我们可以给正方体六个面贴图,这里为了程序简洁明了,就不示范了。

  1 <!DOCTYPE html>
  2 
  3 <html lang="zh-CN">
  4 
  5 <head>
  6     <meta charset="UTF-8" />
  7     <title>04_绘制正方体和位移矩阵</title>
  8     <script src="../js/three.js"></script>
  9 
 10     <!-- 顶点着色器 -->
 11     <script id="shader-vs" type="x-shader/x-vertex">
 12         attribute vec3 aVertexPosition; // 顶点坐标
 13         uniform mat4 uMVMatrix; // 位移矩阵
 14 
 15         void main(void) {
 16         gl_Position = uMVMatrix * vec4(aVertexPosition, 1.0);
 17         }
 18     </script>
 19 
 20     <!-- 片源着色器 -->
 21     <script id="shader-fs" type="x-shader/x-fragment">
 22         precision mediump float;
 23         varying vec4 vColor;
 24 
 25         void main(void) {
 26         gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);
 27         }
 28     </script>
 29 
 30     <script type="text/javascript">
 31         var start = function () {
 32             // 上下文环境
 33             var canvas = document.getElementById("mycanvas");
 34             var gl = canvas.getContext("experimental-webgl");
 35             gl.viewportWidth = canvas.width;
 36             gl.viewportHeight = canvas.height;
 37             gl.viewport(0, 0, gl.viewportWidth, gl.viewportWidth);
 38             gl.clearColor(0.0, 0.0, 0.0, 1.0);
 39             gl.enable(gl.DEPTH_TEST);
 40 
 41             // 顶点着色器
 42             var shader = gl.createShader(gl.VERTEX_SHADER);
 43             gl.shaderSource(shader, document.getElementById(shader-vs).innerHTML);
 44             gl.compileShader(shader);
 45             var vertexShader = shader;
 46 
 47             // 片源着色器
 48             var shader = gl.createShader(gl.FRAGMENT_SHADER);
 49             gl.shaderSource(shader, document.getElementById(shader-fs).innerHTML);
 50             gl.compileShader(shader);
 51             var fragmentShader = shader;
 52 
 53             // 着色器程序
 54             var shaderProgram = gl.createProgram();
 55             gl.attachShader(shaderProgram, vertexShader);
 56             gl.attachShader(shaderProgram, fragmentShader);
 57             gl.linkProgram(shaderProgram);
 58             gl.useProgram(shaderProgram);
 59 
 60             // 获取参数地址
 61             var vertexPositionAttr = gl.getAttribLocation(shaderProgram, aVertexPosition);
 62             gl.enableVertexAttribArray(vertexPositionAttr);
 63             var mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix");
 64 
 65             // 顶点
 66             var vertices = [
 67                 // 前面四个顶点
 68                  -0.5, -0.5, -0.5,
 69                  0.5, -0.5, -0.5,
 70                  0.5, 0.5, -0.5,
 71                  -0.5, 0.5, -0.5,
 72 
 73                  // 后面四个顶点
 74                  -0.5, -0.5, 0.5,
 75                  0.5, -0.5, 0.5,
 76                  0.5, 0.5, 0.5,
 77                  -0.5, 0.5, 0.5,
 78             ];
 79             var vertexPositionBuffer = gl.createBuffer();
 80             gl.bindBuffer(gl.ARRAY_BUFFER, vertexPositionBuffer);
 81             gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
 82 
 83             // 索引
 84             var vertexIndices = [
 85                 // 前面
 86                 0, 1, 2,
 87                 0, 2, 3,
 88 
 89                 // 后面
 90                 4, 5, 6,
 91                 4, 6, 7,
 92 
 93                 // 左面
 94                 4, 0, 3,
 95                 4, 3, 7,
 96 
 97                 // 右面
 98                 1, 5, 6,
 99                 1, 6, 2,
100 
101                 // 上面
102                 3, 2, 6,
103                 3, 6, 7,
104 
105                 // 下面
106                 0, 1, 5,
107                 0, 5, 4
108             ];
109             var vertexIndexBuffer = gl.createBuffer();
110             gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, vertexIndexBuffer);
111             gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(vertexIndices), gl.STATIC_DRAW);
112 
113             // 渲染循环
114             var x = 0, y = 0, z = 0;
115             var render = function () {
116                 // 清屏
117                 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
118 
119                 // 顶点
120                 gl.bindBuffer(gl.ARRAY_BUFFER, vertexPositionBuffer);
121                 gl.vertexAttribPointer(vertexPositionAttr, 3, gl.FLOAT, false, 0, 0);
122 
123                 // 位移矩阵
124                 var euler = new THREE.Euler(x, y, z);
125                 var mat = new THREE.Matrix4();
126                 mat.makeRotationFromEuler(euler);
127                 gl.uniformMatrix4fv(mvMatrixUniform, false, mat.toArray());
128 
129                 // 绘制
130                 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, vertexIndexBuffer);
131                 gl.drawElements(gl.TRIANGLES, 36, gl.UNSIGNED_SHORT, 0);
132 
133                 x += 0.01;
134                 y += 0.01;
135                 z += 0.01;
136                 requestAnimationFrame(render);
137             }
138             render();
139         }
140     </script>
141 </head>
142 
143 <body onload="start();">
144     <canvas id="mycanvas" style="border: none;" width="500" height="500"></canvas>
145 </body>
146 
147 </html>

效果图:

技术分享

参考资料:

    Lesson4 真正的3D物体:http://www.hiwebgl.com/?p=186

    THREEJS官网:https://threejs.org/

 

04 绘制正方体和位移矩阵