1. 程式人生 > >WebGL學習筆記(一)

WebGL學習筆記(一)

clear ont tin form rgba int 顏色緩沖區 數據 其他

目錄

  • 繪制二維圖形(2D圖形)
    • 經過一下三個步驟
    • 簡單js程序代碼
    • 簡單html文件代碼
  • 繪制實例(一個點)
    • 著色器分為以下兩種:
      • 1. 頂點著色器
      • 2. 片元著色器
      • 初始化著色器
    • 繪制操作
    • 程序的執行流程
    • main()函數的執行流程
    • 將位置信息從js程序中傳給頂點著色器
      • 使用attribute變量
      • 使用uniform變量
  • 響應鼠標點擊事件動態畫點

繪制二維圖形(2D圖形)

經過一下三個步驟

  1. 獲取
  2. 向該元素強求二維圖形的“繪圖上下文”;
  3. 在繪圖上下文上調用相應的繪圖函數,以繪制二維圖形;

簡單js程序代碼

//DrawRectangle.js
function(){
    //獲取<canvas>元素
    var canvas = document.getElementById(‘example‘);//example是在html文件中定義的canvas元素的id;
    if(!canvas){
        console.log(‘Failed to review the <canvas> element‘);
        return;
    }
    
    //獲取繪制二維圖形的繪圖上下文
    var ctx = canvas.getContext(‘2d‘);
    
    //繪制藍色矩形
    ctx.fillSyle = ‘rgba(0,0,255,1.0)‘;//設置填充顏色為藍色,r:紅;g:綠;b:藍;a:透明度;
    ctx.fillRect(120,10,150,150);//使用填充顏色填充矩形
}

簡單html文件代碼

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="utf-8" />
 <title>Clear canvas</title>
</head>

<body onload="main()">
 <canvas id="webgl" width="400" height="400">
 Please use the browser supporting "canvas"
 </canvas>
 
 <script src="../lib/webgl-utils.js"></script>
 <script src="../lib/webgl-debug.js"></script>
 <script src="../lib/cuon-utils.js"></script>
 <script src="HelloCanvas.js"></script>
</body>
</html>

其中onload="main()"表示在body執行結束之後執行main()函數,而main()函數在HelloCanvas文件中,因此這也是進入HelloCanvas文件的入口;

繪制實例(一個點)

和之前的以RGB的形式指定WebGL的背景色不一樣,這裏不能直接使用先指定繪圖顏色再繪制的方式。WebGL依賴於一種新的方式成為著色器的繪圖機制。

著色器分為以下兩種:

1. 頂點著色器

var VSHADER_SOURCE=
    ‘void main() {\n‘ +
    ‘gl_Position = vec4(0.0,0.0,0.0,1.0);\n‘ +//設置坐標
    ‘gl_PointSize = 10.0;\n‘ +//設置尺寸
    ‘}\n‘;
  1. gl_position變量必須被賦值,且其數據類型是float型。gl_PointSize並不是必須的,若不賦值,著色器就會為其取默認值1.0。
  2. vec4表示的是齊次坐標。(x,y,z,w):x y z表示點的位置坐標,w為0時表示向量,w為1時表示點;

2. 片元著色器

var FSHADER_SOURCE=
    ‘void main() {\n‘ +
    ‘gl_FragColor = vec4(1.0,0.0,0.0,1.0);\n‘ +//設置顏色
    ‘}\n‘;
  1. 片元就類似於屏幕上的一個像素(嚴格說其包括像素的位置、顏色和其他信息)
  2. gl_FragColor變量是片元著色器唯一的內置變量,控制著像素在屏幕上的最終顏色。

在代碼中,著色器程序是以字符串的形式“嵌入”在javascript文件中,在程序真正開始運行前它就已經設置好了。

初始化著色器

重要: WebGL程序包括運行在瀏覽器中的JavaScript和運行在WebGL系統的著色器程序這兩個部分。

繪制操作

  1. 使用gl.drawArrays(gl.POINTS,0,1);來繪制各種圖形
  2. 參數:mode-繪制方式(有gl.POINTS,gl.LINES,gl.TRIANGLES,gl.LINE_LOOP等等),first-指定從哪個頂點開始繪制(整數型),count-指定繪制需要用到多少個頂點(整數型)
  3. 程序調用gl.drawArray()時,著色器將被執行count次,每次處理一個頂點。一旦頂點著色器執行完後,片元著色器就會開始執行。

程序的執行流程

  1. 瀏覽器
  2. 執行加載js程序
  3. 執行WebGL的相關方法(頂點著色器、片元著色器,分別逐頂點、逐片元操作)
  4. 渲染到顏色緩沖區->顯示在瀏覽器上。

main()函數的執行流程

  1. 獲取
  2. 獲取WebGL繪圖上下文
  3. 初始化著色器(頂點、片元)
  4. 設置
  5. 清除
  6. 繪圖

將位置信息從js程序中傳給頂點著色器

  1. 使用attribute變量:傳輸的是那些與頂點相關的數據

  2. 使用uniform變量:傳輸的是那些對於所有頂點都相同的數據

使用attribute變量

  1. 在頂點著色器中,聲明attribute變量;
    var VSHADER_SOURCE= ‘attribute vec4 a_Position;\n‘ + ‘void main() {\n‘ + ‘gl_Position = a_Position;\n‘ +//設置坐標 ‘gl_PointSize = 10.0;\n‘ +//設置尺寸 ‘}\n‘;

    attribute:存儲限定符;

    vec4:類型(數組)

    a_Position:變量名

  2. 將attribute變量賦值給gl_Position變量;

    //獲取attribute變量的存儲位置
    var a_Position = gl.getAttributeLocation(gl.program,‘a_Position‘);
    if(a_Position < 0) {
     console.log(‘Failed to get the storage location of a_Position‘);
     return;
    }

    gl.program:程序對象(包括頂點著色器好片元著色器)

    a_Position:想要獲取處處地址的attribute變量的名稱

  3. 向attribute變量傳輸數據;

    //將頂點位置傳輸給attribute變量
    gl.vertexAttrib3f(a_Position,0.0,0.0,0.0);

    a_Position:attribute變量的存儲地址

    後三個參數:x、y、z坐標值

    省略了w透明度分量,函數會默認將第四個分量設置為1.0。

使用uniform變量

改變點的顏色可以使用uniform變量實現

  1. 在片元著色器中準備uniform變量;
    var FSHADER_SOURCE= ‘precision mediump float;\n‘ + ‘uniform vec4 u_FragColor;\n‘ +//uniform變量 ‘void main() {\n‘ + ‘gl_FragColor = vec4(1.0,0.0,0.0,1.0);\n‘ +//設置顏色 ‘}\n‘;

  2. 用這個uniform變量想gl_FragColor賦值;
    //獲取attribute變量的存儲位置 var u_FragColor = gl.getUniformLocation(gl.program,‘u_FragColor‘); if(u_FragColor < 0) { console.log(‘Failed to get the storage location of u_FragColor‘); return; }
  3. 將顏色數據從javascript傳給uniform變量;
    gl.uniform4f(u_FragColor,rgba[0],rgba[1],rgba[2],rgba[3]);

響應鼠標點擊事件動態畫點

  1. 在main()函數裏面註冊鼠標點擊事件相應函數(匿名函數)。
//註冊鼠標點擊事件響應函數
canvas.onmousedown = function(ev) { click(ev,gl,canvas,a_Position); };
  1. click函數完成了什麽
    1. 獲取鼠標點擊的位置並存儲在一個數組中;
    2. 清空
    3. 格局數組的每個元素,在響應的位置繪制點;
  2. 不能直接使用鼠標點擊位置原因
    1. 鼠標點擊位置是在“瀏覽器客戶區”中的坐標,而不是在

    技術分享圖片

    技術分享圖片

    將坐標從瀏覽器客戶區坐標系下轉換到canvas坐標系下
    var x = ev.clientX; var y = ev.clientY; var rect = ev.target.getBoundingClientRect();
    將坐標從canvas坐標系下轉換到WebGL下

    x = ((x - rect.left) - canvas.width/2)/(canvas.width/2);//<canvas>的中心點坐標是(canvas.height/2, canvas.width/2);
    
    y = (canvas.height/2 - (y - rect.top))/(canvas.height/2);

WebGL學習筆記(一)