在之前的两篇文章中我们介绍了PerlinNoise的两种用途:创建云雾等自然效果以及用作随机数提供源。那么在这一章中,贫道将隆重介绍一位perlinNoise的好基友:DisplacementMapFilter

神马是DisplacementMapFilter

DisplacementMapFilter是一种滤镜,使用它可以让一张BitmapData的像素发生偏移,产生出一种类似于扭曲的效果。山羊书(《Foundation  Actionscript3.0 Image Effect》)中,在第四章Advanced Bitmap Manipulation中的Displace pixels这一节中对此滤镜有着详细的介绍,下面先引用其一张截图:

从上图中我们可以看到,以左边这张图作为滤镜的像素提供源产生一个DisplacementMapFilter后应用于右侧的一张格子图上面,会出现一个圆形的像素偏移区域。那么DisplacementMapFilter这个滤镜的工作原理是怎么样的呢?我们应该如何使用它?

在山羊书中对DisplacementMapFilter滤镜工作原理做了非常详细的剖析,但是你现在在看我的文章,不可能还拿出山羊书来翻一翻先,好吧,下面我简单地翻译并概括一下山羊书中对其的解释。首先我们来看DisplacementMapFilter滤镜的参数设置:

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)

mapBitmap:BitmapData (default = null) — 包含置换映射数据的 BitmapData 对象。

mapPoint:Point (default = null) — 一个值,它包含目标显示对象的左上角相对于映射图像左上角的偏移量。

componentX、Y:uint (default = 0) — 说明在映射图像中使用哪个颜色通道来置换 x ,y 结果。 可能的值为 BitmapDataChannel 常数。

scaleX、Y:Number (default = 0.0) — 用于缩放映射计算的 x , y 置换结果的乘数。

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系列中,列位可以去置顶的帖子里下载源码进行查看。

【AS3 Coder】任务四:噪音的魅力(下)的更多相关文章

  1. 【AS3 Coder】任务七:初涉PureMVC——天气预报功能实现

    转自:http://www.iamsevent.com/post/36.html AS3 Coder]任务七:初涉PureMVC——天气预报功能实现 使用框架:AS3任务描述:了解PureMVC框架使 ...

  2. 【AS3 Coder】任务九:游戏新手引导的制作原理(上)

    使用框架:AS3任务描述:了解游戏中新手的制作原理及流程 难度:3 本章源码下载:http://www.iamsevent.com/zb_users/UPLOAD/GuideManager/Test1 ...

  3. 【AS3 Coder】任务五:Flash 2D游戏的第二春(中)

    在上一节中,我们介绍了如何构建我们小小的90度角RPG游戏的背景,在这一节中我将为列位带来重头戏部分,隆重介绍我们的主角及NPC登场,噔噔噔噔……掌声在哪里?! 额,没听到掌声,罢了,直接开场吧. 本 ...

  4. 【AS3 Coder】任务四:噪音的魅力(上)

    使用框架:AS3任务描述:使用AS3中BitmapData的noise方法以及perlinNoise方法构建自然景观效果以及其他一些比较cool的效果难度系数:2 本文章源码下载:www.iamsev ...

  5. 【AS3 Coder】任务四:噪音的魅力(中)

    如果把Math.random方法作为一个生成随机数字的办法,那么bitmapData.perlinNoise就是一个生成随机颜色的办法.在这一部分的对于噪声的应用介绍文章中我们一起来看看使用柏林噪声的 ...

  6. 【AS3 Coder】任务九:游戏新手引导的制作原理(下)

    在上一篇教程中,我们了解了一套我自创的新手引导管理框架的使用原理,那么在本篇教程中,我们将考虑新手引导制作中可能遇到的一些棘手问题及探讨其解决方案.Are you ready my baby? Let ...

  7. 【AS3 Coder】任务五:Flash 2D游戏的第二春(下)

    在上一节中,我们基本上已经讲完了游戏中最主要的逻辑部分,不过为了更加全面地运用Starling中的一些特性,在本节中我们将一起来看看如何实现多面板切换以及粒子效果,这两个玩意儿可是比较频繁会出现于St ...

  8. 【AS3 Coder】任务八:没剧情还玩毛RPG

    使用框架:AS3任务描述:了解RPG游戏中剧情播放器的制作原理及流程难度系数:3(了解原理,能根据XML文件播放剧情) / 5(会制作剧情编辑器) 本章源码下载:http://www.iamseven ...

  9. 【AS3 Coder】任务六:人物换装(纸娃娃)系统的制作

    使用框架:AS3(Flash Professional CS5.0及更高版本 + Flash Buider)任务描述:了解人物换装系统的制作原理难度系数:2 本章源码下载:http://www.iam ...

随机推荐

  1. Python 本地线程

    1. 本地线程,保证即使是多个线程,自己的值也是互相隔离. 2.普通对象演示 import threading import time class A(): pass a=A() def func(n ...

  2. RabbitMQ消息队列(二): 工作队列

    1. 工作队列: 对于资源密集型任务,我们等待其处理完成在很多情况下是不现实的,比如无法在http的短暂请求窗口中处理大量耗时任务, 为了达到主线程无需等待,任务异步执行的要求,我们可以将任务加入任务 ...

  3. 常见协议基础知识总结--DHCP协议

    DHCP动态主机配置协议,简单点说,就是提供了自动获取ip地址的功能,基于四层的UDP协议: 以下描述此协议的整个工作流程: (1) 客户端发送discovery报文,二三层广播报文,源ip地址全0: ...

  4. 嵌入式上 iscsi实现

    前言 去年公司设备(haisi3516)上需要提供iscsi的功能,于是花了几天时间探究了下.linux内核(2.6.xx)支持iscsi,只是我发现当时我们设备的内核编译时没有选上,于是重新编译了内 ...

  5. Selenium2+python自动化37-爬页面源码(page_source)【转载】

    前言 有时候通过元素的属性的查找页面上的某个元素,可能不太好找,这时候可以从源码中爬出想要的信息.selenium的page_source方法可以获取到页面源码. selenium的page_sour ...

  6. 正则表达式筛选出jpg、png的图片url

    有些字符串也不是富文本,也不是带标准标签的图片地址和文字.想筛选出所有图片或地址怎么办呢.话不多说直接上带码. private static void reg() { // TODO Auto-gen ...

  7. (9)python 异常

    以下程序是python2版本下测试的代码 一.内置异常 没有错误信息的普通异常 raise Exception 添加错误信息的异常 raise Exception ('...错误') 内建异常 异常名 ...

  8. Codeforces 702C Cellular Network(二分)

    题目链接:http://codeforces.com/problemset/problem/702/C 题意: 在数轴上有N个城市和M个信号塔,给你这N个城市以及M个塔在数轴上的位置,求M个塔可以覆盖 ...

  9. 主席树【bzoj3524(p3567)】[POI2014]Couriers

    Description 给一个长度为n的序列a.1≤a[i]≤n. m组询问,每次询问一个区间[l,r],是否存在一个数在[l,r]中出现的次数大于(r-l+1)/2.如果存在,输出这个数,否则输出0 ...

  10. 算法-桶排序(Bucket sort)

    本文由@呆代待殆原创,转载请注明出处. 简介:这个排序算法不属于比较排序,在平均情况下他的时间代价是O(n),并且它假设它的输入数据均匀的分布在一个固定的区间里. 思路:桶排序假设他的输入均匀的分布在 ...