http://www.adobe.com/cn/devnet/html5/articles/css-shaders.html帶給網頁電影般視覺衝擊力的CSS著色器
HTML5和CSS方面不斷湧現的成果 (如過渡,動畫,變形,文本陰影,圖形陰影,漸層和SVG) 大大提升了HTML的圖形和互動的豐富性。 現在你可以在CSS和HTML中使用.
SVG的濾鏡效果*
Filter Effects 1.0* , 除SVG外, 針對網頁內容的其他效果如灰階,復古色調,色相旋轉都逐漸成為可能。還有更進階的特效,如下面圖一展示給你的輪廓分明的效果,也將成為可能。
圖一. SVG內容加了濾鏡效果,轉自svg-wow.org網站
Adobe
CSS著色器* 已提交W3C FX專案組。CSS著色器定義一個過濾效果的可擴充性機制,它為所有HTML5內容提供豐富且容易實現的動畫視覺效果, 它們能和
CSS動畫* 和 CSS 過度*。
下面的視頻讓你體驗一下CSS 著色器讓HTML內容產生什麼樣咂舌的效果:
CSS 著色器翻頁效果 (0:39)
CSS 著色器展開地圖效果 (0:18)
CSS 著色器顯示twiter資料來源 (0:22)
這篇文章描述CSS著色器到底是什麼以及它是如何工作的,過程中會附上代碼範例,還會涉及到如何使用CSS著色器建立自訂效果和寫自己的自訂著色器。
幾點需要注意: 這是一個處在進展中的工作,隨著我們繼續更廣泛的和社會討論,我們將會做一些改變。在這篇文章中所使用的文法反映CSS著色器的建議的文法,但它很可能會隨著與W3C FX專責小組和廣泛社區的討論而演變。還要注意,按照慣例,在我們的WebKit的原型裡所有提議的新屬性的首碼都會加上-webkit-
首碼。 為了簡單起見,在本文的其餘部分我將省略此首碼。
Filter Effects 1.0
為了便於理解CSS著色器,有必要讓你對提前定義好的濾鏡做一番瞭解, 下面這個例子展示了一個簡單的濾鏡效果:滑鼠移到上面,使用者可以看到一個簡單的內容灰階漸層效果。
灰階漸層效果示範 (0:06)
<html><head> ... <style>#shaded { filter: grayscale(1); transition: filter ease-in 0.3s;}#shaded:hover { filter: grayscale(0);}</style></head><body> <div id="shaded"> <div id="multi-col"> <h2>The Creative Web</h2> <p>Lorem ipsum dolor ... </p> <img id="png-img" src="planes.jpg"/> <p>Mauris at ... </p> <img id="svg-img" src="picture.svg" /> <p>Morbi congue ....</p> <img id="css3-img" src="html5_css3_styling.svg" /> </div> </div></body></html>
使用這個濾鏡效果方法很簡單:filter
屬性定義了針對內容的一個濾鏡(或者一系列濾鏡)。你可以看到,把它和CSS動畫整合是很簡單的。filter
屬性是可以作為動畫參數實現動畫的。
在這個例子中, grayscale()
濾鏡被調用實現逐漸淡出的動畫,原因當使用者滑鼠放在目標元素上時,濾鏡函數的參數amount
被從1(完全灰階)過度到0(沒有灰階)。
W3C濾鏡效果規範草案(W3C Filter Effects 1.0)做了下面2個定義:
- 它作為定義濾鏡的通用文法,把基礎濾鏡整合在一張圖上。
- CSS
filter
屬性是一個已定義了的濾鏡的索引,你可以把一個或者多個濾鏡傳給它。
你可以把一系列的濾鏡方法傳給這個filter
屬性,如:blur(模糊), drop-shadow(陰影), gamma(伽馬), grayscale(灰階), hue-rotate(色旋轉), invert(反向), opacity(透明度), saturate(飽和度), sepia(邊緣突出), and sharpen(銳利化)等.
- blur(5, 5)
- drop-shadow(10, 5, 5)
- hue-rotate(328deg)
- saturate(5)
- invert(1)
- grayscale(1)
- opacity(0.5)
- gamma(1.1, 3.6, 0)
- sepia(0.5)
圖二. 濾鏡效果函數效果
濾鏡效果美就美在其簡單非常文法,與CSS動畫的漸層整合相當容易。
但是,有些效果實現起來就很難了,比如,怎麼只讓內容的一部分變成灰階? 或者如何?內容的以不同的方式漸層,如內容上實現掃過的效果? 或者你想實現的濾鏡效果在預先定義好的濾鏡包裡沒有? 這就是CSS著色器誕生的原因。
CSS著色器提出在預定義的過濾器和CSS動畫過渡的過濾效果集中添加自訂方法custom()
。CSS著色器為建立任意的效果提供了靈活性和表現力,通過它實現從最簡單的到最複雜的效果都沒有問題。
CSS著色器實現進階特效
這裡我從一個例子開始,上邊提過的灰階效果的例子很不錯, 但它任然有改進的餘地。 下面這個視頻展示了一個更加強大的效果: 隨著內容從灰階到彩色漸層,它會閃動幾下,同時,一個色彩效果從底部到頂部掃過去。
這個例子使用了一個vertex著色器實現閃動效果,一個像素著色器實現顏色橫掃。二者都是通過自訂濾鏡被引用的,這個自訂濾鏡也帶了參數方便著色器的配置。下面是代碼:
<html><head> ... <style>#shaded { filter: custom(url('wobble.vs') /* wobble effect */ url('color-swipe.fs'), /* swipe effect */ 40 40, /* mesh lines/cols */ amplitude 60, /* wobble strength */ amount 0.0); /* effect amount */ transition: filter ease-in-out 2s; ...;}#shaded:hover { filter: custom(url('wobble.vs') url('color-swipe.fs'), 40 40, amplitude 60, amount 1.0);}</style></head><body> <div id="shaded"> <div id="multi-col"> <h2>The Creative Web</h2> <!-- Same as previous example --> </div> </div></body></html>
著色器規範我們將在日後詳細討論。目前重要的是讓你們瞭解各個著色器都帶給你什麼樣的效果,以及向外暴露什麼參數供CSS來控制。
在這個例子中,自訂濾鏡使用了wobble.vs
頂點著色器實現變形、 color-swipe.fs
片段著色器實現灰階到常色掃過的轉場效果。
著色器是什嗎?
著色器在3D圖形中是常見的,它們(一般是)處理3D幾何面(vertex 著色器)和顏色像素(片段著色器)的小程式。
比如vertex著色器能夠實現表面如旗子飄動的效果,或者翻滾效果,就如前面例子一樣。片段著色器(通常叫做像素著色器)能夠實現任意方式的計算來控制像素的顏色。CSS著色器能夠駕驅於硬體加速著色器軟體的強大功能。
CSS著色器如何工作的?
有了CSS著色器,你可以把你的HTML和SVG元素變成一個頂點網格(在第二步),這可以實現各種變形,即使可能在3D場合中。第三步,網格能夠被渲染(或者合并)為像素交給片段著色器上色。
圖三. CSS著色器處理模型.
作為一個開發人員,你可以控制網格的顆粒度,你可以定義參數控制著色器。在這個例子中,有著色器ID的元素被設定了濾鏡參數:
custom(url('wobble.vs') /* wobble effect */ url('color-swipe.fs'), /* swipe effect */ 40 40, /* mesh lines/cols */ amplitude 60, /* wobble strength */ amount 0.0); /* effect amount */
wobble.vs
和 color-swipe.fs
著色器內部設定,當參數為0時,內容整體灰階上將不會有任何翻滾和像素著色器。wobble.vs和color-swipe.fs著色器內部設定,當參數為0時,內容整體灰階上將不會有任何翻滾和像素著色器。
當使用者滑鼠經過目標內容,它的濾鏡屬性就被設定為:
custom(url('wobble.vs') url('color-swipe.fs'), 40 40, amplitude 60, amount 1)
再次提醒,那些參數的意義會因著色器而異。在這個例子中,原著色器作者做出規定, 如果參數為0.5, 那麼翻滾達到最大效果,參數為1時,動作將變為靜止。顏色橫掃著色器是這樣的:在0.0到1.0之間, 效果從底部到頂部以shine曲線過渡。觀察上面的視頻你能夠更好地理解這個視覺效果。
就如前面提到的灰階濾鏡例子,與CSS整合實現效果的做法一樣,同樣非常簡單,只要使用漸層屬性就ok了。
開發著色器
在現實開發中,大多數人將通過配置參數充分發揮著色器提供的完美的自訂效果,就如前面提到的例子。
開發著色器,從中做些實踐並不是那麼難。其實其中有一個小秘密,就是這個過程中你會享受到無窮的樂趣。
著色器的開發語言是OpenLG ES 語言*,和開發
WebGL*著色器使用的是同一種語言。 這裡是上面產生翻滾效果中用的頂點著色器的例子。
如果你不瞭解著色器,下面術語能夠協助你理解這個例子:
- Vertex:(頂點)供著色器作處理的幾何座標
- Texture:(光柵映像). CSS著色器把元素的渲染轉換為材質供vertex和片段著色器處理
- Attributes:(屬性)基於每個頂點的參數, 傳給vertex 著色器
- Uniform:(全域參數)面對所有頂點和面的全域參數,由custom()方法傳給著色器
- Projection Matrix: (投射矩陣)是一個將 歸一化的頂點座標範圍(沿每個座標軸[-0.5, +0.5] s)的座標點轉換回實際視角的座標系統座標點的矩陣
precision mediump float; /* required */// ================= Per-vertex attributes =================== //attribute vec3 a_position; /* The vertex's coordinates */attribute vec2 a_texCoord; /* The vertext's texture coordinate */// Uniform parameters are available to shaders and have the // same value for all vertex or pixel.uniform mat4 u_projectionMatrix; /* The projection matrix */// ================ Shader parameters ======================== //uniform float amplitude;uniform float amount;// ============== End shader parameters ====================== //const float rotate = 20.0; /* could be made a uniform */ /* to allow control form CSS */const float PI = 3.14...;varying vec2 v_texCoord;mat4 rotateX(float f) {...}mat4 rotateY(float f) {...}mat4 rotateZ(float f) {...}void main(){ v_texCoord = a_texCoord.xy; vec4 pos = vec4(a_position, 1.0); float r = 1.0 - abs((amount - 0.5) / 0.5); float a = r * rotate * PI / 180.0; mat4 rotX = rotateX(a); mat4 rotY = rotateY(a / 4.0); mat4 rotZ = rotateZ(a / 8.0); float dx = 0.01 * cos(3.0 * PI * (pos.x + amount)) * r; float dy = 0.01 * cos(3.0 * PI * (pos.y + amount)) * r; float dz = 0.1 * cos(3.0 * PI * (pos.x + pos.y + amount)) * r; pos.x += dx; pos.y += dy; pos.z += dz; gl_Position = u_projectionMatrix * rotZ * rotY * rotX * pos;}
這是那個例子中用的顏色橫掃著色器代碼:
precision mediump float; /* required */// The 'original' content rendering in a texture.uniform sampler2D s_texture;// ================ Shader parameters ======================== //uniform float amplitude; /* unused in this fragment shader */uniform float amount;// ============== End shader parameters ====================== //varying vec2 v_texCoord;// The desired 'color swipe' color.const vec4 swipeColor = vec4(1.0, 1.0, 1.0, 1.0); vec4 grayscale(vec4 color) { ...; return gray;}void main() { vec4 color = texture2D(s_texture, v_texCoord); vec4 gray = grayscale(color); vec2 pos = v_texCoord; float p = 1.0 - pos.y; /* progress from bottom to top */ vec4 sc = swipeColor * color.a; float threshold = amount * 1.2; if (p < threshold) { float a = min(abs(threshold - p) / 0.2, 1.0); gl_FragColor = mix(sc, color, a); } else { float a = min(abs(threshold - p) / 0.005, 1.0); gl_FragColor = mix(sc, gray, a); }}
網上有很多不錯的資源會對你的著色器開發有協助,一切類庫也包含了很棒的著色器套件(參看文章底部的連結)
著色語言,如OpenGL ES,都是讓視覺效果開發變得簡單,CSS著色器將這些很棒的表現元素與CSS句法緊緊相連,讓它產生這些效果變得異常容易。
和WebGL作對比
WebGL* 提供了HTML5畫布元素的實現方案,它為畫布提供了3D上下文,在這個上下文裡面,你可以訪問到像素著色器(和其他頂點著色器以及WebGL提供的其他3D特性),WebGL的作用範圍僅僅在canvas*
範圍內。
與此形成鮮明對比的是,CSS著色器可以應用任何著色器到任何網頁內容。
下一步該怎麼辦?
Adobe作為FX主力軍的一員正把CSS著色器貢獻給W3C, 我們的目標是一旦得到W3C的肯定,我們將著手把代碼貢獻給WebKit,這樣不久網站開發人員們就能夠受益於這套全新強大的濾鏡效果集了。
與此同時, 你可能想參考下面的資源擷取更多關於CSS動畫和特效的相關資訊:
- FX Task Force*
- CSS Animations*
- CSS Transitions*
- Filter Effects 1.0*
- CSS 2D Transforms*
- CSS 3D Transforms*
- OpenGL ES 2.0*
- OpenGL ES Shading Language* (PDF)
- WebGL*
- WebGL Wiki*
- GLFX.js*
+
本文遵守知識共用—署名-非商業性使用-相同方式共用3.0 Unported License (Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License)許可條件。 適合本文包含的代碼範例、但超越本許可條件範圍的其它許可條件能夠在Adobe中查到。
關於作者
Vincent 致力於互連網標準工程,現於CSS工作群組、FX專責小組以及SVG工作群組工作。目前他正致力於CSS著色器(CSS shaders)、CSS 地區(CSS regions)、CSS排除(CSS exclusions)以及可伸縮向量圖形(SVG)的研究。在加入Adobe之前,Vincent供職於Oracle公司,主要是在商業智慧領域從事圖形、互動以及使用者介面動畫製作的工作,他使得大量複雜的資料集變得直觀可解,讓使用者能夠更為方便地設定瀏覽資料、檢測趨勢,或是發現異常。而在加入Oracle以前,Vincent在Sun
Microsystems工作,在那裡他專註於圖形、動畫及互動技術的研究,其中Java 2D API 以及SVG格式方面則是他最重要的關注點。
Vincent在Apache(軟體基金會的支援下)與人共同發起並領導了Batik項目,這是一個開源Java工具包,用於操控、查看或SVG內容的代碼轉換。Vincent為SVG規範及其在行動裝置上的版本——SVG微型簡化版本(SVG Tiny)——的發展做出了巨大貢獻。他在全球資訊網聯盟(W3C)主持複合文檔格式(CDF)方面的事務。Vincent還是
《Java 2D API 圖形》(Java 2D API Graphics)一書的作者,對於圖形設計,他總是抱有極大的熱情。