Joe Ward のFlex および AIRチュートリアル用の Pixel Bender の基本に従い、Flex 4.5 Flashplayer 11 用に更新しています。そうしないと、HSlider が変更されたときにシェーダーが更新/更新されません。
つまり、スクリプトは、アクティブなアラート メッセージがある場合に実行されます。アラート メッセージを削除すると、blendShader は 1 回だけ機能し、その後は更新されません。
スクリプトフロー:
初期化() OK
シェーダー作成 OK
検出 HSlider 変更 OK
updateFilter() OK
シェーダーの乱流値を更新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());
}
}
}