WebGL學習筆記(一)


繪制二維圖形(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. 鼠標點擊位置是在“瀏覽器客戶區”中的坐標,而不是在 中的坐標。

    1. 的坐標系統和WebGL的坐標系統,其原點位置和Y軸的正方向都不一樣。

    將坐標從瀏覽器客戶區坐標系下轉換到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);
    


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM