带给网页电影般视觉冲击力的CSS着色器

移动开发
HTML5和CSS方面不断涌现的成果 (如过渡,动画,变形,文本阴影,图形阴影,渐变和SVG) 大大提升了HTML的图形和互动的丰富性。

HTML5和CSS方面不断涌现的成果 (如过渡,动画,变形,文本阴影,图形阴影,渐变和SVG) 大大提升了HTML的图形和互动的丰富性。 现在你可以在CSS和HTML中使用. SVG的滤镜效果  Filter Effects 1.0 , 除SVG外, 针对网页内容的其他效果如灰度,棕褐色调,色相旋转都逐渐成为可能。还有更高级的特效,如下面图一展示给你的轮廓分明的效果,也将成为可能。

图一. SVG内容加了滤镜效果,转自svg-wow.org网站

图一. 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)

这里是这个灰度渐变效果的代码:

  1. <html> 
  2. <head>                                                        
  3.     ...     
  4. <style> 
  5. #shaded {  
  6.     filter: grayscale(1);  
  7.     transition: filter ease-in 0.3s;  
  8. }  
  9.  
  10. #shaded:hover {  
  11.     filter: grayscale(0);  
  12. }  
  13. </style> 
  14. </head> 
  15.  
  16. <body> 
  17.     <div id="shaded"> 
  18.         <div id="multi-col"> 
  19.             <h2>The Creative Web</h2> 
  20.  
  21.             <p>Lorem ipsum dolor ... </p> 
  22.             <img id="png-img" src="planes.jpg"/> 
  23.  
  24.             <p>Mauris at ... </p> 
  25.             <img id="svg-img" src="picture.svg" /> 
  26.               
  27.             <p>Morbi congue ....</p> 
  28.             <img id="css3-img" src="html5_css3_styling.svg" /> 
  29.               
  30.         </div> 
  31.     </div> 
  32. </body> 
  33. </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着色器实现高级特效

这里我从一个例子开始,上边提过的灰度效果的例子很不错, 但它任然有改进的余地。 下面这个视频展示了一个更加强大的效果: 随着内容从灰度到彩色渐变,它会闪动几下,同时,一个色彩效果从底部到顶部扫过去。

简单CSS着色器演示 (0:10)

这个例子使用了一个vertex着色器实现闪动效果,一个像素着色器实现颜色横扫。二者都是通过自定义滤镜被引用的,这个自定义滤镜也带了参数方便着色器的配置。下面是代码:

  1. <html> 
  2. <head>                                                        
  3.     ...     
  4. <style> 
  5. #shaded {  
  6.     filter: custom(url('wobble.vs')        /* wobble effect */  
  7.                    url('color-swipe.fs'), /* swipe effect  */  
  8.                    40 40,                 /* mesh lines/cols */  
  9.                    amplitude 60,          /* wobble strength */  
  10.                    amount 0.0);           /* effect amount */  
  11.     transition: filter ease-in-out 2s;  
  12.     ...;  
  13. }  
  14.  
  15. #shaded:hover {  
  16.     filter: custom(url('wobble.vs')   
  17.                    url('color-swipe.fs'),   
  18.                    40 40,   
  19.                    amplitude 60,   
  20.                    amount 1.0);  
  21. }  
  22. </style> 
  23. </head> 
  24.  
  25. <body> 
  26.     <div id="shaded"> 
  27.         <div id="multi-col"> 
  28.             <h2>The Creative Web</h2> 
  29.             <!-- Same as previous example --> 
  30.         </div> 
  31.     </div> 
  32. </body> 
  33. </html> 

着色器规范我们将在日后详细讨论。目前重要的是让你们了解各个着色器都带给你什么样的效果,以及向外暴露什么参数供CSS来控制。

在这个例子中,自定义滤镜使用了wobble.vs顶点着色器实现变形、 color-swipe.fs 碎片着色器实现灰度到常色扫过的切换效果。

着色器是什么?

着色器在3D图形中是常见的,它们(一般是)处理3D几何面(vertex 着色器)和颜色像素(碎片着色器)的小程序。

比如vertex着色器能够实现表面如旗子飘动的效果,或者翻滚效果,就如前面例子一样。碎片着色器(通常叫做像素着色器)能够实现任意方式的计算来控制像素的颜色。CSS着色器能够驾驱于硬件加速着色器软件的强大功能。

CSS着色器如何工作的?

有了CSS着色器,你可以把你的HTML和SVG元素变成一个顶点网格(在第二步),这可以实现各种变形,即使可能在3D场合中。第三步,网格能够被渲染(或者合并)为像素交给碎片着色器上色。

图三. CSS着色器处理模型

图三. CSS着色器处理模型.

作为一个开发者,你可以控制网格的颗粒度,你可以定义参数控制着色器。在这个例子中,有着色器ID的元素被设置了滤镜参数:

  1. custom(url('wobble.vs')        /* wobble effect */  
  2.            url('color-swipe.fs'), /* swipe effect  */  
  3.            40 40,                 /* mesh lines/cols */  
  4.            amplitude 60,          /* wobble strength */  
  5.            amount 0.0);           /* effect amount */ 

wobble.vs 和 color-swipe.fs 着色器内部设定,当参数为0时,内容整体灰度上将不会有任何翻滚和像素着色器。wobble.vs和color-swipe.fs着色器内部设定,当参数为0时,内容整体灰度上将不会有任何翻滚和像素着色器。

当用户鼠标经过目标内容,它的滤镜属性就被设置为:

  1. custom(url('wobble.vs')   
  2.        url('color-swipe.fs'),   
  3.        40 40,   
  4.        amplitude 60,  
  5.        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)的坐标点转换回实际视角的坐标系统坐标点的矩阵

  1. precision mediump float; /* required */  
  2.  
  3. // ================= Per-vertex attributes =================== //  
  4. attribute vec3 a_position; /* The vertex's coordinates */  
  5. attribute vec2 a_texCoord; /* The vertext's texture coordinate */  
  6.  
  7. // Uniform parameters are available to shaders and have the   
  8. // same value for all vertex or pixel.  
  9. uniform mat4 u_projectionMatrix; /* The projection matrix */  
  10.  
  11. // ================ Shader parameters ======================== //  
  12. uniform float amplitude;  
  13. uniform float amount;  
  14. // ============== End shader parameters ====================== //  
  15.  
  16.  
  17. const float rotate = 20.0; /* could be made a uniform   */  
  18.                             /* to allow control form CSS */  
  19. const float PI = 3.14...;  
  20.  
  21. varying vec2 v_texCoord;  
  22.  
  23.  
  24. mat4 rotateX(float f) {...}  
  25. mat4 rotateY(float f) {...}  
  26. mat4 rotateZ(float f) {...}  
  27.  
  28. void main()  
  29. {          
  30.     v_texCoord = a_texCoord.xy;  
  31.     vec4 pos = vec4(a_position, 1.0);  
  32.       
  33.     float r = 1.0 - abs((amount - 0.5) / 0.5);  
  34.     float a = r * rotate * PI / 180.0;  
  35.     mat4 rotX = rotateX(a);  
  36.     mat4 rotY = rotateY(a / 4.0);  
  37.     mat4 rotZ = rotateZ(a / 8.0);  
  38.       
  39.     float dx = 0.01 * cos(3.0 * PI * (pos.x + amount)) * r;  
  40.     float dy = 0.01 * cos(3.0 * PI * (pos.y + amount)) * r;  
  41.     float dz = 0.1 * cos(3.0 * PI * (pos.x + pos.y + amount)) * r;  
  42.  
  43.     pos.x += dx;  
  44.     pos.y += dy;  
  45.     pos.z += dz;  
  46.       
  47.     gl_Position = u_projectionMatrix * rotZ * rotY * rotX * pos;  

这是那个例子中用的颜色横扫着色器代码:

  1. precision mediump float; /* required */  
  2.  
  3. // The 'original' content rendering in a texture.  
  4. uniform sampler2D s_texture;  
  5.  
  6. // ================ Shader parameters ======================== //  
  7. uniform float amplitude; /* unused in this fragment shader */  
  8. uniform float amount;  
  9. // ============== End shader parameters ====================== //  
  10.  
  11. varying vec2 v_texCoord;  
  12.  
  13. // The desired 'color swipe' color.  
  14. const vec4 swipeColor = vec4(1.0, 1.0, 1.0, 1.0);   
  15.  
  16. vec4 grayscale(vec4 color) {  
  17.     ...;   
  18.     return gray;  
  19. }  
  20.  
  21. void main() {  
  22.     vec4 color = texture2D(s_texture, v_texCoord);  
  23.     vec4 gray = grayscale(color);  
  24.     vec2 pos = v_texCoord;  
  25.  
  26.     float p = 1.0 - pos.y; /* progress from bottom to top */  
  27.       
  28.     vec4 sc = swipeColor * color.a;  
  29.     float threshold = amount * 1.2;  
  30.     if (p < threshold) {  
  31.         float a = min(abs(threshold - p) / 0.2, 1.0);      
  32.         gl_FragColor = mix(sc, color, a);  
  33.     } else {  
  34.         float a = min(abs(threshold - p) / 0.005, 1.0);  
  35.         gl_FragColor = mix(sc, gray, a);  
  36.     }  

网上有很多不错的资源会对你的着色器开发有帮助,一切类库也包含了很棒的着色器套件(参看文章底部的链接)

着色语言,如OpenGL ES,都是让视觉效果开发变得简单,CSS着色器将这些很棒的表现元素与CSS句法紧紧相连,让它产生这些效果变得异常容易。

和WebGL作对比

WebGL 提供了HTML5画布元素的实现方案,它为画布提供了3D上下文,在这个上下文里面,你可以访问到像素着色器(和其他顶点着色器以及WebGL提供的其他3D特性),WebGL的作用范围仅仅在canvas 范围内。

与此形成鲜明对比的是,CSS着色器可以应用任何着色器到任何网页内容。

下一步该怎么办?

Adobe作为FX主力军的一员正把CSS着色器贡献给W3C, 我们的目标是一旦得到W3C的肯定,我们将着手把代码贡献给WebKit,这样不久网站开发者们就能够受益于这套全新强大的滤镜效果集了。

与此同时, 你可能想参考下面的资源获取更多关于CSS动画和特效的相关信息:

责任编辑:Yeva 来源: adobe.com
相关推荐

2017-01-11 19:15:55

Android着色器Tint

2021-12-23 09:34:05

着色器编程语言软件开发

2021-03-18 08:03:58

SteamMesa缓存

2013-09-22 13:39:35

网页设计网页布局

2010-09-14 10:55:14

DIV CSS网页制作

2019-12-03 09:27:03

机器人人工智能系统

2020-10-30 11:06:58

AMDRX 6000RX 5700 XT

2023-10-16 15:58:54

开源Blender

2023-04-12 07:46:24

JavaScriptWebGL

2017-05-08 11:41:37

WebGLThree.js

2013-04-15 14:23:21

2011-03-11 10:27:45

UbuntuLAMP配置

2023-11-15 14:15:03

开源Blender

2022-09-26 12:28:16

OpenGLAPI使用移动应用

2024-12-05 10:57:24

2018-03-12 10:36:09

无线路由千兆网络5GHz

2015-06-10 09:06:05

HTML 5卓越工具动画效果

2023-05-06 07:23:57

点赞
收藏

51CTO技术栈公众号