テクスチャ座標を正弦関数を利用してずらす擬似ラスタースクロールを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();
}
}
}