原生webgl學習(四) WebGL繪製矩形
阿新 • • 發佈:2018-12-15
上節課筆者繪製了一個顏色隨頂點位置變化的三角形,實現平移、旋轉和縮放變換的矩陣計算,並提供了一個可供互動的選單欄工具:原生webgl學習(三) WebGL中的矩陣運算:平移、旋轉和縮放;
在前面我們已經畫了兩次三角形了,這次,改變一些套路,我們畫矩形。畫矩形的程式碼跟上一節大同小異,程式碼解釋可以參考上一節:原生webgl學習(三) WebGL中的矩陣運算:平移、旋轉和縮放,唯一不同的是頂點座標發生了改變,利用兩個三角形構成一個矩形,只需要將程式碼中的頂點稍作修改即可:
let positions = [ -150, -100, 150, -100, -150, 100, 150, -100, -150, 100, 150, 100 ];
在畫圖的時候gl.drawArrays的引數稍作修改即可,由於頂點陣列長度增加,由原來的3個頂點變為6個頂點,故count應變為6,在這裡提供一種更加友好的方法,可以根據陣列的長度畫圖:
//這樣一來對所有陣列都適用,三維的為positions.length / 3
let primitiveType = gl.TRIANGLES;
let offset3 = 0;
let count = positions.length / 2;
gl.drawArrays(primitiveType, offset3, count);//畫圖
這個demo的程式碼在你們下載的資料夾下的chapter-02裡面的color-triangle-02.html,執行效果如下:
大家要注意,這個demo的矩形的顏色並不會隨著頂點的位置的變化而變化,那是由於在JavaScript程式碼裡面,已經提前設定好頂點的顏色,所以著色器程式碼也要稍微修改一下:
<script id="vertex-shader" type="x-shader/x-vertex"> attribute vec2 a_position; attribute vec4 a_color; uniform mat3 u_matrix; varying vec4 v_color; void main() { vec4 offset = vec4(0.1, 0.1, 0, 1); gl_Position = vec4((u_matrix * vec3(a_position, 1)).xy, 0, 1) + offset; v_color = a_color; } </script> <script id="fragment-shader" type="x-shader/x-fragment"> precision mediump float; varying vec4 v_color; void main() { gl_FragColor = v_color; } </script>
頂點著色器裡面定義了一個用於接收來自JavaScript程式碼顏色資訊的attribute變數:a_color,在JavaScript程式碼中,需要獲取到這個變數的位置:
let colorAttributeLocation = gl.getAttribLocation(program, 'a_color');
為其建立緩衝區,並寫入資料:
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
setColor(gl, 1);
//設定顏色,alpha為透明度
function setColor(gl, alpha = 1) {
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
Math.random(), Math.random(), Math.random(), alpha,
Math.random(), Math.random(), Math.random(), alpha,
Math.random(), Math.random(), Math.random(), alpha,
Math.random(), Math.random(), Math.random(), alpha,
Math.random(), Math.random(), Math.random(), alpha,
Math.random(), Math.random(), Math.random(), alpha
]), gl.STATIC_DRAW);
}
接下來要建立著色器中的a_color與上述緩衝區之間的連結,並取出緩衝區的資料:
//建立著色器中attribute顏色變數與緩衝區之間的連線
gl.enableVertexAttribArray(colorAttributeLocation);
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
const size2 = 4;//2維座標:每次迭代執行提取兩個單位資料
const type2 = gl.FLOAT;//每個單位的資料型別是32位浮點型;如果為Uint8Array的8位陣列,要設定為gl.UNSIGNED_BYTE
const normalize2 = false;//不需要歸一化資料
const stride2 = 0;//每次迭代前進大小* sizeof(型別)以獲得下一個位置
const offset2 = 0;//從緩衝起始位置開始讀取
//到指定的緩衝區取出資料
gl.vertexAttribPointer(colorAttributeLocation, size2, type2, normalize2, stride2, offset2);
更多的細節請讀者自行看程式碼,裡面有詳細的註釋。這裡有一個問題,我們要畫矩形和幹嘛,有什麼用?這裡筆者想到了一個比較有趣的應用,利用三角形和矩形構建中文簡體字,下一節將帶領大家實現這個騷操作,敬請期待!