我正在关注 Joe Ward 的Flex 和 AIR教程的 Pixel Bender 基础知识,并为 Flex 4.5 Flashplayer 11 更新它。在grainBlend 部分工作时,如果我弹出“警报”消息,它效果很好。否则,当 HSlider 更改时,着色器不会刷新/更新。
换句话说:如果我有一个活动的警报消息,脚本就会运行。如果我删除警报消息,blendShader 只能工作一次,之后就不会更新。
脚本流:
初始化()好的
创建着色器确定
检测 HSlider Change OK
updateFilter() 确定
更新 Shader 的湍流值 OK
更新图像“噪声”着色器并重绘不工作
我相信本教程的以下摘录可能是问题所在。“...因为在设置显示对象的 blendShader 属性时会克隆着色器对象,所以不能简单地更改原始 Shader 对象的参数。您还必须将更新后的 Shade 对象重新分配给 blendShader 属性...。”
shader.data.turbulence.value = [turbulence.value];
noise.blendMode = BlendMode.SHADER;
noise.blendShader = shader;
弹性代码
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
contentCreationComplete="init()"
backgroundColor="0x666666">
<fx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.events.SliderEvent;
//Embed the Pixel Bender kernel in the output SWF
[Embed(source="kernels/grainblend.pbj", mimeType="application/octet-stream")]
private var GrainBlendKernel:Class;
//Create the Shader object
[Bindable]
private var shader:Shader = new Shader( new GrainBlendKernel() );
private function init():void
{
//Set the slider values based on the parameter metadata
turbulence.minimum = shader.data.turbulence.minValue;
turbulence.maximum = shader.data.turbulence.maxValue;
turbulence.value = shader.data.turbulence.defaultValue;
turbulence.addEventListener( SliderEvent.CHANGE, updateFilter );
//Apply the blend
noise.blendShader = shader;
}
private function updateFilter( event:Event ):void
{
trace(turbulence.value);//print slider
//Alert.show("Hit");
shader.data.turbulence.value = [turbulence.value];
trace("shader's value: "+shader.data.turbulence.value);
noise.blendMode = BlendMode.SHADER;
noise.blendShader = shader;
}
]]>
</fx:Script>
<s:VGroup width="100%">
<s:HGroup width="100%" height="100%" horizontalAlign="center" verticalAlign="top">
<s:VGroup>
<mx:Canvas width="195" height="194" backgroundColor="#663300"/>
<s:Label text="Background" textAlign="center" width="196"/>
</s:VGroup>
<s:VGroup>
<s:Image source="img/noise.jpg" width="195" height="194"/>
<s:Label text="Perlin noise" width="196" textAlign="center"/>
</s:VGroup>
<s:VGroup>
<mx:Canvas width="195" height="194" backgroundColor="#663300">
<s:Image source="img/noise.jpg" id="noise" width="195" height="194"/>
</mx:Canvas>
<s:Label text="Grain blend" width="196" textAlign="center"/>
</s:VGroup>
</s:HGroup>
<s:HGroup width="100%" horizontalAlign="center" verticalAlign="top">
<s:Label text="{turbulence.value}"/>
<s:HSlider id="turbulence" width="200"/>
</s:HGroup>
</s:VGroup>
像素弯曲内核
<languageVersion: 1.0;>
kernel GrainBlend
< namespace : "com.adobe.example";
vendor : "Adobe Systems Inc.";
version : 1;
description : "Creates a wood grain or marbleing effect"; >
{
input image4 background;
input image4 noise;
output pixel4 dst;
parameter float turbulence
<
maxValue : 500.0;
minValue : 0.0;
defaultValue : 150.0;
>;
void evaluatePixel()
{
pixel4 a = sampleNearest(background, outCoord());
pixel4 b = sampleNearest(noise, outCoord());
float alpha = a.a; //save the original alpha
if( (b.a > 0.0) && (a.a > 0.0)){
float seed = outCoord().x + (((b.r + b.g + b.b)/3.0) * turbulence);
float grain = (0.7 * sin(seed) + 0.3 * sin(2.0 * seed + 0.3) + 0.2 * sin(3.0 * seed + 0.2));
dst = sampleNearest(background, outCoord()) * (grain + 0.5);
dst.a = alpha; //restore the original alpha
}
else {
//Just copy the background pixel outside the area of the noise image
dst = sampleNearest(background, outCoord());
}
}
}