使用着色器作为混合模式与使用其他混合模式类似。着色器定义的外观取决于将两个显示对象混合在一起的视觉效果。若要将着色器用于混合模式,请将 Shader 对象指派给前景显示对象的
blendShader
属性。如果为
blendShader
属性指定非
null
值,显示对象的
blendMode
属性将自动设置为
BlendMode.SHADER
。下面的清单演示如何使用着色器作为混合模式。注意,此示例假定存在名为
foreground
的显示对象。该对象与其他显示内容包含在显示列表的同一父级中,而
foreground
与其他内容重叠:
foreground.blendShader = myShader;
使用着色器作为混合模式时,着色器必须由至少两个输入定义。如示例所示,您未在代码中设置输入值。而是将两个混合后的图像自动用作着色器的输入。前景图像设置为第二个图像。(此显示对象便是要对其应用混合模式的对象。)背景图像由前景图像边框后的所有像素组合而成。背景图像设置为第一个输入图像。如果所用着色器要求两个以上的输入,则还需为前两个之外的其他输入提供值。
下面的示例演示如何使用着色器作为混合模式。此示例使用基于亮度的加亮混合模式。混合的结果是以任一混合对象中最亮的像素值显示该像素。
注:
此示例的代码由 Mario Klingemann 编写。感谢 Mario 分享此示例。若要查看 Mario 的更多作品及阅读他的文章,请访问
www.quasimondo.com/
。
这段重要的 ActionScript 代码用到下面两个方法:
-
init()
:应用程序加载时调用
init()
方法。在此方法中,代码加载着色器字节代码文件。
-
onLoadComplete()
:在
onLoadComplete()
方法中,代码创建名为
shader
的 Shader 对象。然后绘制三个对象。第一个对象
backdrop
是混合对象后的深灰色背景。第二个对象
backgroundShape
是绿色渐变椭圆。第三个对象
foregroundShape
是橙色渐变椭圆。
foregroundShape
椭圆是混合的前景对象。混合的背景图像由部分
backdrop
和部分
backgroundShape
构成,并叠加了
foregroundShape
对象的边框。
foregroundShape
对象是位于显示列表最前面的对象。它与
backgroundShape
部分重叠,与
backdrop
全部重叠。由于上述重叠的存在,如果不应用混合模式,橙色椭圆 (
foregroundShape
) 将全部显示,并遮盖住绿色椭圆 (
backgroundShape
) 的一部分:
而在应用混合模式之后,绿色椭圆的较亮部分会“穿透”前景显示出来,因为该部分比遮盖它的那部分
foregroundShape
更亮。
下面是此示例的 ActionScript 代码。使用此类作为 Flash Builder 中纯 ActionScript 项目的主应用程序类,或者作为 Flash Professional 中 FLA 文件的文档类:
package
{
import flash.display.BlendMode;
import flash.display.GradientType;
import flash.display.Graphics;
import flash.display.Shader;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.geom.Matrix;
import flash.net.URLLoader;
import flash.net.URLLoaderDataFormat;
import flash.net.URLRequest;
public class LumaLighten extends Sprite
{
private var shader:Shader;
private var loader:URLLoader;
public function LumaLighten()
{
init();
}
private function init():void
{
loader = new URLLoader();
loader.dataFormat = URLLoaderDataFormat.BINARY;
loader.addEventListener(Event.COMPLETE, onLoadComplete);
loader.load(new URLRequest("LumaLighten.pbj"));
}
private function onLoadComplete(event:Event):void
{
shader = new Shader(loader.data);
var backdrop:Shape = new Shape();
var g0:Graphics = backdrop.graphics;
g0.beginFill(0x303030);
g0.drawRect(0, 0, 400, 200);
g0.endFill();
addChild(backdrop);
var backgroundShape:Shape = new Shape();
var g1:Graphics = backgroundShape.graphics;
var c1:Array = [0x336600, 0x80ff00];
var a1:Array = [255, 255];
var r1:Array = [100, 255];
var m1:Matrix = new Matrix();
m1.createGradientBox(300, 200);
g1.beginGradientFill(GradientType.LINEAR, c1, a1, r1, m1);
g1.drawEllipse(0, 0, 300, 200);
g1.endFill();
addChild(backgroundShape);
var foregroundShape:Shape = new Shape();
var g2:Graphics = foregroundShape.graphics;
var c2:Array = [0xff8000, 0x663300];
var a2:Array = [255, 255];
var r2:Array = [100, 255];
var m2:Matrix = new Matrix();
m2.createGradientBox(300, 200);
g2.beginGradientFill(GradientType.LINEAR, c2, a2, r2, m2);
g2.drawEllipse(100, 0, 300, 200);
g2.endFill();
addChild(foregroundShape);
foregroundShape.blendShader = shader;
foregroundShape.blendMode = BlendMode.SHADER;
}
}
}
下面是 LumaLighten 着色器内核的源代码,用于创建“LumaLighten.pbj”Pixel Bender 字节代码文件:
<languageVersion : 1.0;>
kernel LumaLighten
<
namespace : "com.quasimondo.blendModes";
vendor : "Quasimondo.com";
version : 1;
description : "Luminance based lighten blend mode";
>
{
input image4 background;
input image4 foreground;
output pixel4 dst;
const float3 LUMA = float3(0.212671, 0.715160, 0.072169);
void evaluatePixel()
{
float4 a = sampleNearest(foreground, outCoord());
float4 b = sampleNearest(background, outCoord());
float luma_a = a.r * LUMA.r + a.g * LUMA.g + a.b * LUMA.b;
float luma_b = b.r * LUMA.r + b.g * LUMA.g + b.b * LUMA.b;
dst = luma_a > luma_b ? a : b;
}
}
有关使用混合模式的详细信息,请参阅
应用混合模式
。
注:
当 Pixel Bender 着色器程序以混合模式在 Flash Player 或 AIR 中运行时,采样和
outCoord()
函数的行为与在其他上下文中不同。在混合模式中,采样函数将始终返回着色器计算的当前像素。例如,您不能为了采集邻近像素而向
outCoord()
中添加偏移。同样,如果您使用
outCoord()
函数而不使用采样函数,则其坐标的计算结果将始终为 0。例如,您无法利用像素的位置来影响混合图像的合并方式。