自訂篩選器 (或 CSS 著色器) 如先前呼叫,可讓您將 WebGL 著色器的功能與 DOM 內容搭配使用。由於在目前的實作中,著色器與 WebGL 中的著色器幾乎相同,因此您必須退一步,瞭解一些 3D 術語和一些圖形管線。
我們在郵件中附上了我最近傳送到 LondonJS 的簡報版本,在這部影片中,我將概略介紹您需要瞭解的 3D 術語、您會遇到哪些變數類型,以及如何立即使用自訂篩選器。此外,您也可以擷取這些投影片,自行按照示範操作。
著色器簡介
我先前撰寫了著色器簡介,其中會詳細介紹著色器的概念,以及如何透過 WebGL 視角使用著色器。如果您從未處理著著色器,需要先詳閱一下,因為現有的 WebGL 著色器術語有許多自訂篩選器概念和語言轉軸。
這樣,我們就要啟用「自訂濾鏡」和「彈性」選項了!
啟用自訂篩選器
Chrome、Canary 和 Android 版 Google Chrome 皆提供自訂篩選器。只要前往 about:flags
並搜尋「CSS 著色器」,啟用後即可重新啟動瀏覽器。現在可以出發了!
語法
自訂篩選器會根據現有篩選器 (例如 blur
或 sepia
),進一步延伸至 DOM 元素。Eric Bidelman 為這些功能編寫了很棒的遊樂場工具,建議您一探究竟。
如要將自訂篩選器套用至 DOM 元素,請使用下列語法:
.customShader {
-webkit-filter:
custom(
url(vertexshader.vert)
mix(url(fragment.frag) normal source-atop),
/* Row, columns - the vertices are made automatically */
4 5,
/* We set uniforms; we can't set attributes */
time 0)
}
您將會看到我們宣告的頂點和片段著色器、我們想要讓 DOM 元素細分的列數和欄數,以及我們想要傳遞的任何統一樣式。
最後值得一提的是,我們透過混合模式 (normal
) 和複合模式 (source-atop
) 在片段著色器周圍使用 mix()
函式。我們來看看片段著色器本身,以瞭解我們甚至需要 mix()
函式的原因。
像素推送
如果您熟悉 WebGL 的著色器,就會發現「自訂篩選器」的功能稍有不同。針對其中一個,我們沒有建立片段著色器用來填滿像素的紋理。系統不會將套用篩選器的 DOM 內容自動對應至紋理,這意味著兩種:
- 為了安全起見,我們無法查詢 DOM 紋理的個別像素顏色值
- 我們不會 (至少在目前實作項目中) 自行設定最終像素顏色,即不限制
gl_FragColor
。而是假設您想要轉譯 DOM 內容,而您將透過css_ColorMatrix
和css_MixColor
間接操控其像素。
這表示片段著色器的 Hello World 看起來會像這樣:
void main() {
css_ColorMatrix = mat4(1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0);
css_MixColor = vec4(0.0, 0.0, 0.0, 0.0);
// umm, where did gl_FragColor go?
}
系統會將 DOM 內容的每個像素乘以 css_ColorMatrix
,在上述情況中,身分矩陣並不會改變任何 RGBA 值。如有需要,只要保留紅色的值,我們就會使用 css_ColorMatrix
,如下所示:
// keep only red and alpha
css_ColorMatrix = mat4(1.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 1.0);
您可以看到將 4D (RGBA) 像素值乘以矩陣所得到的像素值,而不是另一邊取得經過操控的像素值,在本例中,這個數字會零掉綠色和藍色元件。
css_MixColor
主要是做為您希望的基礎顏色,與 DOM 內容搭配使用。你熟悉的融合模式包括疊加、螢幕、色彩凸顯、硬光等熟悉的混合模式。
這兩個變數可透過多種方式操控像素。請參閱濾鏡效果規格,進一步瞭解混合模式和複合模式的互動方式。
Vertex 建立
我們負責在 WebGL 建立網格的 3D 點,但是在「自訂篩選器」中,只需指定所需的列數和欄數,瀏覽器就會自動將您的 DOM 內容分成數個三角形:
接著,每個頂點都會通過我們的頂點著色器進行操作,這表示我們可以在有需要時,開始在 3D 空間中四處移動這些頂點。不用多久,就能製作出令人讚嘆的效果!
使用著色器建立動畫
在著色器中使用動畫,是有趣和吸引人的關鍵。做法是在 CSS 中使用轉場效果 (或動畫) 來更新統一值:
.shader {
/* transition on the filter property */
-webkit-transition: -webkit-filter 2500ms ease-out;
-webkit-filter: custom(
url(vshader.vert)
mix(url(fshader.frag) normal source-atop),
1 1,
time 0);
}
.shader:hover {
-webkit-filter: custom(
url(vshader.vert)
mix(url(fshader.frag) normal source-atop),
1 1,
time 1);
}
因此,在上述程式碼中,需要注意的是在轉場期間,時間會從 0
減少到 1
。在著色器中,我們可以宣告統一的 time
,並使用其目前的值:
uniform float time;
uniform mat4 u_projectionMatrix;
attribute vec4 a_position;
void main() {
// copy a_position to position - attributes are read only!
vec4 position = a_position;
// use our time uniform from the CSS declaration
position.x += time;
gl_Position = u_projectionMatrix * position;
}
開始玩!
自訂濾鏡是讓你玩得開心的有趣工具,就算沒有自訂濾鏡,也能創造出令人驚豔的效果。這項功能仍處於早期開發階段,現在情況也略有改變,但新增這些程式庫將可對專案進行些微的展示,何不付諸實現?