Skip to content

Instantly share code, notes, and snippets.

@Nutrox
Created March 8, 2011 02:37
Show Gist options
  • Save Nutrox/859749 to your computer and use it in GitHub Desktop.
Save Nutrox/859749 to your computer and use it in GitHub Desktop.
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