Pages

Sunday, January 9, 2011

DiagonalBlockWipe shader for Flex effects

I played around a bit with PixelBender shaders and the result is a nice little shader which can be used for transition effects.

I started out with Adobe's Wipe effect and created a diagonal block wipe, which looks like that:

To view this page ensure that Adobe Flash Player version 10.0.0 or greater is installed.

You can change both the direction of the wipe and the size of the blocks.
Now let's have a look at the code:

<languageVersion:1.0;>
kernel DiagonalBlockWipe<
 namespace: "flex";
 vendor: "Norbert Kopcsek";
 version: 1;
 description: "Diagonal block wipe between two images for Flex effects";
>
{
 // first input is unused in FxAnimateTransitionShader effect
 input image4 src0;
 input image4 from;
 input image4 to;
 output pixel4 dst;

 parameter float progress<
  minValue: 0.00;
  maxValue: 1.00;
  defaultValue: 0.0;
 >;
 
 parameter float blockSize<
  minValue: 1.0;
  maxValue: 256.0;
  defaultValue: 30.0;
 >;

 parameter float width<
  minValue: 0.0;
  maxValue: 1024.0;
  defaultValue: 576.0;
 >;

 parameter float height<
  minValue: 0.00;
  maxValue: 1024.0;
  defaultValue: 384.0;
 >;
 
 // 0 == top left->bottom right
 // 1 == top right->bottom left
 // 2 == bottom right->top left
 // 3 == bottom left->top right
 parameter int direction<
  minValue: 0;
  maxValue: 3;
  defaultValue: 0;
 >;

 void
 evaluatePixel()
 {
  float2 coord = outCoord();
  // Use src0 just to defeat the optimizer from removing the input
  pixel4 color1 = sampleNearest(src0, coord);
  color1 = sampleNearest(from, coord);
  pixel4 color2 = sampleNearest(to, coord);
  
  float2 projectedCoord;
  
  if (direction == 0) {
   projectedCoord = coord;
  }
  else if (direction == 1) {
   projectedCoord = float2( width - coord.x, coord.y );
  }
  else if (direction == 2) {
   projectedCoord = float2( width - coord.x, height - coord.y );
  }
  else {
   projectedCoord = float2( coord.x, height - coord.y );
  }
  
  float blockProgress = floor( ( width + height ) * progress / blockSize );
  float2 block = floor( projectedCoord / float2( blockSize, blockSize ));
  dst = (block.x > blockProgress - block.y && block.y > blockProgress - block.x ) ? color1 : color2;
  
  // workaround for Flash filter bug that replicates last column/row
  if (coord.x >= width || coord.y >= height) {
   dst.a = 0.0;
  }
 }
}

The major part of the shader is the same as in Adobe's Wipe effect. The only parameter I added is blockSize, which defines the length of one side of the blocks used in the transition. The change of the code is rather simple: First it calculates the block it is in and then decides whether the block shows color1 of the from image or color2 of the to image based on the given blockProgress.

2 comments:

  1. Nice work, thanks for the post...the direction selection doesn't work for me?

    ReplyDelete
  2. Thanks for the hint. I fixed it. The shader stays the same.

    ReplyDelete