This tutorial shows the current best practises for initializing Flash 11 Stage3D (Molehill) graphics in a way that is error tolerant and gracefully handles problems setting up 3d rendering. This code is from my book, Adobe Flash 11 Stage3D (Molehill) Game Programming Beginner’s Guide.
Now that Flash 11 is about to go mainstream and everyone’s computer will be able to deliver next-gen hardware accelerated 3d graphics in a web page, coders are pretty excited to dive in and start making some cool stuff.
As you can imagine, many users are running ancient computers, including old netbooks that aren’t capable of Shader 2.0 in the GPU. Others might have their Flash settings improperly configured. Others still will be running the stale old Flash 10 for some time. Finally, some game portals might forget that Stage3D can only be run on the video hardware if the HTML embed contains WMODE=DIRECT.
In all these cases, 3d graphics will either not work at all or will be rendered by the CPU, using software emulation. This will deliver terrible, unplayably bad performance and will make your game look bad.
We need to detect these instances and tell the user about them. Instead of crashing or an ugly and frightening error message, we can gracefully detect when our Flash 11 3d Molehill games are not going to work and tell the user how to fix the problem. Here’s how.
//
// Stage3D - Init Tutorial
// by http://www.mcfunkypants.com
// Gracefully detects when running in software mode
// or old versions of the Flash player
//
package
{
[SWF(width="640", height="480", frameRate="60",
backgroundColor="#FFFFFF")]
import flash.system.System;
import flash.system.Capabilities;
import flash.system.ApplicationDomain;
import flash.display.*;
import flash.display3D.*;
import flash.display3D.textures.*;
import flash.events.*;
import flash.geom.*;
import flash.utils.*;
import flash.text.*;
import com.adobe.utils.*;
public class Stage3dGame extends Sprite
{
// used to politely tell users about problems
private var titlescreenTf:TextField;
// etc..
While we’re at it, lets use AS3 best practises and wait for the stage to appear, just in case it our flash is using a preloader, etc..
public function Stage3dGame()
{
if (stage != null)
init();
else
addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
if (hasEventListener(Event.ADDED_TO_STAGE))
removeEventListener(Event.ADDED_TO_STAGE, init);
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
// add some text labels
initGUI();
You already know how to add textfields to the stage, so we aren’t going to bother with the contents of initGUI() right now. Do it yourself. This tutorial will focus exclusively upon detecting Stage3D init problems. Continuing with our init() function:
// are we running Flash 11 with Stage3D available?
var stage3DAvailable:Boolean =
ApplicationDomain.currentDomain.hasDefinition
("flash.display.Stage3D");
if (stage3DAvailable)
{
stage.stage3Ds[0].addEventListener(
Event.CONTEXT3D_CREATE, onContext3DCreate);
// detect when the swf is not using wmode=direct
stage.stage3Ds[0].addEventListener(
ErrorEvent.ERROR, onStage3DError);
// request hardware 3d mode now
stage.stage3Ds[0].requestContext3D();
}
else
{
trace("stage3DAvailable is false!");
titlescreenTf.text =
'Flash 11 Required.\nYour version: '
+ Capabilities.version
+'\nThis game uses Stage3D.'
+'\nPlease upgrade to Flash 11'
+'\nso you can play 3d games!';
}
}
In the code above we first ask Flash if it has heard of the Stage3D class. If not, then we must be running an older version of Flash. In that case we simply tell the user they need to upgrade to Flash 11.
If we are running Flash 11, the next step is to request a Context3D and listen for any errors. We set up two event listeners and are done with the init() function.
If the user has Flash 11 but for some reason we cannot get a hardware accelerated Context3D, we need to tell the user about it. Nobody wants to be running in software mode. This can happen when the HTML embed doesn’t use WMODE=DIRECT or if hardware 3d is turned off in the Flash settings.
Additionally, really old graphics cards are not supported. The list of old graphics cards that do NOT work with Flash 11
From (http://kb2.adobe.com/cps/921/cpsid_92103.html)
All Platforms
Any GPU that doesn’t support Pixel Shader version 2.x or above
Intel GMAs that DON’T support Pixel Shader 2.x: 740, i752, IEG, IEG2, GMA 900, GMA 950, GMA 3000, GMA 3100, GMA 3150
Chrome VIA Chipset
Windows
Any graphics driver older than January 1, 2009
NVIDIA driver 8.17.11.9621
NVIDIA driver 8.17.11.8267
Any Intel GMA driver before X.X.10.2021
Macintosh
All Intel GMAs
ATI Radeon X1600
ATI Radeon 2400
Firefox 3.6 and earlier
Mac OS X 10.5 or earlier
// this error is fired if the swf is not using wmode=direct
private function onStage3DError ( e:ErrorEvent ):void
{
trace("onStage3DError!");
titlescreenTf.text = 'Embed Error Detected!'
+'\nYour Flash 11 settings'
+'\nhave hardware 3D turned OFF.'
+'\nIs wmode=direct in the html?'
+'\nExpect poor performance.';
}
If all goes well and we do get a proper 3d context, the onContext3DCreate event will be fired. Let’s handle it.
private function onContext3DCreate(event:Event):void
{
// Remove existing frame handler. Note that a context
// loss can occur at any time which will force you
// to recreate all objects we create here.
// A context loss occurs for instance if you hit
// CTRL-ALT-DELETE on Windows.
// It takes a while before a new context is available
// hence removing the enterFrame handler is important!
if (hasEventListener(Event.ENTER_FRAME))
removeEventListener(Event.ENTER_FRAME,enterFrame);
// Obtain the current context
var t:Stage3D = event.target as Stage3D;
context3D = t.context3D;
if (context3D == null)
{
// Currently no 3d context is available (error!)
trace('ERROR: no context3D - video driver problem?');
return;
}
// detect software mode (html might not have wmode=direct)
if ((context3D.driverInfo == Context3DRenderMode.SOFTWARE)
|| (context3D.driverInfo.indexOf('oftware')>-1))
{
//Context3DRenderMode.AUTO
trace("Software mode detected!");
titlescreenTf.text = 'Software Rendering Detected!'
+'\nYour Flash 11 settings'
+'\nhave hardware 3D turned OFF.'
+'\nIs wmode=direct in the html?'
+'\nExpect poor performance.';
}
// if this is too big, it changes the stage size!
titlescreenTf.text = 'Flash 11 Stage3D '
+'(Molehill) is working perfectly!'
+'\nFlash Version: '
+ Capabilities.version
+ '\n3D mode: ' + context3D.driverInfo;
// Disabling error checking will drastically improve performance.
// If set to true, Flash sends helpful error messages regarding
// AGAL compilation errors, uninitialized program constants, etc.
context3D.enableErrorChecking = false;
CONFIG::debug
{
context3D.enableErrorChecking = true; // v2
}
// The 3d back buffer size is in pixels
context3D.configureBackBuffer(swfWidth, swfHeight, 0, true);
// Initialize our mesh data
initData();
// assemble all the shaders we need
initShaders();
// start animating
addEventListener(Event.ENTER_FRAME,enterFrame);
}
The initData and initShaders functions are left as an exercise to the reader. Once you get past the line above you can rest assured that your players are running Flash 11 and have proper hardware accelerated 3d graphics at the ready.
Upload some textures, compile some AGAL shaders, tell Molehill about your fancy mesh data and start an ENTER_FRAME render loop however you wish to. These techniques are explained in full in my Flash 11 Stage3D book if you want more detail. The purpose of this blog post is to simply show the current “best practises” regarding Stage3D inits. Enjoy!
Here’s a demo. On the top left is some text that tells you what version of Flash you’re running, whether or not you are in software mode, and what the current framerate is.
The Flash above should be running in hardware accelerated 3d at a full 60fps.
Just for fun, the example below shows what the exact same .SWF file looks like when forced to use software rendering. We could allow the demo to run in software mode but for games this is generally not acceptable and it is better to simply display an error message. The choice is yours: Flash 11 does have a near-perfect software emulation mode if you don’t care about framerate and just want it to work on every possible system.

Pingback: Flash11 Stage3D Tutorial: handling init errors | Indie Game … | www.mawir.net
Pingback: Flash11 Stage3D Tutorial: handling init errors | Indie Game … | SWF & iPad
Pingback: Flash11 Stage3D Tutorial: handling init errors | Indie Game … | Flash | Adobe-Tutorial.com
Hey Chris good stuff. What’s the latest on the book release date?
says:
Great news! The book is available for pre-order right now! If you purchase it now (at a discount) you get the rough copy (“raw” edition) immediately plus the full version for free when it is ready – which will be in a couple weeks max.
Pingback: Stage3D developer tips #3 | Flash Developer Diary | Scoop.it
says:
Hello Chris,
This is a little off-topic, but I’m out of ideas and I can’t seem to find an answer anywhere. I’m using your code (I also have the RAW book), and it works fine in all types of project except mobile ones. I’m not getting any errors, but my stage3Ds[0] is offset for some reason (although I’m setting its x & y at 0, 0) and smaller (should fill the screen). Here’s a print screen of the output. The green area is context3D.clear(0, 1, 0). The rest is supposed to be a blue 2D Sprite with alpha 0.2, but the 3D seems to affect it somehow.
I should also mention that I can load models with textures in the green area. I have tried both with AIR SDK 3.0 & 3.1, same result…
Thank you,
Ana
says:
Hi Ana,
It is hard to help without looking at your source code, but here are a few suggestions that, with fingers crossed, may point you in the right direction. Firstly, is your stage set to stage.scaleMode = StageScaleMode.NO_SCALE; and stage.align = StageAlign.TOP_LEFT; secondly are you telling your context3D.configureBackBuffer(stage.width, stage.height, 2, true); and thirdly could your stage3d have a different registration point origin? Fourthly, is your swf width and height set in code [SWF(width="640", height="480", frameRate="60", backgroundColor="#FFFFFF")] as well as in your project options and AIR descriptor xml etc?
Best of luck and let me know if you solve the problem!
says:
Hello Chris,
I finally discovered that the problem was the mobile fullscreen handling. After setting false in the application xml, everything works fine.
However I think it is an issue that should be resolved. After all, if we’re making a 3D game for mobile platforms, we’d probably want it to run in fullscreen mode.
In any case, thank you very much for your reply!
Best wishes,
Ana
Pingback: Molehill Programming Tutorial | Indie Game Developer Breakdance McFunkypants