自訂篩選器簡介 (又稱 CSS 著色器)

Paul Lewis

自訂篩選器 (或 CSS 著色器) 如先前呼叫,可讓您將 WebGL 著色器的功能與 DOM 內容搭配使用。由於在目前的實作中,著色器與 WebGL 中的著色器幾乎相同,因此您必須退一步,瞭解一些 3D 術語和一些圖形管線。

我們在郵件中附上了我最近傳送到 LondonJS 的簡報版本,在這部影片中,我將概略介紹您需要瞭解的 3D 術語、您會遇到哪些變數類型,以及如何立即使用自訂篩選器。此外,您也可以擷取這些投影片,自行按照示範操作。

著色器簡介

我先前撰寫了著色器簡介,其中會詳細介紹著色器的概念,以及如何透過 WebGL 視角使用著色器。如果您從未處理著著色器,需要先詳閱一下,因為現有的 WebGL 著色器術語有許多自訂篩選器概念和語言轉軸。

這樣,我們就要啟用「自訂濾鏡」和「彈性」選項了!

啟用自訂篩選器

Chrome、Canary 和 Android 版 Google Chrome 皆提供自訂篩選器。只要前往 about:flags 並搜尋「CSS 著色器」,啟用後即可重新啟動瀏覽器。現在可以出發了!

語法

自訂篩選器會根據現有篩選器 (例如 blursepia),進一步延伸至 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 內容自動對應至紋理,這意味著兩種:

  1. 為了安全起見,我們無法查詢 DOM 紋理的個別像素顏色值
  2. 我們不會 (至少在目前實作項目中) 自行設定最終像素顏色,即不限制 gl_FragColor。而是假設您想要轉譯 DOM 內容,而您將透過 css_ColorMatrixcss_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 內容分成數個三角形:

Vertex 建立
圖片依資料列和資料欄細分

接著,每個頂點都會通過我們的頂點著色器進行操作,這表示我們可以在有需要時,開始在 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;
}

開始玩!

自訂濾鏡是讓你玩得開心的有趣工具,就算沒有自訂濾鏡,也能創造出令人驚豔的效果。這項功能仍處於早期開發階段,現在情況也略有改變,但新增這些程式庫將可對專案進行些微的展示,何不付諸實現?

其他資源