《WebGL編程指南》1&2 WebGL入門

什么是WebGL?

WebGL是一種可以在網(wǎng)頁(yè)上繪制渲染3D圖形,并允許用戶與之交互的技術(shù)。瀏覽器內(nèi)置了WebGL,可以搭配HTML5和JavaScript使用。

WebGL的優(yōu)勢(shì)?

充分利用前端開發(fā)與瀏覽器的優(yōu)勢(shì),不需要復(fù)雜的開發(fā)環(huán)境,可以輕松開發(fā)可移植性強(qiáng)、兼容性強(qiáng)的三維圖形程序。WebGL程序使用三種語(yǔ)言開發(fā):HTML、JavaScript、GLSL ES(OpenGL ES)著色器代碼內(nèi)嵌在JavaScript中,以字符串形式在JavaScript中編寫。

例2.1 DrawRectangle 繪制一個(gè)實(shí)心藍(lán)色矩形

目標(biāo): 了解canvas標(biāo)簽與繪圖上下文

步驟:

  1. 獲取canvas元素
var canvas = document.getElementById('canvas');
  1. 向該元素請(qǐng)求二維圖形的繪圖上下文
var ctx = canvas.getContext('2d');
  1. 使用繪圖上下文的繪圖函數(shù),繪制二維圖形
// 設(shè)置填充顏色為藍(lán)色
ctx.fillStyle = 'rgba(0, 0, 255, 1.0)';
// 使用填充顏色填充指定大小和位置的矩形
ctx.fillRect(120, 10, 150, 150);

fillRect函數(shù)前兩個(gè)參數(shù)是位置,后兩個(gè)參數(shù)是寬高。

例2.2 HelloCanvas 清空/使用指定顏色填充canvas

目標(biāo): 使用指定顏色清空畫布

步驟:

  1. 獲取canvas元素

  2. 獲取WebGL繪圖上下文

var gl = getWebGLContext(canvas);
  1. 設(shè)置背景色,設(shè)置的背景色會(huì)常駐系統(tǒng),待下一次調(diào)用前不會(huì)改變
gl.clearColor(0.0, 0.0, 1.0, 1.0);
  1. 清空canvas,用背景色填充,擦除已經(jīng)繪制的內(nèi)容
gl.clear(gl.COLOR_BUFFER_BIT);  

gl.COLOR_BUFFER_BIT指的是顏色緩沖區(qū)(color buffer),除此之外還有深度緩沖區(qū)和模板緩沖區(qū)。

例2.3 HelloPoint1 繪制一個(gè)點(diǎn)(版本1)

目標(biāo): 學(xué)習(xí)編寫著色器代碼,初始化著色器并繪制圖形

著色器是WebGL的繪圖機(jī)制,著色器包括頂點(diǎn)著色器片元著色器兩種,頂點(diǎn)著色器是用于描述頂點(diǎn)特性(如位置、顏色等)的程序,頂點(diǎn)指的是圖形的端點(diǎn)和交點(diǎn),片元著色器是進(jìn)行逐片元處理過(guò)程(如光照等)的程序,片元是WebGL術(shù)語(yǔ),可以理解為像素。

步驟:

  1. 獲取canvas元素

  2. 獲取WebGL繪圖上下文

  3. 初始化著色器

initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)

著色器初始化之前,頂點(diǎn)和片元著色器都是空白的,函數(shù)將字符串形式的著色器代碼從JavaScript傳給WebGL系統(tǒng)并建立著色器。

  1. 設(shè)置背景色

  2. 清空canvas

  3. 繪制一個(gè)點(diǎn)

gl.drawArrays(gl.POINTS, 0, 1);

調(diào)用該函數(shù),頂點(diǎn)著色器被執(zhí)行count次,每次處理一個(gè)頂點(diǎn)。

著色器代碼:

// 頂點(diǎn)著色器程序
var VSHADER_SOURCE = 
    'void main() {\n' +
    '    gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n' + // 設(shè)置坐標(biāo)
    '    gl_PointSize = 10.0;\n' + // 設(shè)置尺寸
    '}\n';

// 片元著色器程序
var FSHADER_SOURCE = 
    'void main() {\n' +
    '    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n' + // 設(shè)置顏色
    '}\n';

在著色器代碼中,gl_Position必填,指定頂點(diǎn)位置,vec4表示4個(gè)浮點(diǎn)數(shù)矢量,gl_PointSize為頂點(diǎn)尺寸,gl_FragColor為片元顏色。

WebGL坐標(biāo)為右手坐標(biāo)系統(tǒng),并且在二維平面中與canvas坐標(biāo)系統(tǒng)也不一致。


例2.4 HelloPoint2 繪制一個(gè)點(diǎn)(版本2)

目標(biāo): 使用attribute變量,使用attribute或uniform變量將位置信息從JavaScript程序中傳給頂點(diǎn)著色器,attribute變量傳輸與頂點(diǎn)相關(guān)的數(shù)據(jù),uniform變量傳輸與頂點(diǎn)無(wú)關(guān)的數(shù)據(jù)

步驟:

  1. 在頂點(diǎn)著色器代碼中,聲明attribute變量,并賦值給gl_Position變量
'attribute vec4 a_Position;\n' +
···
'   gl_Position = a_Position;\n' + // 設(shè)置坐標(biāo)
  1. 著色器初始化后,獲取attribute變量的存儲(chǔ)位置
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
  1. 向attribute變量傳遞數(shù)據(jù)
gl.vertexAttrib3f(a_Position, 0.0, 0.0, 0.0);

gl.vertexAttrib?f(?=1/2/3/4)的任務(wù)是從JavaScript向頂點(diǎn)著色器中的attribute變量傳值。

例2.5 ClickedPoints 通過(guò)鼠標(biāo)點(diǎn)擊繪點(diǎn)

目標(biāo): 加入鼠標(biāo)交互,通過(guò)鼠標(biāo)點(diǎn)擊繪點(diǎn),了解瀏覽器、canvas、webgl坐標(biāo)系統(tǒng)與相互轉(zhuǎn)換

步驟:

  1. 為鼠標(biāo)點(diǎn)擊事件綁定回調(diào)函數(shù)click
canvas.onmousedown = function(ev) {
    click(ev, gl, canvas, a_Position);
}
  1. 通過(guò)event可以獲得鼠標(biāo)點(diǎn)擊的位置(瀏覽器頁(yè)面坐標(biāo)),該坐標(biāo)需要轉(zhuǎn)換到canvas坐標(biāo)系統(tǒng)下,再轉(zhuǎn)換到webgl坐標(biāo)系統(tǒng)下
var x = ev.clientX;  // 鼠標(biāo)點(diǎn)擊處的x坐標(biāo)
var y = ev.clientY;  // 鼠標(biāo)點(diǎn)擊處的y坐標(biāo)
var rect = ev.target.getBoundingClientRect();

ev.target表示canvas元素,getBoundingClientRect用于獲取某個(gè)元素相對(duì)于視窗的位置集合,返回包含top、left、bottom、right、width和height屬性的對(duì)象。

坐標(biāo)轉(zhuǎn)換代碼如下:

x = ((x - rect.left) - canvas.width/2)/(canvas.width/2);
y = (canvas.height/2 - (y - rect.top))/(canvas.height/2);
  1. 清空canvas,根據(jù)數(shù)組的每個(gè)元素,在相應(yīng)位置繪制點(diǎn):點(diǎn)位置傳遞給變量,并繪制
// 清空canvas
gl.clear(gl.COLOR_BUFFER_BIT);

var len = g_points.length;
for (var i = 0; i < len; i += 2) {
    // 將點(diǎn)的位置傳遞到變量a_Position中
    gl.vertexAttrib3f(a_Position, g_points[i], g_points[i+1], 0.0);
    // 繪制點(diǎn)
    gl.drawArrays(gl.POINTS, 0, 1);
}

存儲(chǔ)點(diǎn)坐標(biāo)的數(shù)組會(huì)存儲(chǔ)所有點(diǎn)坐標(biāo),每次點(diǎn)擊后指定canvas背景顏色(設(shè)置顏色緩沖區(qū)),再把數(shù)組中的所有點(diǎn)繪制出來(lái)。若注釋清空canvas代碼,在第一次點(diǎn)擊后canvas背景色變?yōu)榘咨?,因?yàn)槔L制點(diǎn)后,顏色緩沖區(qū)會(huì)被重置為默認(rèn)顏色。

例2.6 ColoredPoints 改變點(diǎn)的顏色

目標(biāo): 熟悉uniform變量的使用

步驟:

  1. 在片元著色器中定義并使用uniform變量,注意在片元著色器中使用變量時(shí)需要使用精度限定詞指定變量的范圍和精度,否則程序會(huì)報(bào)錯(cuò)
var FSHADER_SOURCE = 
    'precision mediump float;\n' +  // 精度限定詞
    'uniform vec4 u_FragColor;\n' + // uniform變量
    'void main() {\n' +
    ' gl_FragColor = u_FragColor;\n' + // 設(shè)置顏色
    '}\n';
  1. 獲取uniform變量地址
var u_FragColor = gl.getUniformLocation(gl.program, 'u_FragColor');
  1. 向uniform變量傳遞數(shù)據(jù)
gl.uniform4f(u_FragColor, rgba[0], rgba[1], rgba[2], rgba[3]);
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 談起WebGL可能有一些人比較陌生,實(shí)際上WebGL是一種3D繪圖標(biāo)準(zhǔn),這種繪圖技術(shù)標(biāo)準(zhǔn)允許把JavaScript...
    三石青韋閱讀 18,436評(píng)論 2 11
  • 默認(rèn)情況下,canvas是透明的。 canvas可以靈活地支持二維圖形和三維圖形,它不直接提供繪圖方法,而是提供一...
    fehysunny閱讀 1,678評(píng)論 0 3
  • WebGL從2012年開始接觸,后面因?yàn)殚_始專注前端其他方面的事情,慢慢地就把它給遺忘。最近前端開始又流行起繪畫制...
    我不是傳哥閱讀 4,385評(píng)論 1 22
  • \color{blue}{ch2} 坐標(biāo)圖 canvas的坐標(biāo)橫軸為x軸(正方向朝右),縱軸為y軸(正方向朝下) ...
    liuyangjike閱讀 782評(píng)論 0 1
  • Python3.5+Scrapy爬取伯樂(lè)在線的博客文章 創(chuàng)建虛擬環(huán)境 使用命令行創(chuàng)建scrapy項(xiàng)目 創(chuàng)建基本模板...
    捂不暖的石頭閱讀 928評(píng)論 0 0

友情鏈接更多精彩內(nèi)容