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.
Update: CreateJS 1.0.0 has been released, and is available on the CDN!
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!
Common Questions
The five most common issues that you may encounter on your first run with StageGL are:
- I don’t see my Shape or Text elements
- I don’t see my Bitmap, Bitmap Text, or Sprite elements
- My background is grey
- I don’t like the image quality
- Things are in the wrong place when I resize
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
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.
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.
Pingback: Getting Started with StageGL – Javascript World
Great entry! thanks a lot :-)
Sounds great. This is awesome.
Any news on if/when Animate’s export will support it?
Thanks so much!
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.
The DisplayObject.compositeOperation property cannot be used with the StageGL, can be? I tried value “lighter” to it.
EaselJS NEXT: Randomized Particles with StageGL
#jsdoit: http://jsdo.it/FumioNonaka/I18d
This is SO COOL!
Next up – React Native support?!
https://github.com/ekulabuhov/react-native-canvas
Great news! And nice that it is so plug n play beside the few caveats mentioned!
What filters are coming? Directional blur at any angle would be nice. :)
I use animate cc to make demos.Could you tell me how can I add the stageGL ? I have tried var stage = new createjs.StageGL(“canvasId”); but it show the gray background to me without errors.
here is the demo:
http://119.29.8.64/vipstyle/channel/act/170495richman/src/html/index.html?_wv=1
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.
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)
UPD: I’ve finally figured out why my sprites randomly don’t render — https://www.dropbox.com/s/97y4m3yoqe9yjvb/stageGL.jpg?dl=0
But still the question remains: why stageGL randomly not creating those uvRects for some sprites (for a same image). Any help would be much appreciated as i really want to switch to stageGL.
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.
nice
I got blurry issue on highDPI screen. Please tell me how to fix.
Your sample: https://codepen.io/createjs/pen/dZvVKp
@Phap
The blurryness specific to high DPI is probably the content being stretched. Call update viewport with the retina size of the surface. It uses the DOM size of the screen by default (performance reasons), so you need to tell it to use the retina size.
stage.updateViewport(
domWidth * window.devicePixelRatio,
domHeight * window.devicePixelRatio
);
Hi @David,
I think the stage.updateViewport is to update the viewport size to fit the canvas size.
To fix the blurryness, we need to update the scaleX, scaleY properties of the Shape:
shape.scaleX = shape.scaleY = window.devicePixelRatio
But this just makes the shape bigger.
I found this post: http://www.unfocus.com/2014/03/03/hidpiretina-for-createjs-flash-pro-html5-canvas/
Any help, thanks
Updated:
Applying
antialias: true
will fix the blurry issue for Shape but not BitmapAh the blurriness was from things being rotated or scaled. Of note, anti-alias will only work on square textures that are a power of two, so some materials will respond to it but not others. This is mostly a WebGL 1.0 complication.
Pingback: createjs stagegl与animateCC协作 - geek720
I copied the code from the pink circle example and got a WebGL warning: drawArrays: This operation requires zeroing texture data in firefox browser.
Am I doing something wrong?