6 votes

L'application du filtre d'ombrage à un objet BitmapData ignore le rectangle passé - comment appliquer correctement le filtre d'ombrage ?

J'ai le code suivant, fait pour le test seulement, car c'était une sorte de bug que je voulais clouer :

        _shader = new Shader(new TheShader() as ByteArray);
        _shader.data.width.value = [64.0];
        _shader.data.height.value = [64.0];
        _shaderFilter = new ShaderFilter(_shader);
        _sequence = new Vector.<BitmapData>();
        var smallBD:BitmapData;
        var i:int;
        _delta = new Point();
        var megabase:BitmapData = new TheBitmap().bitmapData;
        var _rect:Rectangle = new Rectangle(0, 0, 64, 64);
        for (i = 0; i < 64; i++) {
            smallBD = new BitmapData(64, 64, true, 0x00808080);
            //_rect.x = i;
            _rect.y = i;
            smallBD.applyFilter(megabase, _rect, _delta, _shaderFilter);
            _sequence.push(smallBD);
        }

Ensuite, je parcours _sequence pour voir si le changement de rectangle a un effet réel. Cela ne fait rien, si _shaderFilter est en fait un filtre shader. Le test avec n'importe quel filtre Flash intégré fonctionne comme prévu, mais avec ShaderFilter, il fonctionne parfois comme si le rectangle fourni était simplement sourceBitmapData.rect, quel que soit le bitmap source, et parfois il se comporte comme si aucune donnée n'était transmise, avec des limites situées à des positions bizarres - avec un bitmap de taille 512x384, le bord de la région qui est transmise au shader est apparemment situé à (256,192) ou au centre du bitmap. Jusqu'à présent, je n'ai pu mettre en œuvre qu'une solution de contournement, à savoir copierPixels() la région requise, puis appliquerFilter() à la place. Quelqu'un peut-il prouver qu'il s'agit d'un bug et que je ne fais pas quelque chose de mal ?

PS : J'utilise FlashDevelop avec comme cible de projet Flash Player 10.3, et je ne sais pas si FP11 corrige ce problème.

1voto

Dave Points 7854

Malheureusement, je ne peux pas vous dire comment résoudre ce problème, mais je peux vous confirmer que ce n'est pas votre faute !

Le problème semble être que Flash ignore sourceRect entièrement lors de l'utilisation de shaders personnalisés. Au début, j'ai pensé que les valeurs étaient transmises à un paramètre non documenté du shader, mais j'ai ensuite remarqué que chaque pixel de l'image bitmap de sortie était modifié, même lorsque l'attribut sourceRect est plus petit ou le destPoint est non nul. De plus, il ne semble pas y avoir de inCoord() pour correspondre à la fonction outCoord() Il semble donc que ce ne soit pas une utilisation prévue par les développeurs !

Je peux vous proposer une suggestion : au lieu de copier le ROI dans un nouveau BitmapData ajoutez un float2 offset à votre shader, et décalez toutes les recherches de pixels de cette valeur. Cela permettra d'économiser un peu de traitement.

Voici le scénario de test réduit que j'ai utilisé pour confirmer ce comportement :

ShaderTest.as :

package {
    import flash.display.Sprite;
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Shader;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    import flash.filters.ShaderFilter;

    final public class ShaderTest extends Sprite {
        [Embed(source="test.pbj",mimeType="application/octet-stream")]
        private static const sCopy : Class;

        final private function R( x, y, w, h ) : Rectangle {
            return new Rectangle( x, y, w, h );
        }
        final public function ShaderTest( ) {
            super( );
            var
            s  : Shader = new Shader( new sCopy( ) ),
            f  : ShaderFilter = new ShaderFilter( s ),
            d1 : BitmapData = new BitmapData( 256, 256, false, 0 ),
            d2 : BitmapData = new BitmapData( 128, 128, false ),
            b1 : Bitmap = new Bitmap( d1 ),
            b2 : Bitmap = new Bitmap( d2 ),
            w  : Rectangle = R( 16, 16, 64, 64 );
            b2.x = 274;
            addChild( b1 );
            addChild( b2 );

            for( var i : int = 0; i < 8; ++ i ) {
                for( var j : int = 0; j < 8; ++ j ) {
                    d1.fillRect( R( i * 32 + 1, j * 32 + 1, 30, 30 ), (((i + j) & 1) * 0x00FF00) | (i << 21) | (j << 5) );
                }
            }
            d2.applyFilter( d1, w, new Point( 10, 10 ), f );
            d1.fillRect( R( w.x, w.y, 1, w.height ), 0xFF0000 );
            d1.fillRect( R( w.x, w.y, w.width, 1 ), 0xFF0000 );
            d1.fillRect( R( w.x, w.y + w.height - 1, w.width, 1 ), 0xFF0000 );
            d1.fillRect( R( w.x + w.width - 1, w.y, 1, w.height ), 0xFF0000 );
        }
    }
}

test.pbk :

<languageVersion:1.0;>

kernel bugtest <namespace:"Me";vendor:"Me";version:1;>{
    input image4 src;
    output pixel4 dst;
    void evaluatePixel(){
        dst = sampleNearest(src,outCoord());
    }
}

Sortie :

Screenshot of output

(le petit carré à droite est copié à partir du grand carré à l'aide d'un shader. La boîte rouge montre le sourceRect . Le site destPoint est (10,10). Malgré ces deux paramètres, le rendu de l'intégralité du bitmap est effectué).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X