topical media & game development
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.