2012-08-29 12 views
6

ho il seguente codice, realizzato per testare solo, come questa è stata una sorta di un bug ho voluto inchiodare:L'applicazione del filtro shader a un oggetto BitmapData ignora il rettangolo passato: come applicare correttamente il filtro shader?

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

Poi ho scorrere _sequence per vedere se cambia rettangolo in realtà fa qualcosa. Non fa nulla, se _shaderFilter è in realtà un filtro shader. Test con uno qualsiasi dei filtri Flash incorporati funziona come previsto, ma con ShaderFilter a volte funziona come se il rettangolo fornito fosse chiaramente sourceBitmapData.rect, qualunque fosse la bitmap di origine, e talvolta si comporta come se non ci fossero dati passati, con il limite di essere situato in una posizione strana - con una bitmap di dimensione 512x384, il bordo della regione passata allo shader è apparentemente situato a (256,192) o al centro della bitmap. Finora sono stato in grado di implementare solo una soluzione alternativa, ovvero copyPixels(), la regione richiesta, quindi applyFilter() in posizione. Qualcuno può provare che è un bug e non sto facendo qualcosa di sbagliato?

PS: Sto utilizzando FlashDevelop con destinazione del progetto Flash Player 10.3 e non so se FP11 risolve questo problema.

risposta

1

Beh, purtroppo non posso dirti come risolvere il problema, ma posso confermare che non è colpa tua!

Il problema sembra essere che Flash ignora completamente sourceRect quando si utilizzano shader personalizzati. All'inizio ho pensato che potesse passare i valori a un parametro non documentato nello shader, ma poi ho notato che ogni pixel della bitmap di output viene modificato, anche quando lo sourceRect è più piccolo o lo destPoint è diverso da zero. Inoltre, non sembra che la funzione inCoord() corrisponda a outCoord(), quindi sembra che questo non sia un utilizzo previsto dagli sviluppatori!

Posso offrire un suggerimento; invece di copiare la ROI in un nuovo oggetto BitmapData, aggiungere un parametro float2 offset allo shader e spostare tutte le ricerche di pixel di questo valore. Salverà un po 'di elaborazione.

Qui è il caso di prove ridotto che ho usato per confermare il comportamento:

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

uscita:

Screenshot of output

(il piccolo quadrato sulla destra copia dal grande quadrato usando uno shader. Il riquadro rosso mostra sourceRect. Lo destPoint è (10,10). Nonostante entrambe queste impostazioni, rende effettivamente l'intera bitmap)

+0

Grazie per aver tentato un test indipendente! Hai provato a compilarlo con il target FP11 e controllare se funziona allo stesso modo? – Vesper

+1

@Vesper Sì, l'ho provato il 10 e 11. Lo stesso risultato in entrambi (lo screenshot è da 11) – Dave