<languageVersion : 1.0;> # define PI 3.141592 # define DOUPLEPI 6.28318531 kernel RadialCaleidoscope < namespace : "RadialCaleidoscope"; vendor : "ChenTong"; version : 1; description : "Caleidoscope -effect for radial reflection"; > { parameter float angle // 类似于 2*PI/n, 整数 n >3 < minValue:float(0.0001); maxValue:float(PI); defaultValue:float(0.628318531); >; parameter float direction < minValue:float(0.0); maxValue:float(DOUPLEPI); defaultValue:float(0.0001); >; parameter float2 basepoint // 或 中心点 < minValue:float2(0.01); maxValue:float2(496.01,496.01); defaultValue:float2(150.01,150.01); >; input image4 src; output pixel4 dst; void evaluatePixel() { // 相对于中心点(基点)的位置 float2 po = outCoord() - basepoint; // 极坐标的角度和半径 // 加 4*PI 保持角度为正角度 float theta = atan(po.y,po.x)-direction +2.0*DOUPLEPI; float radius = sqrt(po.x*po.x+po.y*po.y); // 求余操作 float newAngle = mod(theta,angle); float section = floor(theta/angle); // 镜像奇数位置 if (mod(section,2.0)>0.5) newAngle = angle-newAngle; // 将极坐标转换为平面直角坐标 dst = sampleLinear(src,basepoint+float2(radius *cos(newAngle += direction), radius *sin(newAngle))); } }
AS类文件:
package{ import flash.display.Bitmap; import flash.display.GradientType; import flash.display.Shader; import flash.display.Shape; import flash.display.Sprite; import flash.display.StageAlign; import flash.display.StageScaleMode; import flash.events.Event; import flash.filters.ShaderFilter; import flash.geom.Matrix; [SWF(width="800",height="600",frameRate="10",backgroundColor="0x000000")] public class RadialKaleidoscope extends Sprite{ [Embed(source="pbj/RadialCaleidoscope.pbj",mimeType="application/octet-stream")] private var ShaderClass:Class; [Embed(source="assets/Flower6.jpg")] private var Flower:Class; private var container:Sprite; private var shader:Shader; private var filter:ShaderFilter; private var image:Bitmap; private var maskShape:Shape; private var gradientShape:Shape; private var radius:Number = 250; private var angle:Number = 0; private var value:Number = 0; public function RadialKaleidoscope(){ stage.align = StageAlign.TOP_LEFT; stage.scaleMode = StageScaleMode.NO_SCALE; container = new Sprite(); addChild(container); shader = new Shader(new ShaderClass()); shader.data.basepoint.value = [256.0,192.0]; shader.data.angle.value = [0.2168]; filter = new ShaderFilter(shader); image = new Flower(); container.x = (800-image.width)/2; container.y = (600-image.height)/2; container.addChild(image); image.filters = [filter]; maskShape = new Shape(); maskShape.graphics.beginFill(0xffffff,1); maskShape.graphics.drawCircle(0,0,radius); maskShape.graphics.endFill(); addChild(maskShape); maskShape.x = 400; maskShape.y = 300; container.mask = maskShape; gradientShape = new Shape(); var matrix:Matrix = new Matrix(); var colors:Array = [0x000000,0x000000]; var alphas:Array = [0,1]; var ratios:Array = [150,255]; matrix.createGradientBox(radius*2,radius*2,0,-radius,-radius); gradientShape.graphics.lineStyle(); gradientShape.graphics.beginGradientFill(GradientType.RADIAL,colors,alphas,ratios,matrix); gradientShape.graphics.drawCircle(0,0,radius); gradientShape.graphics.endFill(); addChild(gradientShape); gradientShape.x = 400; gradientShape.y = 300; addEventListener(Event.ENTER_FRAME,onEnterframe); } private function onEnterframe(e:Event):void{ value = Math.cos(angle+=0.02)*Math.PI+Math.PI*2; shader.data.direction.value = [value]; image.filters = [filter]; } } }