<languageVersion: 1.0;> kernel stereographics < namespace : "advanced stereographic projection"; vendor : "Chentong"; version : 1; description : "enhanced by warp(s), turn(s), scale(s) & zoom(s)"; > { # define PI 3.141592 # define DOUPLEPI 6.28318531 parameter float2 center < minValue: float2( 0.0, 0.0 ); maxValue: float2( 2000.0, 2000.0 ); defaultValue: float2( 180.0, 180.0 ); description: "set input image center"; >; parameter float2 xy_replication < minValue: float2(1.0, 1.0); maxValue: float2(181.0, 181.0); defaultValue: float2(28.0, 28.0); description: "xy.replicate map"; >; parameter float radius < minValue: float(0.0); maxValue: float(100.0); defaultValue: float(72.0); description: "set radius"; >; parameter float scale < minValue: float(0.1); maxValue: float(4.0); defaultValue: float(2.3); description: "set aspect ratio"; >; parameter float zoom < minValue: float(0.10); maxValue: float(5.00); defaultValue: float(1.00); description: "set zoom"; >; parameter float turn < minValue: float(0.00); maxValue: float(1.00); defaultValue: float(1.00); description: "set rotation"; >; parameter float warp < minValue: float(0.1); maxValue: float(PI); defaultValue: float(2.3); description: "set warp"; >; input image4 src; output pixel4 dst; void evaluatePixel() { // 相对于 xy 中心点的位置 float2 pos = outCoord()-center; // 平面直角坐标 -- 极坐标 // distance (r) float r = sqrt( pos.x * pos.x + pos.y * pos.y ); // angle (a) float theta = atan( pos.y / pos.x ); // 光谱半径 float spectral = scale * r; // 衰减 float damp = -sin( warp ) * 1.0 + cos( warp ); float rad = xy_replication.y * zoom; float maxpi = 2.0 * atan( scale ); float edgewise = 2.0 * atan( spectral / rad ); float meridian = theta + DOUPLEPI * turn; // 计算新的 xy 位置 float ny = ( xy_replication.y ) * ( 2.0 * edgewise / maxpi ) - ( xy_replication.y ); float nx = ( xy_replication.x - 1.0 )* meridian / PI - ( xy_replication.x ); // 极坐标 -- 平面直角坐标 float vx = radius * cos( nx ); float vy = radius * sin( ny ); dst = sampleLinear(src, center + float2( vx, vy * damp ) ); } }
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 StereographicProjection extends Sprite{ [Embed(source="pbj/asp.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; public function StereographicProjection(){ stage.align = StageAlign.TOP_LEFT; stage.scaleMode = StageScaleMode.NO_SCALE; container = new Sprite(); addChild(container); shader = new Shader(new ShaderClass()); shader.data.center.value = [256.0,192.0]; 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{ var pos:Number = Math.cos(angle+=0.1)*40+50; shader.data.radius.value = [pos]; //var turn:Number = Math.cos(angle+=0.01); //shader.data.turn.value = [turn]; //var scale:Number = Math.cos(angle+=0.05)*2+2; //shader.data.scale.value = [scale]; image.filters = [filter]; } } }
转载请注明:陈童的博客 » 立体投影万花筒 — Stereographic Projection Kaleidoscope