Flex 4.5 blendShader, Pixel Bender не обновляет

Я следую учебному пособию Джо Уорда о Pixel Bender для Flex и AIR и обновляю его для Flex 4.5 Flashplayer 11. Работая над разделом grainBlend, он отлично работает, если у меня появляется всплывающее сообщение "Alert". В противном случае шейдер не обновляется / обновляется при смене HSlider.

Другими словами: скрипт выполняется, если у меня есть активное оповещение. Если я удаляю Alert Message, blendShader работает только один раз и никогда не обновляется впоследствии.

ScriptFlow:

Init () ОК

создать шейдер ОК

обнаружить HSlider Change OK

updateFilter () ОК

обновить значение турбулентности шейдера ОК

обновить изображение "шумового" шейдера и перерисовать НЕ РАБОТАЮЩИЙ

Я полагаю, что следующая выдержка из учебника может быть проблемой. "... Поскольку объект шейдера клонируется при установке свойства 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>

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 ответ

Я разочаровался в blendShader. Я воссоздал его с помощью фильтров. Это работает сейчас. Кроме того, я динамически создал коричневый фон и шум перлина. Увидеть ниже!

<?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>`
Другие вопросы по тегам