Thursday, August 18, 2011

Molehill - Flash 11

Somehow, in the flurry of figthing to get N9 out, I missed Adobes latest big thing.

I have always loved pretty much everything adobe has been pushing out, but this one is just insane.

New Adobe Flash 11 will contain support for 3d acceleration, totally abstracted from opengl/DirectX/OpenGlES or lack of any acceleration.

Guys at Adobe have done outstanding job at abstracting the GPU acceleration to work the same on all platforms (MS, Linux, Osx, Mobile) - yet, you still get to code shaders all the same for all of them.

One of course immediately compares Stage3D to webgl and Silverlight 5. Silverlight 5 looks to me like a nice first try for MS. Webgl, while nice as an idea of pulling it all to browser itself, lacks the compatibility between browsers, and does not even try to protect code copying.

One of the most interesting, and perhaps odd things about the stage3d/molehill, is that adobe somehow resisted trying to crete their own development & design tools for 3d. It would have been a futile effort to do it the whole way from 3d object modelling to animation crafting in a way that pleases all, so they decided to stick with doing just the 3d abstraction layer and do it par none. Having been testing it a bit, I must applaud for job well done.

By not doing the toolset, they have in effect taken all existing adobe 3d engine creators to come onboard as well as converted some of the other engine developers like Unity. While Unity says this is not the end of their dedicated web based player, I don't see any reason why they would keep two competing implementations alive.

For Unity, you code your game with normal c#/javascript/boo, which gets converted to actionscript. These days scripts are mostly running game decision logic, and pretty much all of the heaevy lifting is done on shader programs. So, not a whole lot of perf is lost by sticking completely to actionscript.

For most of the other Stage3D based engines, it's business as usual, use maya/3dmax/whatever makes you tick to do the meshes and place the textures, use the 3d game RAD tool to get it all together and actionscript to control it all.

Let me give you and example of how the code looks for a simple triangle with color slides between the vertices between the three competitors:

WebGl (note that I have dropped shader creation completely -> read from source) source : Source

triangleVertexPositionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexPositionBuffer);
var vertices = [
0.0, 1.0, 0.0,
-1.0, -1.0, 0.0,
1.0, -1.0, 0.0
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
triangleVertexPositionBuffer.itemSize = 3;
triangleVertexPositionBuffer.numItems = 3;

triangleVertexColorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexColorBuffer);
var colors = [
1.0, 0.0, 0.0, 1.0,
0.0, 1.0, 0.0, 1.0,
0.0, 0.0, 1.0, 1.0
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);
triangleVertexColorBuffer.itemSize = 4;
triangleVertexColorBuffer.numItems = 3;
//Shader creation
//--> Read from the source, it's far too long to express here

Ms Silverlight 5 Source Full source :

vertexBuffer = CreateTriangle();

// Shader creation:
Stream shaderStream = Application.GetResourceStream(new Uri(@"TriangleSample;component/Triangle.vs", UriKind.Relative)).Stream;
vertexShader = VertexShader.FromStream(resourceDevice, shaderStream);

shaderStream = Application.GetResourceStream(new Uri(@"TriangleSample;component/", UriKind.Relative)).Stream;
pixelShader = PixelShader.FromStream(resourceDevice, shaderStream);

//Vertex buffer
var vertices = new VertexPositionColor[3];
vertices[0].Position = new Vector3(-1, -1, 0); // left
vertices[1].Position = new Vector3(0, 1, 0); // top
vertices[2].Position = new Vector3(1, -1, 0); // right
vertices[0].Color = new Color(255, 0, 0, 255); // red
vertices[1].Color = new Color(0, 255, 0, 255); // green
vertices[2].Color = new Color(0, 0, 255, 255); // blue

// create graphics device managed buffer
var vb = new VertexBuffer(resourceDevice, VertexPositionColor.VertexDeclaration,
vertices.Length, BufferUsage.WriteOnly);

// copy vertex data to graphics device buffer
vb.SetData(0, vertices, 0, vertices.Length, 0);

Adobe Flash Stage3D Source :

//Shader creation
context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, modelMatrix, true );

var vertexShaderAssembler : AGALMiniAssembler = new AGALMiniAssembler();
vertexShaderAssembler.assemble( Context3DProgramType.VERTEX,
"m44 op, va0, vc0 \n" + // 4x4 matrix transform from stream 0 (vertex position) to output clipspace
"mov v0, va1 \n" // copy stream 1 (vertex color) to fragment shader

var fragmentShaderAssembler : AGALMiniAssembler= new AGALMiniAssembler();
fragmentShaderAssembler.assemble( Context3DProgramType.FRAGMENT,"mov oc, v0);" // output color

//Vertex buffer
vertexbuffer.uploadFromVector ( Vector.([
4.-1,-1,0, 255/255,0,0, // red
5.0,1,0, 193/255,216/255,47/255, // green
6.1,-1,0, 0,164/255,228/255 // blue
7.]),0, 3 ); // start at offset 0, count 3

context3D.setVertexBufferAt( 1, vertexbuffer, 3,Context3DVertexBufferFormat.FLOAT_3 );

What I find interesting is that at the same time, Stage3d example code may look a bit more complex than the other, but that's the efficiency and concise presentation talking.

Silverlight stays the most readable of them all, but mostly because shader program is in separate file.

I think this is the new platform that games developers for facebook and mobile will embrace. It will be the basis of new wave of creative coding frameworks, ditching openframeworks and alike.

While also silverlight 5 seems to have a nice home for indie game development for 360+WP7/8, I don't believe it to have as significant impact on gaming as a whole as Stage 3d from adobe will.

I'm in awe.

Now, take a look at how Adobe presents this:

Don't mind about how "very very exciting it is"

If you want a hands on, try the max racer yourself:

First install Flash 11 Beta, then open the game.