WebGL 顏色與紋理使用介紹
引言
基于之前的知識,這里主要是
- 將頂點的其他數(shù)據(jù)--如顏色等-傳入頂點著色器
- 圖元光柵化--在頂點著色器和片元著色器之間的從圖形到片元的轉(zhuǎn)化
- 將紋理映射到圖形或三維對象的表面上
顏色
三角形顏色
在之前的例子中,我們繪制了三角形的圖形,并給它填充了顏色,如果想要顏色是漸變的,則可以把顏色和頂點類似在不同的頂點上設(shè)置不同的顏色向量值。

著色器中
const VSHADER_SOURCE = `
attribute vec4 a_position;
attribute vec4 aColor;
varying vec4 vColor;
void main(void){
gl_Position=a_position;
vColor = aColor;
}
`
const FSHADER_SOURCE = `
precision mediump float;
varying vec4 vColor;
void main() {
gl_FragColor = vColor;
}
`
定義了aColor屬性,這樣可以再去設(shè)置不同頂點上對應(yīng)的顏色值
let aPsotion = webgl.getAttribLocation(webgl.program, "a_position") let arr = [ -0.5, 0.5, 0.0, 1.0, 0.0, 0.0, 1.0, // 左上角,紅色 -0.5, -0.5, 0.0, 0.0, 1.0, 0.0, 1.0, // 左下角,綠色 0.5, -0.5, 0.0, 0.0, 0.0, 1.0, 1.0, // 右下角,藍(lán)色 ] let vertexArr = new Float32Array(arr) let trangleBuffer = webgl.createBuffer() webgl.bindBuffer(webgl.ARRAY_BUFFER, trangleBuffer) webgl.bufferData(webgl.ARRAY_BUFFER, vertexArr, webgl.STATIC_DRAW) webgl.enableVertexAttribArray(aPsotion) webgl.vertexAttribPointer(aPsotion, 3, webgl.FLOAT, false, 7 * Float32Array.BYTES_PER_ELEMENT, 0) const colorAttributeLocation = webgl.getAttribLocation(webgl.program, "aColor"); webgl.vertexAttribPointer(colorAttributeLocation, 4, webgl.FLOAT, false, 7 * Float32Array.BYTES_PER_ELEMENT, 3 * Float32Array.BYTES_PER_ELEMENT); webgl.enableVertexAttribArray(colorAttributeLocation);
在這里有兩個大的步驟
- 圖形裝配過程:將頂點坐標(biāo)構(gòu)成幾何圖形
- 光柵化過程:將圖形轉(zhuǎn)化成片元
在光柵化結(jié)束后,程序開始逐個的片元調(diào)用片元著色器, 那么在這三個點之間的顏色,WebGL系統(tǒng)用這3個頂點的顏色內(nèi)插出來的,這個過程被稱為內(nèi)插過程
具體解析: 在頂點著色器中,三角形的3個頂點的顏色賦給varying變量v_Color,然后片元著色器中的varying變量v_Color就接收到了內(nèi)插之后的片元顏色,在片元著色器中,我們把片元的顏色賦值給gl_FragColor變量,這樣就繪制出了一個彩色的三角形。
紋理
什么是紋理?
可以形象的理解成某個物體的“皮膚”,而這個“皮膚”可以看成是一張圖片,而這張圖片中每一個點是一個片元(紋素),每個片元上涂上合適的顏色。
術(shù)語:貼圖或是紋理映射
- 準(zhǔn)備好需要映射到物體上的紋理圖像,例如
PNG、BMP、DDS、HDR等 - 給幾何圖形配置的紋理映射方式
- 加載紋理圖像,并進(jìn)行配置,以在
WebGL中使用 - 在片元著色器中將相應(yīng)的紋素從紋理中抽取出來,并將紋素中的顏色通過片元進(jìn)行繪制
紋理坐標(biāo)
紋理坐標(biāo)是紋理圖像上的坐標(biāo),通過紋理坐標(biāo)可以在紋理圖像上獲取紋素顏色,WebGL系統(tǒng)中紋理坐標(biāo)是二維的,簡稱st坐標(biāo)系統(tǒng)
注意:紋理坐標(biāo)和區(qū)域坐標(biāo)的關(guān)系
const vertices = [ // 頂點坐標(biāo) // 紋理坐標(biāo) -0.5, 0.5, 0.0, 0.0, 1.0, // 左上角 0.5, 0.5, 0.0, 1.0, 1.0, // 右上角 0.5, -0.5, 0.0, 1.0, 0.0, // 右下角 -0.5, -0.5, 0.0, 0.0, 0.0 // 左下角 ];
這樣你在腦海中就有一個概念了,頂點坐標(biāo)和紋理坐標(biāo)的關(guān)系映射。 當(dāng)我們在區(qū)域內(nèi)繪制了紋理圖像,你會發(fā)現(xiàn),這個圖片和原來的圖片是旋轉(zhuǎn)了90°,這個又涉及到了一個概念:圖片坐標(biāo)
特別說明: 圖片坐標(biāo)
以左上角為原點,向右為x軸正方向,向下為y軸正方向。也就是說,對于一個像素點(x,y),x表示橫坐標(biāo),y表示縱坐標(biāo),坐標(biāo)軸的方向如下圖所示:
(0,0)----------------> x | | | | v y
但WebGL中的坐標(biāo)向上為y軸正方向,所以導(dǎo)致圖片是倒立的。
解決方案
先把解決辦法給出來吧,兩張方式,選取一種即可
- 在圖片的
onload方法中:webgl.pixelStorei(webgl.UNPACK_FLIP_Y_WEBGL, 1) - 在片元著色器中
gl_FragColor = texture2D(u_texture, vec2(v_texcoord.x, 1.0 - v_texcoord.y));
其目的都是對紋理圖像進(jìn)行Y軸(T軸)的反轉(zhuǎn)
紋理圖像
類似于蒙版效果

實現(xiàn)過程
- 頂點著色器中點的坐標(biāo)繪制區(qū)域
- 紋理坐標(biāo)用來裝圖片
- 通過紋理映射
texture2D將區(qū)域換上“皮膚”
著色器設(shè)置
const VSHADER_SOURCE = `
attribute vec2 a_position;
varying vec2 v_texcoord;
void main() {
gl_Position = vec4(a_position, 0.0, 1.0);
v_texcoord = a_position * 0.5 + 0.5;
}
`
const FSHADER_SOURCE = `
precision mediump float;
uniform sampler2D u_texture;
varying vec2 v_texcoord;
void main() {
gl_FragColor = texture2D(u_texture, vec2(v_texcoord.x, 1.0 - v_texcoord.y));
}
`
著色器中使用sampler2D類型的變量來訪問紋理數(shù)據(jù)
看看核心的方法
const texture = webgl.createTexture()
const image = new Image()
image.src = ''
texture.image = image
image.onload = function () {
webgl.bindTexture(webgl.TEXTURE_2D, texture)
webgl.texParameteri(
webgl.TEXTURE_2D,
webgl.TEXTURE_WRAP_S,
webgl.CLAMP_TO_EDGE
)
webgl.texParameteri(
webgl.TEXTURE_2D,
webgl.TEXTURE_WRAP_T,
webgl.CLAMP_TO_EDGE
)
webgl.texParameteri(
webgl.TEXTURE_2D,
webgl.TEXTURE_MIN_FILTER,
webgl.LINEAR
)
webgl.texImage2D(
webgl.TEXTURE_2D,
0,
webgl.RGBA,
webgl.RGBA,
webgl.UNSIGNED_BYTE,
texture.image
)
const textureLoc = webgl.getUniformLocation(webgl.program, 'u_texture');
webgl.uniform1i(textureLoc, 0);
draw()
webgl.drawArrays(webgl.TRIANGLE_STRIP, 0, 4);
}
texParameteri() 設(shè)置紋理圖片的參數(shù)
參數(shù):
TEXTURE_WRAP_T、CLAMP_TO_EDGE: 設(shè)置紋理 S/T 軸方向上的邊緣環(huán)繞方式為 CLAMP_TO_EDGE,即在超出邊緣的部分使用紋理邊緣的像素顏色填充.- TEXTURE_MIN_FILTER、
LINEAR: 設(shè)置紋理的縮小過濾方式為 LINEAR,即當(dāng)紋理需要被縮小時,使用線性過濾的方式得到縮小后的像素顏色值.
texImage2D 加載紋理圖片
- 第一個參數(shù)是紋理類型
- 第二個參數(shù)是細(xì)節(jié)級別
- 第三個參數(shù)是紋理格式
- 第四個參數(shù)也是紋理格式
- 第五個參數(shù)是紋理數(shù)據(jù)的類型
- 最后一個參數(shù)是要加載的紋理圖片
這里使用了 RGBA 格式,表示紅、綠、藍(lán)和透明度,使用 UNSIGNED_BYTE 數(shù)據(jù)類型,表示每個顏色分量使用一個字節(jié)存儲
uniform1i()
- location:表示要傳遞給哪個
uniform變量的位置 - value:表示要傳遞的整數(shù)值
注意哦! 這里的value可不能隨便個整數(shù)
在WebGL中,紋理單元編號從0開始,最多可以使用16個紋理單元。因此,如果你想使用第一個紋理單元,就需要將value設(shè)置為0;如果你想使用第二個紋理單元,就需要將value設(shè)置為1
本想把多重紋理放在這一篇,但發(fā)現(xiàn)篇幅會很長,所以放在了下一篇,主要實現(xiàn)多個圖片的疊加,當(dāng)然是在紋理層面上的疊加了。
我們可以先看看效果

以上就是WebGL 顏色與紋理使用介紹的詳細(xì)內(nèi)容,更多關(guān)于WebGL 顏色紋理的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
js設(shè)置document.domain實現(xiàn)跨域的注意點分析
這篇文章主要介紹了js設(shè)置document.domain實現(xiàn)跨域的注意點,較為詳細(xì)的分析了document.domain跨域的相關(guān)技巧,需要的朋友可以參考下2015-05-05
JavaScript 組件之旅(三):用 Ant 構(gòu)建組件
我們走到哪兒了?前兩期思考了太多東西,你是否已有倦意?別擔(dān)心,本期的話題很輕松,你只需要簡單了解一些語法,寫幾行配置,就能驅(qū)使系統(tǒng)按你預(yù)設(shè)的方式自動完成一些工作。2009-10-10

