テクスチャ座標を正弦関数を利用してずらす擬似ラスタースクロールをAGALで書いてみました。Phaseに加算している値、Frequency、Amplitudeの値を変更するとスクロール量等の調整ができます。
package { import flash.display.BitmapData; import flash.display.Sprite; import flash.display.Stage3D; import flash.display.StageAlign; import flash.display.StageScaleMode; import flash.display3D.Context3D; import flash.display3D.Context3DProgramType; import flash.display3D.Context3DRenderMode; import flash.display3D.Context3DTextureFormat; import flash.display3D.Context3DVertexBufferFormat; import flash.display3D.IndexBuffer3D; import flash.display3D.Program3D; import flash.display3D.VertexBuffer3D; import flash.display3D.textures.Texture; import flash.events.Event; import flash.geom.Matrix3D; import flash.geom.Vector3D; import flash.utils.getTimer; import com.adobe.utils.AGALMiniAssembler; import com.adobe.utils.PerspectiveMatrix3D; import net.hires.debug.Stats; [SWF(width = "480", height = "270", frameRate = "60")] public class RasterScroll extends Sprite { [Embed(source = "RasterScroll.png")] private var imageEmbedClass:Class; private var context3D:Context3D; private var indexBuffer:IndexBuffer3D; private var projectionMatrix:PerspectiveMatrix3D = new PerspectiveMatrix3D(); private var modelMatrix:Matrix3D = new Matrix3D(); private var viewMatrix:Matrix3D = new Matrix3D(); private var modelViewProjection:Matrix3D = new Matrix3D(); private var phase:Number = 0; private var period:Number = Math.PI * 2; private var data:Vector.<Number>; public function RasterScroll() { stage.align = StageAlign.TOP_LEFT; stage.scaleMode = StageScaleMode.NO_SCALE; stage.stage3Ds[0].addEventListener(Event.CONTEXT3D_CREATE, context3DCreateHandler); stage.stage3Ds[0].requestContext3D(Context3DRenderMode.AUTO); addChild(new Stats()); } private function context3DCreateHandler(event:Event):void { context3D = (event.target as Stage3D).context3D; context3D.configureBackBuffer(stage.stageWidth, stage.stageHeight, 4); var vertexShader:AGALMiniAssembler = new AGALMiniAssembler(); vertexShader.assemble(Context3DProgramType.VERTEX, "m44 op, va0, vc0 \n" + "mov v0, va1" ); var fragmentShader:AGALMiniAssembler = new AGALMiniAssembler(); fragmentShader.assemble(Context3DProgramType.FRAGMENT, "mov ft0, v0 \n" + "add ft0.z, ft0.y, fc0.x \n" + // z = y + Phase "mul ft0.z, ft0,z, fc0.y \n" + // z *= Frequency "sin ft0.z, ft0.z \n" + // z = sin(z) "mul ft0.z, ft0.z, fc0.z \n" + // z *= Amplitude "add ft0.x, ft0.x, ft0.z \n" + // x += z "tex ft0, ft0, fs0 <2d,linear> \n" + "mov oc, ft0" ); var shaderProgram:Program3D = context3D.createProgram(); shaderProgram.upload(vertexShader.agalcode, fragmentShader.agalcode); context3D.setProgram(shaderProgram); var vertexBuffer:VertexBuffer3D = context3D.createVertexBuffer(4, 4); vertexBuffer.uploadFromVector(Vector.<Number>([ -1, -1, 0, 1, // x, y, u, v -1, 1, 0, 0, 1, 1, 1, 0, 1, -1, 1, 1 ]), 0, 4); context3D.setVertexBufferAt(0, vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_2); context3D.setVertexBufferAt(1, vertexBuffer, 2, Context3DVertexBufferFormat.FLOAT_2); indexBuffer = context3D.createIndexBuffer(6); indexBuffer.uploadFromVector(Vector.<uint>([ 0, 1, 2, 2, 3, 0 ]), 0, 6); var bitmapData:BitmapData = new imageEmbedClass().bitmapData; var texture:Texture = context3D.createTexture(bitmapData.width, bitmapData.height, Context3DTextureFormat.BGRA, false); texture.uploadFromBitmapData(bitmapData); context3D.setTextureAt(0, texture); projectionMatrix.perspectiveFieldOfViewRH(45 * Math.PI / 180, stage.stageWidth / stage.stageHeight, 1, 10); viewMatrix.appendTranslation(0, 0, -4); data = new Vector.<Number>(4, true); data[0] = phase; // Phase data[1] = 20; // Frequency data[2] = 0.05; // Amplitude data[3] = 0; stage.addEventListener(Event.ENTER_FRAME, render); } private function render(event:Event):void { data[0] = phase; phase += 0.01; if (phase >= period) phase -= period; modelMatrix.appendRotation(0.5, Vector3D.Y_AXIS); modelMatrix.appendRotation(0.5, Vector3D.Z_AXIS); modelViewProjection.identity(); modelViewProjection.append(modelMatrix); modelViewProjection.append(viewMatrix); modelViewProjection.append(projectionMatrix); context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, modelViewProjection, true); context3D.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, data); context3D.clear(); context3D.drawTriangles(indexBuffer); context3D.present(); } } }