1. 程式人生 > >原生WebGL基礎學習(二) 用WebGL繪製一個三角形

原生WebGL基礎學習(二) 用WebGL繪製一個三角形

在開始之前,需要知道著色器的相關知識,可以參考:webgl介紹裡面的著色器介紹,本文的demo 用到的著色器為:

    <script id="vertex-shader" type="x-shader/x-vertex">
        attribute vec4 a_position;
        void main() {
            gl_Position = a_position;
        }
    </script>

    <script id="fragment-shader" type="x-shader/x-fragment">
        precision mediump float;//將精度設定為中等精度
        void main() {
            gl_FragColor = vec4(1, 0, 0.5, 1);
        }
    </script>

其中的attribute定義了一個vec4四維變數,用於表示每個頂點的位置資訊,gl_Position代表頂點的位置, a_position是著色器用於接收來自JavaScript程式碼的頂點位置資訊的入口。gl_FragColor代表每個片元的顏色,通俗的理解是用於設定幾何顏色。

首先,在HTML文件裡建立一個用於畫圖的canvas(畫布):

<canvas id="triangle" width="800" height="600"></canvas>

獲取canvas元素:

 let canvas = document.getElementById('triangle');

判斷瀏覽器是否支援WebGL,其中,antialias表示是否開啟抗鋸齒, depth表明繪製緩衝區包含一個深度至少為16位的緩衝區:

let gl = canvas.getContext('webgl', {antialias: true, depth: false});
 if (!gl) {
    console.log("您的瀏覽器不支援webgl!");
 }

根據id獲取著色器文字,並建立、編譯和連結著色器:

//獲取GLSL文字
let vShaderSource = document.getElementById('vertex-shader').text;
let fShaderSource = document.getElementById('fragment-shader').text;
//建立、編譯和連結著色器
 let program = initShader(gl, vShaderSource, fShaderSource);

在著色器中尋找attribute變數的位置:

let positionAttributeLocation = gl.getAttribLocation(program, 'a_position');

建立緩衝區,並繫結資料:

//建立緩衝區
 let positionBuffer = gl.createBuffer();

 //將它繫結到ARRAY_BUFFER(將其視為ARRAY_BUFFER = positionBuffer)
 //繫結緩衝區
 gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);

 //三個頂點構成一個三角形
  let positions = [
       -0.25, 0,
        0, 0.5,
        0.25, 0
      ];

//通過繫結點向緩衝區繫結資料
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);

 最後進行畫圖:

//使畫布的畫素數和顯示大小匹配
 webglUtils.resizeCanvasToDisplaySize(gl.canvas);

 //設定視口
 gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);

 //清除canvas
 gl.clearColor(0, 0, 0, 1);//設定背景顏色
 gl.clear(gl.COLOR_BUFFER_BIT);

 //應用著色器
 gl.useProgram(program);

 //建立著色器中attribute變數與緩衝區之間的連線
 gl.enableVertexAttribArray(positionAttributeLocation);
 const size = 2;//2維座標:每次迭代執行提取兩個單位資料
 const type = gl.FLOAT;//每個單位的資料型別是32位浮點型
 const normalize = false;//不需要歸一化資料
 const stride = 0;//每次迭代前進大小* sizeof(型別)以獲得下一個位置
 const offset1 = 0;//從緩衝起始位置開始讀取

 //從緩衝區取出資料
  gl.vertexAttribPointer(positionAttributeLocation, size, type, normalize, stride, offset1);

  let primitiveType = gl.TRIANGLES;//繪製三角形
  let offset2 = 0;//從第一個頂點開始
  let count = 3;//畫圖所頂點次數
  gl.drawArrays(primitiveType, offset2, count);//畫圖

顯示效果: