1. 程式人生 > >04 繪制正方體和位移矩陣

04 繪制正方體和位移矩陣

參考 2個 static title 直觀 asc link view maker

我們首先繪制一個正方體,它有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 繪制正方體和位移矩陣