前言
原書中第2章非常長,如果整理成一個文件的話,得看好多天。為了瀏覽方便,我將其拆分成若干小節,方便大家學習。
webgl採用HTML5中引入的canvas元素來定義頁面的繪圖區域。如果沒有WegGL,js只能在canvas上繪製二維圖形。
在這一章中,我們將通過建立若干個示例程式,一步步的介紹一些核心的webgl函式。
1.最短的webgl程式:清空繪圖區
我們要開始編寫最短的webgl程式,這個程式的主要功能是使用背景色清空canvas標籤的繪圖區。(這裡的清空,是指用背景色填充的意思)
html程式碼如下;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>webgl學習</title>
</head>
<body>
<canvas id="canvas" width="400" height="400"></canvas>
<script src="./index.js"></script>
</body>
</html>
複製程式碼
js程式碼如下:
// 獲取canvas
var canvas = document.getElementById('canvas')
// 獲取webgl繪圖上下文
var gl = canvas.getContext('webgl')
if (!gl) {
console.log('Failed to get the rendering context')
}
// 指定清空canvas的顏色
gl.clearColor(0.0, 0.0, 0.0, 1.0)
// 清空canvas
gl.clear(gl.COLOR_BUFFER_BIT)
複製程式碼
示例程式的執行步驟如下:
- 獲取canvas元素
- 獲取webgl的繪圖上下文
- 設定背景色
- 清空canvas
2. 程式解析
2.1 獲取canvas元素
我們通過getElementById獲取canvas元素
var canvas = document.getElementById('canvas')
複製程式碼
2.2 為webgl獲取繪圖上下文
這裡傳入的引數是‘webgl’而不是‘3d’。我們以前使用canvas畫2d圖形的時候傳入的是‘2d’。所以這裡要注意下,不要傳錯了。
var gl = canvas.getContext('webgl')
複製程式碼
2.3 設定canvas的背景色
gl.clearColor(0.0, 0.0, 0.0, 1.0)
複製程式碼
gl.clearColor採用RGBA的方式設定背景色:
gl.clearColor(red,green,blue,alpha)
複製程式碼
引數 | 含義 |
---|---|
red | 指定紅色值(從0.0到1.0) |
green | 指定綠色值(從0.0到1.0) |
blue | 指定藍色值(從0.0到1.0) |
alpha | 指定透明度(從0.0到1.0) |
返回值 | 無 |
錯誤 | 無 |
如果任何值小於0或者大於1,那麼就會被截斷為0.0或者1.0
示例程式執行gl.clearColor(0.0, 0.0, 0.0, 1.0)
,背景色就被指定為了黑色。
我們一般指定顏色時,顏色的值是0到255之間的,但是由於webgl是繼承自OpenGL,所以它遵循傳統OpenGL顏色分量的取值範圍。
一旦指定的背景色,背景色就會駐存在WegGL系統中,在下一次呼叫gl.clearColor之前都不會改變。如果你將來還想用同一個顏色清空繪圖區,就沒必須要再指定一次背景色。
2.4 清空canvas
gl.clear(gl.COLOR_BUFFER_BIT);
複製程式碼
函式引數是gl.COLOR_BUFFER_BIT
,這是因為WebGL中,gl.clear()方法實際上繼承自OpenGL,它基於多基本緩衝區模型。這比二維繪圖上下文複雜的多。清空繪圖區域,實際上在清空顏色緩衝區,傳遞引數gl.COLOR_BUFFER_BIT就是告訴WebGL清空顏色緩衝區。除了顏色緩衝區,WebGL還有其他種類的緩衝區,比如深度緩衝區和模板緩衝區。
gl.clear(buffer)
的用法
buffer是指定待清空的顏色緩衝區,位操作符OR(|)可用於指定多個緩衝區
引數 | 含義 |
---|---|
gl.COLOR_BUFFER_BIT | 顏色緩衝區 |
gl.DEPTH_BUFFER_BIT | 深度緩衝區 |
gl.STENCIL_BUFFER_BIT | 指定模板緩衝區 |
返回值 | 無 |
錯誤 | INVALID_VALUE 緩衝區不是以上三種型別 |
3. 繪製一個點
之前的章節,我們學習如何建立一個wegl程式,以及如何使用一些簡單的webgl函式。這一節我們將進一步在一個示例程式中繪製一個最簡單的圖形,一個點。
注意這裡的html比上一次的html多了一些script。這些script是一些工具函式,避免重複的寫大量的程式碼。程式碼很簡單,可以直接開啟檢視。這裡就不解釋了。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>webgl學習</title>
</head>
<body>
<canvas id="canvas" width="400" height="400"></canvas>
<!-- 引入幾個webgl幫助函式,這裡的程式碼很簡單,你可以直接點選檢視 -->
<script src="https://mycode04-1252305175.cos.ap-guangzhou.myqcloud.com/webgl-lib/lib/webgl-utils.js"></script>
<script src="https://mycode04-1252305175.cos.ap-guangzhou.myqcloud.com/webgl-lib/lib/webgl-debug.js"></script>
<script src="https://mycode04-1252305175.cos.ap-guangzhou.myqcloud.com/webgl-lib/lib/cuon-utils.js"></script>
<script src="./index.js"></script>
</body>
</html>
複製程式碼
javascript程式碼:
// 頂點著色器 注意這裡的\n不能省略。否則不符合語法
var VSHADER_SOURCE = `
void main(){\n
gl_Position = vec4(0.0,0.0,0.0,1.0);\n
gl_PointSize = 10.0;\n
}\n
`
// 片段(片元)著色器
var FSHADER_SOURCE = `
void main(){\n
gl_FragColor = vec4(1.0,0.0,0.0,1.0);\n
}\n
`
function main() {
// 獲取canvas
var canvas = document.getElementById('canvas')
// 獲取webgl繪圖上下文
var gl = canvas.getContext('webgl')
if (!gl) {
console.log('Failed to get the rendering context')
retun
}
// 初始化著色器函式
if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
console.log("設定著色器失敗")
return
}
// 指定清空canvas的顏色
gl.clearColor(0.0, 0.0, 0.0, 1.0)
// 清空canvas
gl.clear(gl.COLOR_BUFFER_BIT)
// 畫一個點
gl.drawArrays(gl.POINTS, 0, 1)
}
window.onload = function () {
main()
}
複製程式碼
3.1 著色器是什麼?
要使用webgl進行繪圖必須使用著色器,在程式碼中,著色器是以字串的形式“嵌入”到js中的。
webgl的著色器分兩種
- 頂點著色器:頂點著色器用來描述頂點的特性(如位置、顏色等)的程式,頂點是指二維或者三維空間的一個點,比如二維或者三維圖形的端點和交點。
- 片元著色器:也叫片段著色器。負責進行逐片元處理過程如光照的程式。片元是webgl的一個術語。你可以理解它為畫素。
在三維場景中,僅僅用線條和顏色把圖形畫出來是遠遠不夠的,必須要考慮光照上去或者觀察者視角發生變化時,對場景有什麼影響。著色器可以高度靈活的完成這些工作。提供各種渲染效果。
上述程式執行流程:
- 先執行javascript程式
- 呼叫webgl的相關方法
- 執行頂點著色器
- 執行片元著色器
- 在顏色緩衝區進行繪製
- 清空繪圖區
- 顏色緩衝區的內容自動在瀏覽器的canvas上顯示出來
3.2 initShaders
initShaders()
,該函式定義在cuon.util.js中,是專為本書編寫的一個工具函式。其用法說明如下:
initShaders(gl,vshader,fshader) | ||
引數 | 取值 | 含義 |
gl | vshader | 指定頂點著色器程式程式碼 |
fshader | 指定片元著色器程式程式碼 | |
返回值 | true | 初始化著色器成功 |
fase | 初始化著色器失敗 |
3.3 頂點著色器
var VSHADER_SOURCE = `
void main(){\n
gl_Position = vec4(0.0,0.0,0.0,1.0);\n
gl_PointSize = 10.0;\n
}\n
`
複製程式碼
頂點著色器必須和c語言一樣,必須包含一個main函式。main前面的void表示這個函式不會有返回值。
首先將頂點位置賦值給gl_Position變數。
在將頂點尺寸賦值給gl_PointSize。
這兩個變數內建在頂點著色器中,有特殊的含義。如下:
型別和變數名 | 含義 |
---|---|
vec4 gl_Position | 表示頂點的位置 |
float gl_PointSize | 表示頂點的尺寸 |
vec4 表示由4個浮點陣列成的向量。
注意:GLSL ES是一種強型別程式語言,比10是整型,10.0就是浮點數,傳錯型別就會報錯。
gl_Position其型別為vec4,但是我們只有3個浮點數(0.0,0.0,0.0),既x、y、z座標值。需要用某種方式把它轉為vec4型別的變數。好在著色器為我們提供了內建函式vec4(),幫助你建立vec4型別的變數。(原書中這一段有錯誤,已糾正)
在賦值gl_Position的向量中,我們新增了1.0作為第4個分量。由4個分量組成的向量稱為齊次座標。,因為它能夠提高處理三維資料的效率。所以被大量使用。雖然齊次座標是四維的,但是如果最後一個分量為1.0,那麼齊次座標就可以表示“前三個分量為座標值”的那個點。
3.4 片元著色器
片元著色器是用來設定顏色的,這裡設定為紅色。
var FSHADER_SOURCE = `
void main(){\n
gl_FragColor = vec4(1.0,0.0,0.0,1.0);\n
}\n
`
複製程式碼
gl_FragColor的用法如下:
型別和變數名 | 含義 |
---|---|
vec4 gl_FragColor | 指定片元顏色(RGBA格式) |
3.5 繪製操作
我們使用drawArrays()進行繪製。
gl.drawArrays(gl.POINTS, 0, 1)
複製程式碼
gl.drawArrays(mode,first,count)
引數 | 含義 |
---|---|
mode | 指定繪製的方式,可以接受以下常量符號: gl.POINTS ,gl.LINES ,gl.LINE_STRIP ,gl.LINE_LOOP ,gl.TRIANGLES ,gl.TRIANGLE_STRIP ,gl.TRIANGLE_FAN |
first | 指定從哪個點開始繪製 |
count | 指定繪製多少個點 |
錯誤 INVALID_ENUM | 傳入的mode引數不是前述引數之一 |
錯誤 INVALID_VALUE | 引數first或者count為負數 |
總結:以上我們簡單介紹了兩個webgl程式,並初步認識了著色器。後續的章節我們將學習webgl的座標系統和更多著色器的相關知識。欲知後事如何,請動動你的手指,關注下我,我會繼續帶來webgl的分享,哈哈