乐趣区

关于前端:说说SVG的feTurbulence滤镜

很多时候,咱们在安排游戏地图或者动漫场景的时候,须要模仿火焰,树丛,云朵等等这些大自然巧夺天工发明进去的形态或者纹理,这个时候,你会发现这些形态整体看起来很有法则,但形态的连续却齐全随机,乱中有序。

上个世纪 80 年代,Ken Perlin 就思考过怎么模仿这些天然纹理这个问题,并且,给出了他的答案。在齐全随机的白噪声函数上,用缓动曲线进行平滑插值,让函数的图像更加趋近于天然噪声的图像,也就是合乎自然界形态和纹理法则的图像,由此创造了 Perlin 噪声算法。Perlin 噪声算法提出后在很多场景都施展了很大的作用,为迪士尼发明电影场景提供了许多帮忙,已经取得奥斯卡科技成果奖,是一个演技失去过认可的算法。

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

在 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 倍放到左上角,残余的空间用来搁置更多的噪声

以下是 baseFrequency 的值缓缓变大的过程

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

numOctaves

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

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

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

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

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

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

比照后面三个图像,第三个图像感觉就像是拿第二个图像当画笔画进去的第一个图像。这,就是八度和弦的魅力,我还是原来的我,然而我花里胡哨起来了。如果再花里胡哨一点,在第三个函数上叠多一个高 10 个八度的函数,会不会更高兴呢。

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

说回 numOctaves 属性,当咱们设置了这个属性之后,算法会在原来的噪声函数上叠加若干个频率不同的他本人,造成细节更加丰盛的噪声,看一下 numOctaves 减少时的动态效果。(这里说一下,numOctaves 只承受不等于 0 的正整数,这是因为八度叠加的最小单位是一个八度,如果一个函数跟本人非整数倍频率的函数叠加,最终函数的大抵形态会受到影响。)

跟 sin 函数叠加本人的八度函数的成果一样,随着 numOctaues 一直减少,图像的大抵形态还是跟 numOctaues 等于 1 的时候一样,然而细节在一直减少。有一个值得注意的点是,当 numOctaues 大于 6 之后,图像的区别开始变得不显著,这并不是达到某个阈值之后,八度叠加就不失效了,而是叠加之后产生的变动更加细小,须要拿个显微镜看一看啦。

type

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

以下是两种 type 的成果

stitchTiles

stitchTiles 须要应用多个图形时能力施展成果,当咱们轻易设置两个应用 feTurbulence 滤镜的图形放在一起的时候,这两个图形的边界会进去断层的景象。两个图形就是独立的个体,本人顾本人长什么样。

然而有时候,咱们须要让两个图形看起来像从一个间断的汇合离开。这个时候就能够将滤镜的 stitchTiles 属性设置成 stitch,那这个时候,图形的边界就会间断起来。

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>

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

在这个成果的根底上,应用 feDisplacementMap 滤镜把一张动态的河流图片映射到图像上,就能够看到以下的成果。此处参考了网上大佬的作品,有趣味能够看看源代码。

纸张的纹路

相比于水流的纹路,纸张的纹路更加密集,图像细节更加丰盛,而且纹路的线条界限不显著。依据这个特点,咱们能够把 feTurbulence 的参数设置成

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

失去这样的图像

而后,应用白光从图像上方 45 度角进行照耀,失去以下图形

总结

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

参考

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

【图形学】谈谈噪声

流水的动效

SVG Filter Effects: Creating Texture with <feTurbulence>

退出移动版