Getting Started with StageGL

Recently, we announced a public preview of StageGL, which offers a new way to create blazingly fast experiences with EaselJS. StageGL focuses on content that WebGL excels at rendering while being almost entirely compatible with the familiar EaselJS Stage.

StageGL was designed to be a drop-in replacement for the Stage class and supports most EaselJS content with little to no change. Grab any samples or projects, and switch out the Stage for a StageGL instance; at minimum that’s all you have to do!

// Regular 2d Canvas content
var stage = new createjs.Stage("canvasId");

// StageGL Canvas content
var stage = new createjs.StageGL("canvasId");

If you’re not seeing anything, or it doesn’t look quite right, read on!

We’re going to assume you’re familiar with EaselJS basics in this article. If you’re not, check out the getting started guide and return to this article when you’re done.

Common Questions

The five most common issues that you may encounter on your first run with StageGL are:

Let’s explore each of these:

I don’t see Shapes or Text

WebGL is designed for displaying raster (bitmap) and polygon data, but Shape and Text elements are made up of vector data. The easiest way to turn it into something we can use is to rasterize it using the cache command.

A demo showing both caching and without caching

See the Pen CreateJS: StageGL Background Color by CreateJS (@createjs) on CodePen.31824

Caching draws an image into a reusable texture. Once cached shapes and text will show up just fine. To read more about caching, and how to optimize cache for StageGL, check out the online documentation.

I don’t see Bitmaps

The two common cases for the bitmaps not being visible are loading and Cross-Origin issues. For loading issues, you can follow the same steps that work for a regular Stage. While having the error with your Stage before you swapped in a StageGL is likely, it’s not guaranteed.

A demo showing some simple preloading

See the Pen CreateJS: StageGL Simple Bitmap by CreateJS (@createjs) on CodePen.31824

If preloading isn’t helping or your console has a Cross-Origin error, then you’re potentially loading content incorrectly across domains (CORS). Put simply, you cannot do WebGL development without some form of server, be it local or remote. The simplest solution is a local server such as MAMP or XAMPP. Compile tools like Gulp and Grunt also have tasks with local server functionality (like BrowserSync). There is even a one-line command for a local server on OS X.

My background is grey

The StageGL default is an opaque grey background. Transparent backgrounds are surprisingly expensive to render, and considering most content will draw its own background, an opaque default is best for everyone. But that doesn’t work for every situation, so there’s a simple API to change it up.

To control the background color, change the clear color. It only supports a solid color, anything complex like a gradient or an image should be created like any other content in the display list.

A demo showing a colored background

See the Pen CreateJS: StageGL Color Background by CreateJS (@createjs) on CodePen.31824

Enabling background transparency occurs when creating the stage. Inside of the options object, set the “transparent” property to true.

A demo showing a transparent background

See the Pen CreateJS: StageGL Transparent Background by CreateJS (@createjs) on CodePen.31824

 

Note that transparent stages will be considerably less performant.

I don’t like the image quality

By default, WebGL can appear pixelated or jagged, changing this requires specific content. Firstly all your image sources need to be square and have dimensions which are Power-of-Two (1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, etc). Secondly, we need to set the “antialias” property to true when creating the stage.

var stage = new createjs.StageGL("canvasID",{ antialias: true });

With both of these in place, your image aliasing quality will go from “nearest neighbor” to “linear” and look much more like a standard canvas.

Antialiasing with power-of-two images

WebGL only knows how to work best with Square-Power-of-Two (SPOT) textures. WebGL 2.0 is going to do away with this restriction, but for now, StageGL is designed for the current standard. Support for 2.0 will be added in the future when the spec matures.

Notes:

  • Turning on antialiasing with StageGL doesn’t mean your textures have to be SPOT; however, you won’t notice consistent smoothing quality increases without it, despite the slight performance cost.
  • Just because your image source is square, doesn’t mean your art has to be. Using SpriteSheets and Bitmap.sourceRect allows you keep your display objects at any size while your sources fit the more specific SPOT requirements.

Things are in the wrong place when I resize

If the entire drawing area is misshapen or misaligned it’s because WebGL has the wrong size. An updateViewport call will fix it, try commenting it out in the pen below. While adjusting the size on resize is necessary, the visible size doesn’t have to match the provided size, i.e. showing a 400px wide canvas in 200px. This can reduce blurring on retina (up-scale), or increase performance (down-scale).

A demo showing a responsive layout

See the Pen CreateJS: StageGL Stage Resize by CreateJS (@createjs) on CodePen.31824

Note: You may have done canvas scaling using CSS and DOM properties with a context2D canvas. While this will work for the initial display, after that point updating the canvas element’s width and height properties will not adjust the drawing area, always use updateViewport to control the drawing area.

Conclusion

Those are the basics for your first time out with StageGL. There’s plenty more complex topics like advanced memory management, custom filters, and optimization – and we hope to cover those in the future.

Get the latest StageGL today code from GitHub. StageGL is now a standard part of the EaselJS minified library, so no need to include it separately. A new version of all the libraries for the CDN that includes StageGL is imminent. Stay tuned!

Common Questions

Below are a few more answers to common questions. If you have your own, feel free to add them in the comments.

WebGL… that means I can do things in 3D now, right?
Unfortunately not. EaselJS is not a 3D library, nor does it have any intention of being so. In fact, bypassing several of the complications of 3D rendering is what allows StageGL to be so fast. If you’re looking for a 3D library; ThreeJS and BabylonJS are both excellent choices. Don’t be afraid to employ EaselJS for making dynamic textures to use with them!

What browsers/OSes support StageGL?
All the modern ones! Very few browsers at this point in time don’t support the APIs we use. To give a more detailed answer look at websites like caniuse.com. There are no other dependencies, so if you can use WebGL, you can use StageGL. If you’re having issues running StageGL but WebGL works fine, let us know.

My project works just fine with a Stage, why do I need StageGL?
Better performance, and the ability to do more with that free power you’ve just generated! Or simply reduce the battery usage of your site on mobile devices. By splitting demands on the system across the processor and the graphics card, you’re much less likely to be bottlenecked and can create better experiences.

Is there anything mobile-specific I should know?
You probably shouldn’t make your textures bigger than 2048×2048. Each graphics card has its own capabilities, but between mobile graphics cards and desktop graphics cards there can be a substantial power/capability discrepancy. If you go past the maximum texture size of the card, the texture simply won’t render (StageGL should surface an error). Most mobile devices standardize at about 2048×2048, where I’ve seen laptops capable of 16384×16384.

Does StageGL work with Adobe Animate exports?
Currently there’s no direct StageGL export option from Animate, but you can convert or use Animate content with StageGL with just a little effort. Just remember the rules above, switch your Stage in the exported HTML to a StageGL instance, and remember to cache your Shape / Text objects. Objects exported from Animate will often include a “nominalBounds” property, which is a great source for the dimensions you should use to cache an object. Other than that, Animate content should be identical to handwritten content. Here is a simple example.

Can I mix StageGL with regular Stage content?
You can not blend a Stage and StageGL using the same canvas. Common approaches to blend the two content types is to either use separate canvases for each stage (preferably with the WebGL opaque canvas in the background), or to use caching to bring unsupported content into StageGL. Note that if you are using separate canvases, StageGL supports the nextStage property to shuttle mouse events between stages.

18 thoughts on Getting Started with StageGL

  1. Pingback: Getting Started with StageGL – Javascript World

    • We haven’t tagged a new version to send to Adobe yet — and chances are good it will have to be turned on manually (since we can’t support vector content in StageGL yet). Once the next version is released (currently testing a candidate), it will get sent to Adobe and the CDN.

    • It will depend on what your stage contents contain. StageGL only supports Bitmap content, so any vectors, including masks will not render. Hope that offers some insight.

  2. Hm… Just tested out the new stageGL on a complete project that works on stage.
    And i see to get “random” errors with sprites. StageGL randomly stops rendering some sprites. Console says the following (vocalDebug):

    NPOT(Non Power of Two) Texture: canvas_139
    NPOT(Non Power of Two) Texture: canvas_140

    // also randomly i get this one
    Error: WebGL warning: drawArrays: This operation requires zeroing texture data. This is slow

    As far as i know all modern GPUs can handle NPOT easily, it even doesn’t affect performance almost at all.
    And the weird thing is that some sprites that are NPOT are rendering successfully, whereas others NPOTs don’t. Any ideas what’s going on?

    ps: i got about 2500-3000 images/sprites

    • We can handle NPOT textures just fine, the warning is because of smoothing issues. We’re using WebGL, which is based on OpenGL-ES2. This means that we’re actually restricted from the full power of a modern graphics card by an older interface, it’s why we’re excited for WebGL 2.0.

      Regardless, being NPOT or not shouldn’t affect anything. Except maybe the smoothing of some of the images. The texture data error you’re randomly getting is more likely to be the culprit here.

      That error is basically saying that the the drawing of the StageGL content is outpacing the rate the texture is being loaded to the graphics card. This, combined with the fact that you’re saying some images are randomly not showing up, is making me think that you’re dynamically caching lots of objects? or loading lots of textures? and they’re not making it to the GPU in time for your draw commands.

      A fix might be to update your caches less or to use less static images. Maybe even as a debug step to see if I’m right. If you are outpacing the graphics card, this is one of the times when the variety in hardware is going to require you to reign in your design a little bit unfortunately.

      If you can share with us any example code and/or details on devices which have reproductions of the actual error, that would be great. Then I can see if there’s anything I can actually do to solve or bypass this problem. Lower level APIs like WebGL are a little trickier to work with so thanks for your patience.

      • Here’s a very simplified demo https://jsfiddle.net/7dmv8ujv/
        In my project i got dozens of those kinda entities and many cached shapes (constantly dynamically draw world backgrounds using bitmapFill).
        And i also made a video of this weird behaviour: https://youtu.be/46oxSQ2FoVw

        Video: those running guys are both instances of a same class (see the simplified demo Entity), both use same preloaded spritesheets for animations. But one gets rendered, the other one – does not. And this is random. Sometimes they render both, sometimes the they dont render both.
        – – – –
        Specs:
        FireFox 56.0.1 (64-bit)
        Windows 10 Pro 64-bit CPU
        Intel Core i5 4570 @ 3.80GHz Haswell 22nm Technology
        RAM 16,0GB Dual-Channel DDR3 @ 799MHz (11-11-11-28)
        Motherboard ASUSTeK COMPUTER INC. Z87-A (SOCKET 1150)
        2047MB NVIDIA GeForce GTX 660 (MSI)

      • Ok, so i’ve spend the whole day debugging StageGL source and i managed to figure out what was going on.
        Here’s a working code with the bug: https://jsfiddle.net/82orwe2L/1/
        – – –
        In short:
        StageGL can’t handle multiple images assigned to a single texture.
        – – –
        There are 2 solutions to this issue, both are described in code above.
        I would implement them both.

        • Thanks for your work and input on this. While the snippet is calling private functions the average user won’t call, I see what it’s driving at and how to duplicate the problem in regular behavior. That’s definitely behavior we want to support. I can see where the issue is coming from. I’m going to spend some time trying to figure out the best fix for this. #2 is definitely a fix, but performance and other considerations means I have a few things to try before adopting something like it directly. Apologies for the issues.

          • Yey! Glad i could be of help. Yep, #2 is definitely not the best performance-wise solution, though it (just like the calling of private methods) was just to separate the weird rendering and help u take a look into it.

            As my project is in production, i refactored my code to use #1 — singleton ImageCache class that has a hash for all images mapped url:Image + precalculation off all spritesheets, replacing all url occurrences so that they point to a single cache Image instance, before using in sprites.

            Cheers.

Leave a Reply

Your email address will not be published. Required fields are marked *

© Copyright 2017