说说SVG的feTurbulence滤镜

不少时候,咱们在布置游戏地图或者动漫场景的时候,须要模拟火焰,树丛,云朵等等这些大天然鬼斧神工创造出来的形状或者纹理,这个时候,你会发现这些形状总体看起来颇有规律,但形状的延续却彻底随机,乱中有序。html

上个世纪80年代,Ken Perlin 就思考过怎样模拟这些天然纹理这个问题,而且,给出了他的答案。在彻底随机的白噪声函数上,用缓动曲线进行平滑插值,让函数的图像更加趋近于天然噪声的图像,也就是符合天然界形状和纹理规律的图像,由此发明了Perlin噪声算法。Perlin噪声算法提出后在不少场景都发挥了很大的做用,为迪士尼创造电影场景提供了许多帮助,曾经得到奥斯卡科技成果奖,是一个演技获得过承认的算法。算法

现在Perlin算法成了计算机图形学基础中的一员,任何跟图形学相关的工具库,都有他的实现,咱们能够利用这些工具,从应用的角度学习Perlin噪声算法。svg

在SVG中,feTurbulence滤镜就能够利用Perlin函数建立丰富的图像。使用feTurbulence滤镜的时候,咱们能够经过调整参数直观地看到效果,本文是对feTurbulence滤镜的学习记录,经过一些实验了解不一样参数对feTurbulence滤镜创造出来的图像的影响。函数

feTurbulence的参数

首先,经过mdn 咱们能够初步了解一下feTurbulence滤镜的基本状况,他接收五个参数:工具

  • baseFrequency(默认值:0)
  • numOctaves(默认值:1)
  • seed (默认值:0)
  • stitchTiles(默认值:noStitch)
  • type (默认值:turbulence)

虽然不知道这五个参数有什么做用,可是既然feTurbulence全部参数都有默认值,那咱们不入参地创造一个滤镜,而后一个参数一个参数探究一下,代码以下:学习

<svg width="500" height="500">
  <!-- 定义一个滤镜预设组 -->
  <filter id='noise'>
    <!-- 向组中添加主角 -->
    <feTurbulence/>
  </filter>
  <!-- 建立一个矩形,把滤镜效果应用到矩形上 -->
  <rect width="100%" height="100%" filter="url(#noise)" fill="none">
</svg>

baseFrequency

把上面的代码放入页面运行,咱们什么东西都看不到,由于baseFrequency在不入参的状况默认值为0。而baseFrequency影响的是噪声的频率,当噪声的频率为0时,就天然没有图像啦。加密

频率越大,相同显示区域下能够显示的噪声就越密集,当baseFrequency的值为一个很小的值时(如0.01),生成的图像比较大,细节更丰富,而增大10倍以后,原来的图像被缩小10倍放到左上角,剩余的空间用来放置更多的噪声url

image-20210318153234530

如下是baseFrequency的值慢慢变大的过程spa

baseFrequency

baseFrequency属性能够接受两个值,当这样入参的时候,这两个值分别会当成x轴和y轴上的基础频率,由此,咱们能够生成在某一个方向拉伸的噪声。.net

image-20210318190421390

numOctaves

octaves是八度的意思,玩过音乐的同窗都知道,两个相邻音组中的同名音之间的音高差距就是一个八度,这两个音振动图像类似,高八度的音的振动频率恰好是低八度的两倍。相差八度的两个音同时弹响的时候,能够产生细节更加丰富的音。

在数学函数里,一个函数跟他另外一个不一样频率的函数叠加,也能够达到同样的效果,产生一个轮廓不变,细节更加丰富的函数图像。

咱们以sin函数为例,如下是f(x) = sin(x)和f(x) = sin(10x)的函数图像:

image-20210318171028567

两个图像的振幅同样,后者的频率是前者的10倍,高了10个八度,如今让两个函数同时弹响,造成:

f(x) = sin(x) + sin(10)

他的图像会是怎么样的呢?

image-20210318163824105

对比前面三个图像,第三个图像感受就像是拿第二个图像当画笔画出来的第一个图像。这,就是八度和弦的魅力,我仍是原来的我,然而我花里胡哨起来了。若是再花里胡哨一点,在第三个函数上叠多一个高10个八度的函数,会不会更快乐呢。

f(x) = sin(x) + sin(10x) + sin(20x)

说回numOctaves属性,当咱们设置了这个属性以后,算法会在原来的噪声函数上叠加若干个频率不一样的他本身,造成细节更加丰富的噪声,看一下numOctaves增长时的动态效果。(这里说一下,numOctaves只接受不等于0的正整数,这是由于八度叠加的最小单位是一个八度,若是一个函数跟本身非整数倍频率的函数叠加,最终函数的大体形状会受到影响。)

numOctaves

跟sin函数叠加本身的八度函数的效果同样,随着numOctaues不断增长,图像的大体形状仍是跟numOctaues等于1的时候同样,可是细节在不断增长。有一个值得注意的点是,当numOctaues大于6以后,图像的区别开始变得不明显,这并非到达某个阈值以后,八度叠加就不生效了,而是叠加以后产生的变化更加细小,须要拿个显微镜看一看啦。

type

feTurbulence的type属性把位于同一个子集的两个功能合并在一个滤镜里,type的取值是turbulence和fractalNoise。turbulence是指将柏林函数进行合成时,只取函数的绝对值,合成后的函数在0处不可导,其图像会有一些尖锐效果,形似湍流。fractalNoise则是在原来的噪声中叠加白噪声,让最终的结果呈现出高斯模糊的效果。两种type对应的原理你们能够自行百度谷歌。简单来讲两个的区别是有没有模糊。

如下是两种type的效果

image-20210318201755016

stitchTiles

stitchTiles须要使用多个图形时才能发挥效果,当咱们随便设置两个使用feTurbulence滤镜的图形放在一块儿的时候,这两个图形的边界会出来断层的现象。两个图形就是独立的个体,本身顾本身长什么样。

image-20210318202510729

可是有时候,咱们须要让两个图形看起来像从一个连续的集合分开。这个时候就能够将滤镜的stitchTiles属性设置成stitch,那这个时候,图形的边界就会连续起来。

image-20210318202957298

seed

seed是种子的意思,这是每个随机数算法都须要用到的一个输入,全部的伪随机数算法中,当输入的种子同样的时候,输出老是一致的。

seed

feTurbulence的使用

从上文一路到这里,沿路上已经出现了不少feTurbulence滤镜创造的图像,有静止的、动态、密集的、拉伸的。可能这些图像让人以为很陌生,但这些确实都是平常生活中会出现的图像。老电视在播放画面的时候,会受到电磁波的影响,偶尔出现一扫而过的扭曲画面;牛皮纸粗糙的表面在光线下,会表现出特有的纹理......当咱们想去表达一个受天然噪声影响的事物的时候,均可以使用feTurbulence滤镜,再结合光线,图片,色块等元素进行描述。

水流纹路

当河水平缓流动的时候,水面会出现不少细小的波纹,这种纹路符合的水平拉伸的图像特色,咱们能够建立一个图像,再添加一点动效

<filter id='turbulence-noise' x='0%' y='0%' width='100%' height='100%'>
  <feTurbulence id="feturbulence" baseFrequency="0.015 0.3">
    <animate id="ani1" attributeName="baseFrequency" dur="15s" from="0.015 0.3" to="0.035 0.5" begin="0s; ani2.end"
      fill="feeze">
    </animate>

    <animate id="ani2" attributeName="baseFrequency" dur="15s" from="0.035 0.5" to="0.015 0.3" begin="ani1.end"
      fill="freeze">
    </animate>
  </feTurbulence>
</filter>

运行代码咱们能够看到这样的效果:

see

在这个效果的基础上,使用feDisplacementMap滤镜把一张静态的河流图片映射到图像上,就能够看到如下的效果。此处参考了网上大佬的做品,有兴趣能够看看源代码。

river

纸张的纹路

相比于水流的纹路,纸张的纹路更加密集,图像细节更加丰富,并且纹路的线条界线不明显。根据这个特色,咱们能够把feTurbulence的参数设置成

<feTurbulence type="fractalNoise" baseFrequency='0.04' result='noise' numOctaves="5" />

获得这样的图像image-20210319172234987

而后,使用白光从图像上方45度角进行照射,获得如下图形

image-20210319172613135

总结

feTurbulence实现了Perlin噪声算法,所以咱们能够拿他来模拟绝大部分天然造成的图像,这是一个具备很高可玩性的滤镜,只要咱们了解光影变化的原理,从数学的角度认识世界,就能够找到不少能够跟feTurbulence滤镜结合的元素,创造更多意想不到的玩法。

参考

【计算机图形】Perlin Noise 实例和理解

【图形学】谈谈噪声

流水的动效

SVG Filter Effects: Creating Texture with <feTurbulence>

相关文章
相关标签/搜索