2012-08-29 6 views
6

Ich habe den folgenden Code, gemacht für nur testen, da dies eine Art von Fehler war ich nageln wollte:Das Anwenden des Shader-Filters auf ein BitmapData-Objekt ignoriert das übergebene Rechteck - wie wird der Shader-Filter richtig angewendet?

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

Dann fahre ich durch _sequence, um zu sehen, ob Wechsel tatsächlich Rechteck etwas tut. Es tut nichts, wenn _shaderFilter tatsächlich ein Shader-Filter ist. Das Testen mit einem der integrierten Flash-Filter funktioniert wie vorgesehen, aber mit ShaderFilter funktioniert es manchmal so, als wäre das bereitgestellte Rechteck einfach sourceBitmapData.rect, was auch immer die Quell-Bitmap ist, und manchmal verhält es sich so, als ob keine Daten übergeben wurden, mit Begrenzung an einer seltsamen Position angeordnet - mit einer Bitmap der Größe 512x384 befindet sich die Kante der Region, die an den Shader übergeben wird, scheinbar an (256,192) oder der Mitte der Bitmap. Bisher konnte ich nur einen Workaround implementieren, dh zuerst copyPixels() die benötigte Region, dann applyFilter() an Ort und Stelle. Kann jemand beweisen, dass es ein Fehler ist und ich nicht etwas falsch mache?

PS: Ich benutze FlashDevelop mit Projekt Ziel als Flash Player 10.3, und ich bin mir nicht bewusst, wenn FP11 dies behebt.

Antwort

1

Nun, leider kann ich Ihnen nicht sagen, wie das zu beheben ist, aber ich kann bestätigen, dass es nicht deine Schuld ist!

Das Problem scheint zu sein, dass Flash sourceRect vollständig ignoriert, wenn benutzerdefinierte Shader verwenden. Zuerst dachte ich, es könnte die Werte an einen undokumentierten Parameter im Shader übergeben, aber dann habe ich bemerkt, dass jedes Pixel der Ausgabe-Bitmap geändert wird, auch wenn sourceRect kleiner ist oder destPoint nicht Null ist. Auch scheint es keine inCoord() Funktion zu sein, die outCoord() entspricht, also sieht es so aus, als ob die Entwickler keine Verwendung erwarten würden!

Ich kann einen Vorschlag anbieten; Anstatt den ROI in ein neues BitmapData Objekt zu kopieren, fügen Sie einen float2 offset Parameter zu Ihrem Shader hinzu und verschieben Sie alle Pixel-Lookups um diesen Wert. Es wird etwas Verarbeitung sparen.

Hier ist der reduzierte Testfall ich das Verhalten bestätigen verwendet:

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

Ausgang:

Screenshot of output

(das kleine Quadrat rechts kopiert mit einem Shader vom großen Quadrat). Das rote Feld zeigt die sourceRect. Die destPoint ist (10,10). Trotz dieser beiden Einstellungen, rendert es tatsächlich die gesamte Bitmap)

+0

Vielen Dank für einen unabhängigen Test! Haben Sie versucht, es mit dem FP11-Ziel zu kompilieren und zu prüfen, ob es dort gleich funktioniert? – Vesper

+1

@Vesper Ja, ich habe es auf 10 und 11 versucht. Das gleiche Ergebnis in beiden (der Screenshot ist von 11) – Dave

Verwandte Themen