Sponsored By
Christer Kaitila, Blogger

November 18, 2010

6 Min Read
Game Developer logo in a gray background | Game Developer

alternativa3d

Note: The source code on my blog is properly syntax highlighted.

Adobe's upcoming 3d Flash functionality is called "Molehill" and it allows true next-gen hardware accelerated 3d graphics that can rival Unity, Xbox and Playstation games.  You can read more about the power of Molehill in this article which includes several video examples that are sure to blow you away.

This article is an examination of the programming techniques required to get Molehill 3d graphics running in your Flash Actionscript3 projects.  Since Molehill has yet to be released, we can only prepare for the upcoming revolution in online gaming by studying the API as discussed in Adobe's lectures from their recent conferences. I have gone to the trouble of researching the Molehill API and am happy to present an overview of the AS3 programming techniques that will be used to get amazing 3d graphics in your Flash games.

Here is the source of my information - a lecture from the Adobe Max 2010 conference that is publicly available on the adobe website.  

///////////////////////////////////////////////
// Molehill Programming Example: INITS
// by Chris Kaitila aka Breakdance McFunkypants
// http://www.mcfunkypants.com
///////////////////////////////////////////////

///////////////////////////////////////////////
// INIT STEP ONE - create a rendering context:
///////////////////////////////////////////////

// the "auto" setting lets flash decide between
// openGL, directX and software rendering
context3D = new Context3D(Context3DRenderMode.AUTO);
// put this 3d view on the stage underneath any flash gui elements
stage.stage3Ds[0].attachContext3D(context3D);
// generally a game will only have one context3D
// but could have more than one viewport
stage.stage3Ds[0].viewPort = new Rectangle(0,0,688,528);
// set up the buffer for double buffered rendering
// each frame, you swap buffers for display
context3D.setupBackBuffer(688,528,1,true);

///////////////////////////////////////////////
// INIT STEP TWO - create a vertex and index buffer
///////////////////////////////////////////////

// buffers are created for each model in your game
// once you define a model this way you can render
// it as many times as you want in a single line of code
// in this example you define the buffer as
// six entries of three numbers (x,y,z) each
// but you can embed more info like rgba and
// uv texture coordinates as well...
vertexbuffer = context3D.createVertexBuffer(3,6);

// you only have to upload models once, during startup
// vertex buffers are lists of x,y,z points in space
// each vertex represents a "corner" in your 3d model
// in this example we use x,y,z,r,g,b (6 floats per vertex)
vertexbuffer.upload(
	Vector.<Number>(
	[-1,-1,0, 1,0,0, 0,1,0, 0.75,0.8,0.3, 1,-1,0, 0,0.5,0.9]
	),0,3); // start at offset 0, count 3

// index buffers are lists that define which verteces
// are used by which triangle, since multiple triangles
// can share the same vertex when they are touching
// in this example we define the buffer as 3 entries
indexbuffer = context3D.createIndexBuffer(3);
indexbuffer.upload(Vector.<uint>([0,1,2]),0,3);

///////////////////////////////////////////////
// INIT STEP THREE - create a vertex and fragment program
///////////////////////////////////////////////

// programs are essentially "shaders"
// and define how to draw each elements
// you send a string of assembly-language-like commands,
// and flash will compile them into efficient bytecode

// first compile the assembly language source for a vertex program
// this tells the renderer how to draw the shape (eg where)
// the opcode "m44" is short for a 4x4 transform matrix
var av:AGALMiniAssembler = new AGALMiniAssembler();
av.assemble(Context3DProgramType.VERTEX,
	"m44 op, va0, vc0\n mov v0, va1\n");

// then create a fragment program (a shader)
// which tells the renderer how to draw it (eg colour, texture)
var af:AGALMiniAssembler = new AGALMiniAssembler();
af.assemble(Context3DProgramType.FRAGMENT,
	"mov oc, v0");

// then upload the compiled bytecode to the 3d context
program = context3D.createProgram();
program.upload(av.agalcode, af.agalcode);

// ALL SETUP IS DONE!
// you only have to call the routines above ONCE.

That takes care the the initialization.  In three short steps you created a rendering context, set up a viewport, defined a model by uploading vertex data, and created a vertex and fragment program that tells the 3d engine how to handle this data for drawing.  Now you can use all this data during your render loop.  The amazing thing (and the reason that Molehill will be able to render hundreds of thousands of polygons in full screen resolution at a smooth 60 frames per second) is that you can upload tons of models with thousands of polies during the inits and render them below using only a couple lines of code.  In previous versions of flash you essentially have to re-send each polygon's data every single frame, resulting in thousands of inefficiently repeated draw calls each frame.  The new way "batches" this data for reuse in the same way that you would set up vertex objects in openGL or DirectX using C++.

///////////////////////////////////////////////
// Molehill Programming Example: RENDER LOOP
// by Chris Kaitila aka Breakdance McFunkypants
// http://www.mcfunkypants.com
///////////////////////////////////////////////

///////////////////////////////////////////////
// RENDER LOOP:
///////////////////////////////////////////////
// The following is an example what gets run EVERY FRAME:

// 1. clear the frame to solid black (r,g,b,a)
context3D.clear(0,0,0,1);

// 2. tell flash which program to use
// (which shader to use)
context3D.setProgram(program);

// 3. tell flash which vertex streams to use
// (which models to render)
context3D.setVertexStream(0,vertexbuffer,0,
	Context3DVertexFormat.FLOAT_3);
context3D.setVertexStream(1,vertexbuffer,3,
	Context3DVertexFormat.FLOAT_3);

// 4. set program constants
// send variables used by the programs that change every frame
// this is how you interface with your programs
// you can enable animations or colour changes this way
// or define vectors for use in shaders or lighting
// in this example, we tell the program where the model is
context3D.setProgramConstantsMatrix(
	Context3DProgramType.VERTEX, 0, mvpMatrix, true);

// 5. draw the model!
// this one line can render thousands of polygons in one fast call
// you would draw each model in your scene using calls like this
// you could draw the same model (eg a tree) multiple times
// in different locations for efficient use as props by changing
// the mvpMatrix using another setProgramConstantsMatrix call
// in this example we just draw one shape
context3D.drawTriangles(indexbuffer,0,1);

// 6. update the display
// do this once you have drawn all models you want rendered
// it will display the backbuffer that we just drew on
context3D.swap();

Naturally, since Molehill has not been released yet, this information is subject to change. More importantly, this functionality will not be available until mid-2011, at which time developers will be able to download a .SWC compiled flash file that they can include in their AS3 projects which exposes the Molehill beta API prior to release.  Until you have this beta SWC file, the code above will not compile in Flash.  Additionally, this is pseudocode: I haven't bothered to define every variable - please consider it only a general example of the techniques that you will be using to create next gen 3d flash games next year.

I will be posting more on this subject as Molehill approaches release.  Be sure to subscribe to my RSS feed if you wish to be notified when new articles are posted on my blog.  I also warmly encourage you to follow me on Twitter.  Thanks for your interest!

Read more about:

Featured Blogs
Daily news, dev blogs, and stories from Game Developer straight to your inbox

You May Also Like