【AS3 Coder】任務四:噪音的魅力(下)

        在以前的兩篇文章中咱們介紹了PerlinNoise的兩種用途:建立雲霧等天然效果以及用做隨機數提供源。那麼在這一章中,貧道將隆重介紹一位perlinNoise的好基友:DisplacementMapFilterhtml

 

神馬是DisplacementMapFilterweb

        DisplacementMapFilter是一種濾鏡,使用它可讓一張BitmapData的像素髮生偏移,產生出一種相似於扭曲的效果。山羊書(《Foundation  Actionscript3.0 Image Effect》)中,在第四章Advanced Bitmap Manipulation中的Displace pixels這一節中對此濾鏡有着詳細的介紹,下面先引用其一張截圖:算法

        從上圖中咱們能夠看到,以左邊這張圖做爲濾鏡的像素提供源產生一個DisplacementMapFilter後應用於右側的一張格子圖上面,會出現一個圓形的像素偏移區域。那麼DisplacementMapFilter這個濾鏡的工做原理是怎麼樣的呢?咱們應該如何使用它?ide

        在山羊書中對DisplacementMapFilter濾鏡工做原理作了很是詳細的剖析,可是你如今在看個人文章,不可能還拿出山羊書來翻一翻先,好吧,下面我簡單地翻譯並歸納一下山羊書中對其的解釋。首先咱們來看DisplacementMapFilter濾鏡的參數設置:ui

public function DisplacementMapFilter(mapBitmap:BitmapData = null, mapPoint:Point = null, componentX:uint = 0, componentY:uint = 0, scaleX:Number = 0.0, scaleY:Number = 0.0, mode:String = "wrap", color:uint = 0, alpha:Number = 0.0)spa

mapBitmap:BitmapData (default = null) — 包含置換映射數據的 BitmapData 對象。翻譯

mapPoint:Point (default = null) — 一個值,它包含目標顯示對象的左上角相對於映射圖像左上角的偏移量。code

componentX、Y:uint (default = 0) — 說明在映射圖像中使用哪一個顏色通道來置換 x ,y 結果。 可能的值爲 BitmapDataChannel 常數。component

scaleX、Y:Number (default = 0.0) — 用於縮放映射計算的 x , y 置換結果的乘數。orm

mode:String (default = "wrap") — 濾鏡模式。 可能的值爲 DisplacementMapFilterMode 常數。

color:uint (default = 0) — 指定對於超出範圍的替換應用什麼顏色。 置換的有效範圍是 0.0 到 1.0。若是 mode 設置爲 DisplacementMapFilterMode.COLOR,則使用此參數。

alpha:Number (default = 0.0) — 指定對於超出範圍的替換應用什麼 Alpha 值。 它被指定爲 0.0 到 1.0 之間的標準值。例如,.25 設置透明度值爲 25%。 若是 mode 設置爲 DisplacementMapFilterMode.COLOR,則使用此參數。

        當你傳入一個BitmapData對象做爲DisplacementMapFilter的第一個參數mapBitmap的話,該BitmapData對象實際上就成了一個像素提供源,DisplacementMapFilter內部會根據一個公式來計算出濾鏡應用結果的像素值,該公式能夠表示爲:

dstPixel[x, y] = srcPixel[x + ((componentX(x, y) - 128) * scaleX) / 256, y + ((componentY(x, y) - 128) *scaleY) / 256)

設dstPixel[x, y]爲濾鏡應用結果於(x,y)位置處的像素值,該像素值應與像素提供源srcPixle於(x + ((componentX(x, y) - 128) * scaleX) / 256, y + ((componentY(x, y) - 128) *scaleY) / 256)位置的像素值一致。componentX、Y指某一個顏色通道。

        下面咱們一塊兒來算一次。假設我傳入DisplacementMapFilter中的componentX參數爲BitmapDataChannel.RED,scaleX值爲10, 而像素源mapBitmap於(0,0)位置的紅色值剛好爲0x80(轉換爲十進制是128),那麼x + ((componentX(x, y) - 128) * scaleX) / 256 = 0 + ((componentX(x, y)  - 128) * 10) / 256 = 0 + ( (128 - 128) * 10  ) / 256 = 0

再假設我一樣使用了紅色通道做爲componenY , scaleY 值爲10, 那麼後面那個算式y + ((componentY(x, y) - 128) *scaleY) / 256得出的計算結果也同樣是0.

這意味着什麼呢?這意味着此時濾鏡應用結果在(0,0)位置上的顏色是取自像素提供源(0,0)位置上的顏色的。若像素源mapBitmap於(0,0)位置的紅色值爲0xFF(轉換爲十進制爲255)的話,計算結果將變成(5,5),這意味着此時濾鏡應用結果在(0,0)位置上的顏色是取自像素提供源(5,5)位置上的顏色。那如果像素源mapBitmap於(0,0)位置的紅色值爲0x00(轉換爲十進制爲0)的話,計算結果將變成(-5,-5),這時候怎麼辦呢?DisplacementMapFilter會根據其mode參數來決定如何取(-5,-5)這個超出邊界的像素。下面是四種可選的mode介紹:

 

  • DisplacementMapFilterMode.WRAP -- 將置換值折返到源圖像的另外一側。
  • DisplacementMapFilterMode.CLAMP -- 將置換值鎖定在源圖像的邊緣。
  • DisplacementMapFilterMode.IGNORE -- 若是置換值超出了範圍,則忽略置換並使用源像素。
    • DisplacementMapFilterMode.COLOR -- 若是置換值在圖像以外,則替換 color  alpha 屬性中的值。

扭起來吧少年

        介紹完了好基友DisplacementMapFilter童鞋,接下來就應該看看它能怎樣配合perlinNoise來產生「扭扭更健康」的目標。先看一個水波紋的例子,該例子出自

http://www.thetechlabs.com/tech-tutorials/flash/create-real-water-effects-with-flash-cs4-actionscript-30/

        固然,這個例子也是純英文的,英文很差的童鞋只須要看看它的成果演示就夠了。我這裏只對它頭一個例子作一些解釋,如果打不開上面給的地址,能夠看這裏(點擊圖片瀏覽):

        至於實現原理,說簡單也簡單:生成不規則的波紋靠的是perlinNoise,讓波紋產生扭曲則靠的是以前介紹的DisplacementMapFilter,最後讓波紋不停地滾動,就得靠不停地滾動使用perlinNoise生成的雜點圖像並不停地爲目標圖片更新濾鏡了。在上面給出的文章地址中,老外做者使用了每幀改變perlinNoise的offsets參數來實現滾動:

var bm:BitmapData=new BitmapData(backImg1.width, backImg1.height);
var disp:DisplacementMapFilter = new DisplacementMapFilter(bm,new Point(0,0),1,2,10,60);
var pt1:Point = new Point(0,0);
var pt2:Point = new Point(0,0);
var perlinOffset:Array = [pt1, pt2];

addEventListener(Event.ENTER_FRAME, onFrame);
function onFrame(evt:Event):void {
  perlinOffset[0].x +=1;
  perlinOffset[1].y +=0.1;
  bm.perlinNoise(45,9,2,50,true,false, 7,true,perlinOffset);
  backImg1.filters=[disp];
}

 這樣寫當然簡單,可是在以前的噪聲的魅力(上)這篇文章中咱們提到過,使用這種改變offests參數的方式來滾動柏林雜點圖效率低下,由於它每幀都要調用perlinNoise方法來生成新圖。那麼更加高效的方式以前也在雲飄動的例子中提到過,就是使用一種相似傳送帶的方法(也能夠叫作卡馬克卷軸算法)來作到。這裏就很少解釋了,我直接把水波紋的特效作成了一個單獨組件SWaterWaveEffect,並收錄在了個人SComponent系列中,列位能夠去置頂的帖子裏下載源碼進行查看。

相關文章
相關標籤/搜索