本章主要內(nèi)容:
(1) 將頂點(diǎn)的其他(非坐標(biāo))數(shù)據(jù) —— 如顏色等 —— 傳入頂點(diǎn)著色器
(2)發(fā)生在頂點(diǎn)著色器和片元著色器之間的從圖形到片元的轉(zhuǎn)化勉躺,又稱(chēng)圖元光柵化(rasterzation process)
(3)將圖形(或稱(chēng)紋理)映射到圖形或三維對(duì)象的表面上胖喳。
- 將頂點(diǎn)坐標(biāo)傳入著色器孝常,步驟:
(1)創(chuàng)建緩沖區(qū)對(duì)象七冲。
(2)將緩沖區(qū)對(duì)象綁定到tartget
上背镇。
(3)將頂點(diǎn)坐標(biāo)數(shù)據(jù)寫(xiě)入緩沖區(qū)對(duì)象锨用。
(4)將緩沖區(qū)對(duì)象分配給對(duì)應(yīng)的attribute
變量丰刊。
(5)開(kāi)啟attribute
變量。
交錯(cuò)組織
(interleaving):將頂點(diǎn)坐標(biāo)和尺寸數(shù)據(jù)打包到同一緩沖區(qū)對(duì)象中增拥。gl.vertexAttribPointer()
varying 變量
: 從頂點(diǎn)著色器向片元著色器中傳入數(shù)據(jù)啄巧。
varying 變量只能是float(以及相關(guān)的vec2寻歧,vec3,vec4秩仆,mat2码泛,mat3,mat4)澄耍。在頂點(diǎn)著色器和片元著色器之間噪珊,有兩個(gè)步驟:
[1]圖形裝配過(guò)程:將孤立的頂點(diǎn)坐標(biāo)裝配成幾何圖形。幾何圖形的類(lèi)別由
gl.drawArray() `函數(shù)的第一個(gè)參數(shù)決定齐莲。
輸入數(shù)據(jù):gl_Position
[2] 光柵化過(guò)程:將裝配好的幾何圖形轉(zhuǎn)為片元痢站。
步驟:
(1)根據(jù) gl.drawArrays()
的參數(shù)n,將執(zhí)行頂點(diǎn)著色器n次(執(zhí)行頂點(diǎn)著色器結(jié)果:將坐標(biāo)傳入并存儲(chǔ)在裝配區(qū))
(2)開(kāi)始裝配圖形选酗。使用傳入的點(diǎn)坐標(biāo)阵难,根據(jù) gl.drawArrays()
的第一個(gè)參數(shù)信息(如:gl.TRANGLES)來(lái)決定如何裝配。
(3)光柵化
- 顏色內(nèi)插(interpolation)
-
紋理映射
(texture mapping):根據(jù)紋理圖像芒填,為之前光柵化后的每個(gè)片元涂上合適的顏色呜叫。
紋素
(texels, texture elements):組成紋理圖像的像素。每一個(gè)紋素的顏色都是用RGB或RGBA格式編碼氢烘。
在WebGL中怀偷,要進(jìn)行紋理映射,需遵循以下四步:
(1)準(zhǔn)備好映射到幾何圖形上的紋理圖像播玖。
(2)為幾何圖形配置紋理映射方式椎工。
(3)加載紋理圖像,對(duì)其進(jìn)行一些配置蜀踏,以在WebGL中使用它维蒙。
(4)在片元著色器中將相應(yīng)的紋素從紋理中抽取出來(lái),并將紋素的顏色賦給片元果覆。紋理坐標(biāo)
紋理坐標(biāo)
是紋理圖像上的坐標(biāo)颅痊,通過(guò)紋理坐標(biāo)可以在紋理圖像上獲取紋素顏色。
WebGL系統(tǒng)中的紋理坐標(biāo)系統(tǒng)是二維的局待。
WebGL中使用s和t命名紋理坐標(biāo)斑响。(st坐標(biāo)系統(tǒng))
- 將紋理圖像粘貼到幾何圖形上
在WebGL中,我們通過(guò)紋理圖像的紋理坐標(biāo)與幾何圖形頂點(diǎn)坐標(biāo)間的映射關(guān)系钳榨,來(lái)確定怎樣將紋理圖像貼上去舰罚。
- 紋理映射過(guò)程詳解
步驟:
(1)頂點(diǎn)著色器中接收定點(diǎn)的紋理坐標(biāo),光柵化后傳遞給片元著色器薛耻。
(2)片元著色器根據(jù)片元的紋理坐標(biāo)营罢,從紋理圖像中抽取出紋素顏色,賦給當(dāng)前片元饼齿。
(3)設(shè)置頂點(diǎn)的紋理坐標(biāo)(initVertexBuffers()
)
var verticesTexCoords = new Float32Array([
-0.5, 0.5, 0.0, 1.0,
-0.5, -0.5, 0.0, 0.0,
0.5, 0.5, 1.0, 1.0,
0.5, -0.5, 1.0, 0.0,
])
將頂點(diǎn)坐標(biāo)和紋理坐標(biāo)寫(xiě)入緩沖區(qū)對(duì)象饲漾,將其中的頂點(diǎn)坐標(biāo)分配給a_Position變量并開(kāi)啟之蝙搔。
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, FSIZE * 4, 0);
gl.enableVertexAttribArray(a_Position);
獲取a_TexCoord
變量的存儲(chǔ)位置,將緩沖區(qū)中的紋理坐標(biāo)分配給該變量更開(kāi)啟考传。
var a_TexCoord = gl.getAttribLocation(gl.program, 'a_TexCoord');
gl.vertexAttribPointer(a_TexCoord, 2, gl.FLOAT, false, FSIZE * 4, FSIZE * 2);
gl.enableVertexAttribArray(a_TexCoord);
(4)準(zhǔn)備待加載的紋理圖像吃型,令瀏覽器讀取它(initTextures())
initTextures() => 配置和加載問(wèn)題
調(diào)用gl.createTexture()
創(chuàng)建紋理對(duì)象
var texture = gl.createTexture();
同樣,也可以使用gl.deleteTeture()來(lái)刪除一個(gè)紋理對(duì)象伙菊。如果試圖刪除一個(gè)已經(jīng)被刪除的紋理對(duì)象败玉,不會(huì)報(bào)錯(cuò)也不會(huì)產(chǎn)生任何影響敌土。
調(diào)用gl.getUniformLocation()
從片元著色器中獲取uniform
變量u_Sampler
(取樣器)的存儲(chǔ)位置镜硕,該變量用來(lái)接收紋理圖像
var u_Sampler = gl.getUniformLocation(gl.program, 'u_Sampler');
創(chuàng)建image對(duì)象
var image = new Image();
注冊(cè)圖像加載事件的響應(yīng)函數(shù)
image.onload = function(){ loadTexture(gl, n, texture, u_Sampler, image); };
瀏覽器開(kāi)始加載圖像
image.src = '../resources/sky.jpg';
(5)監(jiān)聽(tīng)紋理圖像的加載事件,一旦加載完成返干,就在WebGL系統(tǒng)中使用紋理(loadTexture())兴枯。
loadTexture()
=> 配置紋理供WebGL使用
對(duì)紋理圖像進(jìn)行y軸翻轉(zhuǎn)(WebGL紋理坐標(biāo)中的t軸的方向和PNG、BMP矩欠、JPG等格式圖片的坐標(biāo)系統(tǒng)的Y軸方向是相反的财剖。)
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
開(kāi)啟0號(hào)紋理單元
WebGL通過(guò)紋理單元的機(jī)制來(lái)同時(shí)使用多個(gè)紋理。
每個(gè)紋理單元有一個(gè)單元編號(hào)來(lái)管理一張紋理圖像癌淮。
系統(tǒng)支持的紋理單元格數(shù)取決于硬件和瀏覽器的WebGL實(shí)現(xiàn)躺坟,但是在默認(rèn)情況下,WebGL至少支持8個(gè)紋理單元乳蓄。
在使用紋理單元之前咪橙,還需要調(diào)用gl.aactiveTexture()
來(lái)激活它。
gl.activeTexture(gl.TEXTURE0);
綁定紋理對(duì)象(設(shè)置紋理的類(lèi)型)
gl.bindTexture(gl.TEXTURE_2D, texture);
配置紋理對(duì)象的參數(shù) => 設(shè)置紋理圖像映射到圖形上的具體方式
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
配置紋理圖像 => 將紋理圖像分配給紋理對(duì)象虚倒,同時(shí)允許你告訴WebGL系統(tǒng)關(guān)于該圖像的一些特性美侦。
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image);
format標(biāo)示紋理數(shù)據(jù)的格式,必須根據(jù)紋理圖像的格式來(lái)選擇這個(gè)參數(shù)
JPG => gl.RGB
PNG => gl.RGBA
BMP => gl.RGB
gl.LUMUNANCE
和 gl.LUMINANCE_ALPHA
通常用在灰度圖像上等等
流明
(luminance)標(biāo)示我們感知到的物體表面的亮度魂奥。通常使用物體表面紅菠剩、藍(lán)顏色分量指的加權(quán)平均來(lái)計(jì)算流明。
type
參數(shù)制定了紋理數(shù)據(jù)類(lèi)型耻煤。通常使用gl.UNSIGNED_BYTE
數(shù)據(jù)類(lèi)型具壮。
分配后的WebGL系統(tǒng):
將0號(hào)紋理傳遞給著色器中的取樣器變量
gl.uniform1i(u_Sampler, 0);
uniform sampler2D u_Sampler;
分配給unform
變量后的WebGL系統(tǒng):
繪制矩形
gl.drawArrays(gl.TRIANGLE_STRIP, 0, n);
從頂點(diǎn)著色器向片元著色器傳輸紋理坐標(biāo)
var VSHADER_SOURCE =
'attribute vec4 a_Position;\n' +
'attribute vec2 a_TexCoord;\n' +
'varying vec2 v_TexCoord;\n' +
'void main() {\n' +
' gl_Position = a_Position;\n' +
' v_TexCoord = a_TexCoord;\n' +
'}\n';
在片元著色器中獲取紋理像素顏色(texture2D())
gl_FragColor = texture2D(u_Sampler, v_TexCoord);