Away3D and Starling interoperation
Since the introduction of Stage3D in Adobe AIR 3 and Flash Player 11, numerous ActionScript 3 frameworks have been introduced and others upgraded to take full advantage of the newfound GPU acceleration. Away3D is one of those frameworks now leveraging these GPU features allowing developers to create incredibly rich 3D interactive experiences. Starling, similarly, is another framework exploiting the power of Stage3D but is focused on providing GPU accelerated 2D graphics.
There have been requests from both the Starling and Away3D developer communities to be able to combine both 2D and 3D frameworks together in a single application. However, this required modification to the APIs themselves or to have each framework render in its own separate Stage3D instance. Unfortunately, along with a greater performance overhead, transparent Stage3D instances are currently unsupported so overlaying the instances obscures the instance beneath, destroying the desired effect.
With the release of Away3D 4.0 Gold and the latest Starling sources from Github, comes the ability to easily combine multiple frameworks into a single Stage3D instance. You can now layer any combination and any number of Away3D or Starling instances.
This tutorial will take you through an example of having a background Starling layer, a middle Away3D layer and a foreground Starling layer.
Initializing the shared Stage3D instance
Under normal operation, when either Away3D or Starling is being used individually, management of the Stage3D is handled internally within the respective framework. This internal management makes them extremely easy to use, but also causes difficulties in sharing the Stage3D instance. Instead, each framework needs access to a common Stage3D instance where all rendering will happen. This is done through the Stage3DManager
and Stage3DProxy
classes within the Away3D framework.
// Stage manager and proxy instances private var stage3DManager : Stage3DManager; private var stage3DProxy : Stage3DProxy; /** * Global initialise function */ private function init():void { stage.scaleMode = StageScaleMode.NO_SCALE; stage.align = StageAlign.TOP_LEFT; initProxies(); } /** * Initialise the Stage3D proxies */ private function initProxies():void { // Define a new Stage3DManager for the Stage3D objects stage3DManager = Stage3DManager.getInstance(stage); // Create a new Stage3D proxy to contain the separate views stage3DProxy = stage3DManager.getFreeStage3DProxy(); stage3DProxy.addEventListener(Stage3DEvent.CONTEXT3D_CREATED, onContextCreated); stage3DProxy.antiAlias = 8; stage3DProxy.color = 0x0; }
The Stage3DManager
is a singleton so to access it you have to explicitly request the singleton instance using thegetInstance()
method. Using the Stage3DManager
instance, you can make a request to allocate the next available Stage3D for your rendering by using the getFreeStage3DProxy()
method. Allocating the Stage3D is an asynchronous process and you must listen for a Stage3DEvent.CONTEXT3D_CREATED
event to know when it is complete.
Fortunately the getFreeStage3DProxy()
method returns a Stage3DProxy
instance which allows you set properties such as the overall anti-alias level and background color immediately.
Constructing the render layers
When the Stage3DEvent.CONTEXT3D_CREATED
event is fired, the Context3D and Stage3D have been successfully allocated to your application and you are ready to construct your layers for rendering.
In this example there is one Away3D scene and two Starling scenes. The Away3D scene renders five textured cubes in a cross formation above of a wire frame grid. The first Starling scene contains a rotating, gradient colored checker-board whilst the second Starling scene contains a simple particle effect. Ensure you are using at least Starling 1.2 as this contains the necessary code to allow sharing of the Stage3D instance.
private function onContextCreated(event : Stage3DEvent) : void { initAway3D(); initStarling(); initMaterials(); initObjects(); initButton(); initListeners(); initListeners(); } /** * Initialise the Away3D views */ private function initAway3D() : void { // Create the first Away3D view which holds the cube objects. away3dView = new View3D(); away3dView.stage3DProxy = stage3DProxy; away3dView.shareContext = true; hoverController = new HoverController(away3dView.camera, null, 45, 30, 1200, 5, 89.999); addChild(away3dView); addChild(new AwayStats(away3dView)); } /** * Initialise the Starling sprites */ private function initStarling() : void { // Create the Starling scene to add the checkerboard-background starlingCheckerboard = new Starling(StarlingCheckerboardSprite, stage, stage3DProxy.viewPort, stage3DProxy.stage3D); // Create the Starling scene to add the particle effect starlingStars = new Starling(StarlingStarsSprite, stage, stage3DProxy.viewPort, stage3DProxy.stage3D); }
The onContextCreated()
method performs a typical initialization process to define the 3D scene, objects, materials, event listeners and also the Starling setup.
In the initAway3D()
method, you construct the View3D
object as usual for an Away3D scene, however, you set itsstage3DProxy
property to your shared Stage3DProxy
instance and instruct the View3D to work with a shared Stage3D by setting shareContext
to true.
Similarly the initStarling()
method creates the Starling scenes. For each scene it is necessary to pass a reference to the Starling sprite scene, the stage and in the case of a shared Stage3D, you also need to pass a Rectangle
defining the size of the view port and a reference to your Stage3D instance. Both of these are accessible directly from theStage3DProxy
instance as viewPort
and stage3D
properties respectively.
Each Away3D scene and Starling sprite layer now has a reference to the shared Stage3D instance. The rest of the scene setup continues as normal. The complete demonstration in the zip file allows you to cycle through, swapping the layers around. Initially, the Starling layer is at the back (the first rendered layer) and rotates the checker-board pattern. On top of this is the 5 cube Away3D scene and finally, on the topmost layer, is the Starling particle effect.
Rendering the layers
When a Stage3D framework manages its own Stage3D instance, there are certain functions in the rendering process which prevent it from being shared. In an extremely simplified view, the rendering of a scene requires it to be cleared –clear()
, the elements rendered – drawTriangles()
and finally, displayed – present()
. It is this clearing anddisplaying performed by the frameworks that stop Stage3Ds being shared.
Now that Away3D and Starling have been instructed to use a shared Stage3D instance, they only need to consider the rendering part of the process, leaving the clearing and presenting responsibility to either you manually or theStage3DProxy
object.
There are two rendering options available through the Stage3DProxy
class which are very similar but provide different control of the clearing and presenting. The manual approach requires you to explicitly call the Stage3DProxy's clear()
and present()
methods around your layer rendering calls whereas the more automatic approach handles that for you.
Taking control – Manually
The manual approach to layered rendering with a shared Stage3D instance requires you to first call thestage3Dproxy.clear()
to clear and reset the back buffer for the shared Stage3D instance. You can then render each layer, starting with the background layers first and working to the foreground layer last, using either Away3D'sview.render()
method or Starlings starlingSprite.nextFrame()
method. Finally you need to callstage3Dproxy.present()
to complete the rendering to the back buffer for display.
/** * Set up the rendering processing event listeners */ private function initListeners() : void { stage.addEventListener(Event.ENTER_FRAME, onEnterFrame); } /** * The main rendering loop */ private function onEnterFrame(event : Event) : void { // Clear the Context3D object stage3DProxy.clear(); // Render the Starling animation layer starlingCheckerboard.nextFrame(); // Render the Away3D layer away3dView.render(); // Render the Starling stars layer starlingStars.nextFrame(); // Present the Context3D object to Stage3D stage3DProxy.present(); }
In the code above, the clearing, rendering and presenting are all performed inside a stage ENTER_FRAME
event handler, allowing you complete control of when each part of the rendering process will take place.
Taking control – Automatically
With the automatic approach, the Stage3DProxy instance performs the clear()
and present()
calls internally. To process the rendering calls, you need to add an ENTER_FRAME
event handler to the Stage3DProxy instance rather than to the stage instance. The rendering calls within this event handler are exactly the same as in the manual approach except that the clear()
and present()
calls are not made.
/** * Set up the rendering processing event listeners */ private function initListeners() : void { stage3DProxy.addEventListener(Event.ENTER_FRAME, onEnterFrame); } /** * The main rendering loop */ private function onEnterFrame(event : Event) : void { // Render the Starling animation layer starlingCheckerboard.nextFrame(); // Render the Away3D layer away3dView.render(); // Render the Starling stars layer starlingStars.nextFrame(); }
This approach saves you from having to make explicit calls to clear()
and present()
but still allows you to define the rendering order of your layers.
Where to go from here
In this tutorial, you learned how to combine multiple Stage3D frameworks, both 2D and 3D layers, into a single application and render those layers on top of one another.
Hopefully you see how easy it can be to build applications using the Away3D and Starling frameworks together, making full use of the GPU acceleration offered by Stage3D.
http://www.adobe.com/devnet/flashplayer/articles/away3d-starling-interoperation.html
You must Sign up as a member of Effecthub to view the content.
2652 views 1 comments
You must Sign up as a member of Effecthub to join the conversation.