topical media & game development

talk show tell print

graphic-player-10-pixel-sample-store-twirl.pbk / pbk



  
*************************************************************************** Copyright (C) 2008 Adobe Systems Incorporated All Rights Reserved. NOTICE: All information contained herein is, and remains the property of Adobe Systems Incorporated and its suppliers, if any. The intellectual and technical concepts contained herein are proprietary to Adobe Systems Incorporated and its suppliers and may be covered by U.S. and Foreign Patents, patents in process, and are protected by trade secret or copyright law. Dissemination of this information or reproduction of this material is strictly forbidden unless prior written permission is obtained from Adobe Systems Incorporated. ***************************************************************************

  
  
  <languageVersion: 1.0;> 
   
  // twirl: A simple example to demonstrate the use of the hydra sampling 
  //           function to yield an interesting effect.  The filter performs 
  //           some math based on the parameter values to change the sampling 
  //           location.
  kernel twirl
  <   namespace : "AIF";
      vendor : "Adobe Systems";
      version : 2;
      description : "twist an image around"; >
  {
      // define PI for the degrees to radians calculation
      const float PI = 3.14159265;
      
      // An input parameter to specify the radius of the twirl effect.
      // For this parameter, we're using metadata to indicate the minimum,
      // maximum, and default values, so that the tools can set the values 
      // in the correctly in the UI for the filter.  
      // NOTE: This parameter indicates how many pixel values out from the 
      // center location we would like to twirl.  The radius is in the pixel
      // coordinate space to ensure that we always rotate in a circle.  For 
      // more information regarding the coordinate spaces, please consult the 
      // pixel bender spec.
      parameter float radius 
      <       
          minValue:float(0.1);
          maxValue:float(2048.0); 
          defaultValue:float(10.0);
      >;
      
      // An input parameter to specify the center of the twirl effect.
      // As above, we're using metadata to indicate the minimum,
      // maximum, and default values, so that the tools can set the values 
      // in the correctly in the UI for the filter.
      parameter float2 center
      <
          minValue:float2(0.0, 0.0);
          maxValue:float2(2048.0, 2048.0);
          defaultValue:float2(256.0, 256.0);
      >;
      
      // An input parameter to specify the angle that we would like to twirl.
      // For this parameter, we're using metadata to indicate the minimum,
      // maximum, and default values, so that the tools can set the values 
      // in the correctly in the UI for the filter.
      parameter float twirlAngle
      <
          minValue:float(0.0);
          maxValue:float(360.0);
          defaultValue:float(90.0);
      >;
      
      // An input parameter that indicates how we want to vary the twirling
      // within the radius.  We've added support to modulate by one of two 
      // functions, a gaussian or a sinc function.  Since Flash does not support
      // bool parameters, we instead are using this as an int with two possible
      // values. Setting this parameter to be 1 will
      // cause the gaussian function to be used, unchecking it will cause 
      // the sinc function to be used.
      parameter int gaussOrSinc
      <
          minValue:int(0);
          maxValue:int(1);
          defaultValue:int(0);
      >;
      
      input image4 oImage;
      output float4 outputColor;
  
  // Region functions are not available in Flash targets, so we only define 
  // the functions if we are executing on a different backend.
  if !AIF_FLASH_TARGET
  
      // needed(): Indicates what area of the input is needed to fulfill the
      //           requested output region.  In this case, we consider a
      //           radius = 1.0 area of the input for each output pixel, so we 
      //           need to outset the area by one.
      region needed(region outputRegion, imageRef inputRef)
      {
          // if we have a gaussian function, negligible rotation occurs at 3 * radius
          // for a sinc function, we want a radius where the value is < 0.03.  That
          // happens at a factor of 33.3 times the radius.
          float2 fallOffPoint = pixelSize(oImage);
          fallOffPoint *= radius;
          if(gaussOrSinc == 0)
              fallOffPoint *= 3.0;
          else
              fallOffPoint *= 33.3;
              
          region rotatedRegion = region(float4(center.x - fallOffPoint.x, 
                                               center.y - fallOffPoint.y,
                                               center.x + fallOffPoint.x, 
                                               center.y + fallOffPoint.y));     
          return union(outputRegion, rotatedRegion);
      }
  
      // changed(): Indicates what area of the output is affected by the 
      //            specified input.  In this case, we will blur out the image 
      //            by exactly one pixel, so the output is the input outset by 
      //            one.
      region changed(region inputRegion, imageRef inputRef)
      {    
          // if we have a gaussian function, negligible rotation occurs at 3 * radius
          // for a sinc function, we want a radius where the value is < 0.03.  That
          // happens at a factor of 33.3 times the radius.
          float2 fallOffPoint = pixelSize(oImage);
          fallOffPoint *= radius;
          if(gaussOrSinc == 0)
              fallOffPoint *= 3.0;
          else
              fallOffPoint *= 33.3;
              
          region rotatedRegion = region(float4(center.x - fallOffPoint.x, 
                                               center.y - fallOffPoint.y,
                                               center.x + fallOffPoint.x, 
                                               center.y + fallOffPoint.y));   
          return union(inputRegion, rotatedRegion);
      }
  
  endif
  
      // evaluatePixel(): The function of the filter that actually does the 
      //                  processing of the image.  This function is called once 
      //                  for each pixel of the output image.
      void
      evaluatePixel()
      {
          // convert the angle to radians
          float twirlAngleRadians = radians(twirlAngle);
  
          // adjust the radius value from pixel coordinates to world coordinates
          // to do this, we multiply by the pixel size.
          float adjustedRadius = length(radius * pixelSize(oImage));
  
          // calculate where we are relative to the center of the twirl
          float2 relativePos = outCoord() - center;
          
          // calculate the absolute distance from the center normalized 
          // by the twirl radius.
          float distFromCenter = length( relativePos );
          distFromCenter /= adjustedRadius; 
          
          // modulate the angle based on either a gaussian or a sync.
          float adjustedRadians;
          
          // precalculate either the gaussian or the sinc weight
          float sincWeight = sin( distFromCenter ) * twirlAngleRadians / ( distFromCenter );
          float gaussWeight = exp( -1.0 * distFromCenter * distFromCenter ) * twirlAngleRadians;
          
          // protect the algorithm from a 1 / 0 error
          adjustedRadians = (distFromCenter == 0.0) ? twirlAngleRadians : sincWeight;
          
          // switch between a gaussian falloff or a sinc fallof
          adjustedRadians = (gaussOrSinc == 1) ? adjustedRadians : gaussWeight;
          
          // rotate the pixel sample location.
          float cosAngle = cos( adjustedRadians );
          float sinAngle = sin( adjustedRadians );
          
          float2x2 rotationMat = float2x2(
              cosAngle,   sinAngle,
              -sinAngle,  cosAngle
          );
          
          relativePos = rotationMat * relativePos; 
          
          // sample and set as the output color.  since relativePos
          // is related to the center location, we need to add it back in.
          // We use linear sampling to smooth out some of the pixelation.
          outputColor = sampleLinear( oImage, relativePos + center );
      }
  }
  


(C) Æliens 20/2/2008

You may not copy or print any of this material without explicit permission of the author or the publisher. In case of other copyright issues, contact the author.