說說SVG的feTurbulence濾鏡

不少時候,咱們在佈置遊戲地圖或者動漫場景的時候,須要模擬火焰,樹叢,雲朵等等這些大天然鬼斧神工創造出來的形狀或者紋理,這個時候,你會發現這些形狀總體看起來頗有規律,但形狀的延續卻徹底隨機,亂中有序。html

上個世紀80年代,Ken Perlin 就思考過怎樣模擬這些天然紋理這個問題,而且,給出了他的答案。在徹底隨機的白噪聲函數上,用緩動曲線進行平滑插值,讓函數的圖像更加趨近於天然噪聲的圖像,也就是符合天然界形狀和紋理規律的圖像,由此發明了Perlin噪聲算法。Perlin噪聲算法提出後在不少場景都發揮了很大的做用,爲迪士尼創造電影場景提供了許多幫助,曾經得到奧斯卡科技成果獎,是一個演技獲得過承認的算法。算法

現在Perlin算法成了計算機圖形學基礎中的一員,任何跟圖形學相關的工具庫,都有他的實現,咱們能夠利用這些工具,從應用的角度學習Perlin噪聲算法。markdown

在SVG中,feTurbulence濾鏡就能夠利用Perlin函數建立豐富的圖像。使用feTurbulence濾鏡的時候,咱們能夠經過調整參數直觀地看到效果,本文是對feTurbulence濾鏡的學習記錄,經過一些實驗瞭解不一樣參數對feTurbulence濾鏡創造出來的圖像的影響。svg

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時,就天然沒有圖像啦。oop

頻率越大,相同顯示區域下能夠顯示的噪聲就越密集,當baseFrequency的值爲一個很小的值時(如0.01),生成的圖像比較大,細節更豐富,而增大10倍以後,原來的圖像被縮小10倍放到左上角,剩餘的空間用來放置更多的噪聲學習

image-20210318153234530

如下是baseFrequency的值慢慢變大的過程加密

baseFrequency

baseFrequency屬性能夠接受兩個值,當這樣入參的時候,這兩個值分別會當成x軸和y軸上的基礎頻率,由此,咱們能夠生成在某一個方向拉伸的噪聲。url

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

相關文章
相關標籤/搜索