Flex 4.5 blendShader,Pixel Bender不爽

时间:2012-10-18 23:03:09

标签: flex4.5 pixel-bender

我正在关注Joe Ward的Pixel Bender basics for Flex and AIR教程,并为Flex 4.5 Flashplayer 11更新它。 在处理grainBlend部分时工作很棒,如果我弹出“警报”消息。否则,在更改HSlider时,着色器不会刷新/更新。

换句话说:如果我有一条活动的Alert消息,脚本就会运行。如果我删除了Alert Message,则blendShader只能运行一次,之后不再更新。

ScriptFlow:

初始化()确定

创建着色器确定

检测HSlider改变确定

updateFilter()确定

更新Shader的turbulace值OK

更新图像“噪音”着色器并重绘不工作

我相信教程中的以下摘录可能就是问题所在。 “...因为在设置显示对象的blendShader属性时克隆了着色器对象,所以不能简单地更改原始Shader对象的参数。还必须将更新的Shade对象重新分配给blendShader属性....”

    shader.data.turbulence.value = [turbulence.value];
noise.blendMode = BlendMode.SHADER;
noise.blendShader = shader;

Flex代码

<?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>

Pixel Bender Kernel

<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());
    }

}
}

1 个答案:

答案 0 :(得分:0)

我放弃了blendShader。我使用过滤器重新创建它。它现在有效。另外,我动态创建了棕色背景和perlin噪音。 见下文!

<?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"
           creationComplete="init()"
           backgroundColor="0x666666">
<fx:Script>
    <![CDATA[
        import mx.events.SliderEvent;

        import spark.filters.ShaderFilter;


        //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
        private var shader:Shader = new Shader( new GrainBlendKernel() );
        private var shaderFilter:ShaderFilter =  new ShaderFilter(shader);
        private var myBrown:BitmapData;
        private var myPerlin:BitmapData;

        private function init():void
        {   
            myPerlin = new BitmapData(200, 200, false, 0x00CCCCCC);
            myBrown = new BitmapData(200, 200, false, 0x00663300);
            //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 );
            myPerlin.perlinNoise(100, 80, 6, Math.floor(Math.random() * 10), false, true, 7, true, null);
            //Set the displayed images to the perlinNoise
            perlinNoise.source = myGrain.source =myPerlin;
            //Set the background image to Brown
            backGround.source = myBrown;
            shader.data.background.input = myBrown;
            myGrain.filters = [shaderFilter];
        }


        private function updateFilter( event:Event ):void
        {
            shader.data.turbulence.value = [turbulence.value];
            myGrain.filters = [shaderFilter];
        }
    ]]>
</fx:Script>
<s:VGroup width="100%">
    <s:HGroup width="100%" height="100%" horizontalAlign="center" verticalAlign="top">
        <s:VGroup>
            <s:BitmapImage id="backGround" width="200" height="200"/>
            <s:Label text="Background" textAlign="center" width="200"/>
        </s:VGroup>
        <s:VGroup>              
            <s:BitmapImage id="perlinNoise" width="200" height="200"/>
            <s:Label text="Perlin noise" width="200" textAlign="center"/>
        </s:VGroup>
        <s:VGroup>
            <s:BitmapImage id="myGrain" width="200" height="200" />
            <s:Label text="Grain blend" width="200" 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>
    </s:Application>`