svg滤镜详解(三)

523 阅读4分钟

v  这一节我们来学习一下svg光照滤镜,这个css中没有的。下面我们详细解释一下svg的光照,如果使用个过three.js做3D效果的同学,都知道three中也有光照效果,我感觉道理是相通的。

光照原理

  我们可以先考虑一下现实中的光照,首先我们需要光源,只有光源才能有光照效果,光源可以分为三类:点光源个平行光源和聚光灯,可以想象一下手电筒和太阳光,照出来的效果是不同的。下面做一个简单的示例:

1664853550564.png
光源分类svg和three稍有不同,感兴趣的同学可以研究一下。通过上图我们可以看出,对于电光源和聚光灯我们需要位置信息。然后就是光源颜色,光强等这个就很好理解了。接下来就是被照射对象的材质,不同材质的物体对光源的反射光是不同的,并且材质不同,反射类型也不同,可以分为镜面反射和漫反射。我们这一节只讲svg的光照滤镜,合成效果我们在下一节讲解。有了上面的分析,我们不管是学习svg还是three.js中的光照都大有裨益。
  这里面有一点需要注意,svg滤镜的光照和three是不同的,svg光照效果不考虑材质的影响,什么意思呢?就是说如果是红色的光照到了绿色的物体上,这时候应该是没有反射光的,但是svg的实际效果是会反射出红色的光,这就和three.js有很大不同。svg想要做真实的光照效果需要和其他滤镜一起实现。记住一点svg中光照滤镜的,物体的颜色只和光照颜色有关,和物体本身的颜色没有关系。

svg光照语法

svg的光照语法是定义反射类型漫反射和镜面反射,在反射类型元素里面添加光源。

漫反射

语法feDiffuseLighting属性值:
light-color:定义光源颜色
surfaceScale:这是一个突起的效果,有光照就有阴影,该值越大滤镜的突起效果越明显
diffuseConstant:漫反射强度,叫做这个名字也不合适,我还没想到合适的词汇,该值越大就越发白,为0是黑色。如果只是漫反射强度不应该成为大数字为白色。从字面意思看叫做漫反射常数,

镜面反射

语法feSpecularLighting属性值:
light-color:定义光源颜色
surfaceScale:这是一个突起的效果,有光照就有阴影,该值越大滤镜的突起效果越明显
specularConstant:光滑程度,数值越大越光滑,反射光的能力越强,0则没有反射效果
specularExponent:光照强度,数值越大颜色越发白,0为正常强度。

平行光光源

语法feDistantLight属性值:
azimuth:入射光线相对于x轴的入射角度,默认0度为x轴正方向
elevation:光源相对于z轴的夹角,svg的z轴垂直于屏幕向外
虽然svg是二维图形但是对于光线的入射角度需要从3维考虑,所以我们需要两个角度.下面是示意图: ba715dc081495014c8acbb2da3d4ebc.png
这样使用两个角度我们就可以确定入射光线相对于xy平面的角度。

点光源

语法fePointLight属性值:
这个属性值比较好解释,因为对于点光源我们只要知道x,y,z坐标就行了。所以点光源的属性值为x,y,z,默认值均为0

聚光灯

我们仔细考虑一下对于这样的光源怎么定义位置和方向呢?我们可以像电光源一样定义x,y,z为光源点,那方向呢?这个滤镜使用(pointsAtX,pointsAtY,pointsAtZ),定义另一个点,有了这两个点我们就可以确定聚光灯光源相对于xy平面的位置和方向了。还需要知道一个量,聚光灯圆锥形的夹角如图:

1664887834522.png
有了这个角度我们就可以确定聚光灯光源了。所以语法feSpotLight属性值:
x,y,z:聚光灯光源的坐标点
pointsAtX,pointsAtY,pointsAtZ:聚光灯朝向的坐标点
limitingConeAngle:聚光灯锥顶的夹角

上面介绍完了svg光照的语法,下面我们写几个例子,加强对光照的理解。

svg光照例子

漫反射平行光源

<svg width="1000" height="500">
    <defs>
        <filter id="diffuseDistant" x="0" y="0" width="100%" height="100%">
            <feDiffuseLighting
                in="SourceGraphic"
                lighting-color="#5f0b2c"
                surfaceScale="5"
                diffuseConstant="5">
                <feDistantLight azimuth="0" elevation="25"/>
            </feDiffuseLighting>
        </filter>
        <polygon filter="url(#diffuseDistant)" transform="scale(2)" points="50 160 55 180 70 180 60 190 65 205 50 195 35 205 40 190 30 180 45 180"
        stroke="#00ff00" fill="#0000ff" stroke-width="5"/>
 </svg>

效果如下:

1665106147272.png
我们还可以加上动画,来感受一下光照效果:

            <feDiffuseLighting
                in="SourceGraphic"
                lighting-color="#5f0b2c"
                surfaceScale="5"
                diffuseConstant="5">
                <feDistantLight azimuth="0" elevation="25">
                  <animate  attributeName="azimuth" from="0" to="360"  begin="0s" dur="5s" repeatCount="100"></animate>
                </feDistantLight>
            </feDiffuseLighting>

有兴趣的同学可以自己尝试一下效果。并且修改里面的数字,看看不同的效果。

漫反射点光源

<feDiffuseLighting
    in="SourceGraphic"
    lighting-color="#5f0b2c"
    surfaceScale="5"
    diffuseConstant="20">
    <fePointLight x="180" y="100" z="50">
      <animate  attributeName="x" from="0" to="360"  begin="0s" dur="5s" repeatCount="indefinite"></animate>
    </fePointLight>
</feDiffuseLighting>

效果如下:

point.gif

漫反射聚光灯

<feDiffuseLighting
in="SourceGraphic"
lighting-color="#5f0b2c"
surfaceScale="5"
diffuseConstant="20">
  <feSpotLight x="50" y="183" z="200"  pointsAtX = "20" pointsAtY="183" pointsAtZ="50" limitingConeAngle="7">
    <animate  attributeName="pointsAtX" from="20" to="80"  begin="0s" dur="5s" repeatCount="indefinite"></animate>
  </feSpotLight>
  </feDiffuseLighting>

效果如下:
spotLight.gif

镜面反射平行光源

<filter id="specularDistant" x="0" y="0" color-interpolation-filters="sRGB" width="100%" height="100%">
    <feSpecularLighting
        lighting-color="#5f0b2c" 
        surfaceScale="5"
        specularConstant="2"
        specularExponent="2"
        >
        <feDistantLight azimuth="45" elevation="45"/>
    </feSpecularLighting>
</filter>

效果如下

1665110366853.png
可以看到镜面反射五角星的线条是白色的,并且镜面反射的颜色和要比漫反射的颜色浅

镜面反射点光源

<feSpecularLighting
    lighting-color="#5f0b2c" 
    surfaceScale="5"
    specularConstant="2"
    specularExponent="2"
    >
    <fePointLight x="180" y="100" z="50">
      <animate  attributeName="x" from="0" to="360"  begin="0s" dur="3s" repeatCount="indefinite"></animate>
    </fePointLight>
</feSpecularLighting>

结果如下:

specularPointLight.gif

镜面反射聚光灯

<feSpecularLighting
    lighting-color="#5f0b2c" 
    surfaceScale="5"
    specularConstant="2"
    specularExponent="2"
    >
    <feSpotLight x="50" y="183" z="200"  pointsAtX = "20" pointsAtY="183" pointsAtZ="50" limitingConeAngle="7">
      <animate  attributeName="pointsAtX" from="20" to="80"  begin="0s" dur="5s" repeatCount="indefinite"></animate>
    </feSpotLight>
</feSpecularLighting>

specularSpotight.gif

为科技球添加光照效果

我们可以为科技球加一个漫反射聚光灯的白色光照效果。效果如下:

1665194205800.png 代码地址:科技球光照效果