Created
March 8, 2011 02:37
-
-
Save Nutrox/859749 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package { | |
import com.adobe.utils.AGALMiniAssembler; | |
import flash.display.Bitmap; | |
import flash.display.Loader; | |
import flash.display.MovieClip; | |
import flash.display.Sprite; | |
import flash.display.StageAlign; | |
import flash.display.StageQuality; | |
import flash.display.StageScaleMode; | |
import flash.display3D.Context3D; | |
import flash.display3D.Context3DBlendFactor; | |
import flash.display3D.Context3DCompareMode; | |
import flash.display3D.Context3DProgramType; | |
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.Rectangle; | |
import flash.utils.ByteArray; | |
// | |
public class MolehillTest03B extends Sprite { | |
// Empty dual-frame SWF used instead of an ENTER_FRAME listener | |
[Embed( source="ticker.swf", mimeType="application/octet-stream" )] | |
private var TickerBytes:Class; | |
// 32x32 texture | |
[Embed( source="texture.png" )] | |
private var TextureBytes:Class; // actually a Bitmap object, not a ByteArray | |
// | |
private var ticker:Loader; | |
private var context:Context3D; | |
private var program:Program3D; | |
private var texture:Texture; | |
private var vertexShader:ByteArray; | |
private var fragmentShader:ByteArray; | |
private var vertexBuffer:VertexBuffer3D; | |
private var indexBuffer:IndexBuffer3D; | |
private var matrix:Vector.<Number>; | |
private var vertices:Vector.<Number>; | |
private var indices:Vector.<uint>; | |
private var viewport:Rectangle; | |
// This cannot be greater than 64000, the maximum number of | |
// vertices a single vertex buffer can hold | |
private const NUM_SPRITES:uint = 64000; | |
// These should match the texture size for this demo | |
private const SPRITE_WIDTH:Number = 32; | |
private const SPRITE_HEIGHT:Number = 32; | |
// | |
public function MolehillTest03B() { | |
stage.align = StageAlign.TOP_LEFT; | |
stage.quality = StageQuality.LOW; | |
stage.scaleMode = StageScaleMode.NO_SCALE; | |
stage.frameRate = 60; | |
stage.mouseChildren = false; | |
// The viewport in this demo will be the same size as the stage | |
viewport = new Rectangle( 0, 0, stage.stageWidth, stage.stageHeight ); | |
// Load the ticker SWF | |
ticker = new Loader(); | |
ticker.contentLoaderInfo.addEventListener( Event.INIT, onTickerInit ); | |
ticker.loadBytes( new TickerBytes() ); | |
} | |
// | |
private function onTickerInit( event:Event ):void { | |
ticker.contentLoaderInfo.removeEventListener( event.type, onTickerInit ); | |
// Request a new Context3D object, this might take a second or two | |
stage.stage3Ds[0].addEventListener( Event.CONTEXT3D_CREATE, onContextCreated ); | |
stage.stage3Ds[0].requestContext3D(); | |
} | |
// | |
private function onContextCreated( event:Event ):void { | |
stage.stage3Ds[0].removeEventListener( event.type, onContextCreated ); | |
// Grab a reference the context, and set the viewport | |
context = stage.stage3Ds[0].context3D; | |
stage.stage3Ds[0].viewPort = viewport; | |
// Initialize things | |
initialize(); | |
// Link the update() method to the ticker SWF frames | |
MovieClip(ticker.content).addFrameScript( 0, update, 1, update ); | |
} | |
// | |
private function initialize():void { | |
// Only enable error checking during development/testing (it is quite slow) | |
context.enableErrorChecking = true; | |
// The size of back buffer will normally match the size of the viewport | |
context.configureBackBuffer( viewport.width, viewport.height, 0, false ); | |
// Blend alpha channels | |
context.setBlendFactors( Context3DBlendFactor.SOURCE_ALPHA, Context3DBlendFactor.ONE_MINUS_SOURCE_ALPHA ); | |
// No depth tests are required for 2D painting | |
context.setDepthTest( false, Context3DCompareMode.ALWAYS ); | |
// Create the vertex and index buffers | |
vertexBuffer = context.createVertexBuffer( NUM_SPRITES, 4 ); // XYUV = 4 32-bit values | |
indexBuffer = context.createIndexBuffer( NUM_SPRITES * 6 ); // 6 indices per sprite | |
var agal:AGALMiniAssembler = new AGALMiniAssembler(); | |
// Create the vertex shader | |
vertexShader = agal.assemble( | |
Context3DProgramType.VERTEX, | |
"m44 op, va0, vc0 \n" + | |
"mov v0, va1 \n" | |
); | |
// Create the fragment shader | |
fragmentShader = agal.assemble( | |
Context3DProgramType.FRAGMENT, | |
"tex ft0, v0, fs0 <2d,clamp,linear> \n" + | |
"mov oc, ft0" | |
); | |
// Create the program and assign the shaders to it | |
program = context.createProgram(); | |
program.upload( vertexShader, fragmentShader ); | |
// Register the program with the context | |
context.setProgram( program ); | |
// Create the texture | |
texture = context.createTexture( | |
SPRITE_WIDTH, SPRITE_HEIGHT, Context3DTextureFormat.BGRA, true | |
); | |
texture.uploadFromBitmapData( Bitmap(new TextureBytes()).bitmapData ); | |
// Register the texture ( fs0, used by the fragment shader ) with the context | |
context.setTextureAt( 0, texture ); | |
// Create the projection matrix ( vc0 ) and register it with the vertex shader | |
var x:Number = 2/viewport.width; | |
var y:Number = -2/viewport.height; | |
matrix = Vector.<Number>([ | |
x, 0, 0,-1, | |
0, y, 0, 1, | |
0, 0, 1, 0, | |
0, 0, 0, 1 | |
]); | |
context.setProgramConstantsFromVector( Context3DProgramType.VERTEX, 0, matrix ); | |
// Create the sprite vertices and indices, they will all initially be placed at | |
// the top-left of the viewport, but the update() method randomizes their positions | |
vertices = new Vector.<Number>(); | |
indices = new Vector.<uint>(); | |
var w:Number = SPRITE_WIDTH; | |
var h:Number = SPRITE_HEIGHT; | |
var p:Number; | |
var i:int = -1; | |
var n:int = NUM_SPRITES; | |
while( ++i < n ) { | |
vertices.push( | |
0,0,0,0, w,0,1,0, w,h,1,1, 0,h,0,1 | |
); | |
p = i * 4; // 4 = number of vertices per sprite | |
indices.push( | |
p,p+1,p+2, p,p+2,p+3 | |
); | |
} | |
// Register the vertex position ( va0 ) and UV coords ( va1 ) with the vertex shader | |
context.setVertexBufferAt( 0, vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_2 ); | |
context.setVertexBufferAt( 1, vertexBuffer, 2, Context3DVertexBufferFormat.FLOAT_2 ); | |
// Upload the indices, this only needs to be done once for this | |
// demo because the vertex list is not modified, only the vertex | |
// properties are changed | |
indexBuffer.uploadFromVector( indices, 0, NUM_SPRITES ); | |
} | |
// | |
private function update():void { | |
// Clear the buffer | |
context.clear( 0, 0, 0, 1 ); | |
// Randomize the position of one sprite | |
var x:Number = viewport.width * Math.random(); | |
var y:Number = viewport.height * Math.random(); | |
var i:int = NUM_SPRITES * Math.random() >> 0; | |
var p:int = i << 4; | |
vertices[p+00] = x; | |
vertices[p+01] = y; | |
vertices[p+04] = x+SPRITE_WIDTH; | |
vertices[p+05] = y; | |
vertices[p+08] = x+SPRITE_WIDTH; | |
vertices[p+09] = y+SPRITE_HEIGHT; | |
vertices[p+12] = x; | |
vertices[p+13] = y+SPRITE_HEIGHT; | |
// Upload the vertices | |
vertexBuffer.uploadFromVector( vertices, 0, NUM_SPRITES ); | |
// Draw the triangles | |
context.drawTriangles( indexBuffer ); | |
// Push the buffer to the screen | |
context.present(); | |
} | |
}// EOC | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment