Learn the PlayCanvas API with the Engine Examples Browser

PlayCanvas has a rich JavaScript API that allows you to build just about any type of interactive content imaginable – games, playable ads, product configurators, AR, VR and more! But learning a new API can be tough. Reading API reference documentation is all well and good, but many people prefer to learn by experimentation. And by examining the code of real world examples. This led the PlayCanvas team to build a new application: the Engine Examples Browser.

Starting exploring the Examples Browser now:

https://playcanvas.github.io/

The browser is written entirely in Typescript and uses a Webpack build process. Naturally, it is 100% open source (MIT license) and the source can be found here.

The Examples Browser has some pretty cool features:

  • Gallery panel. Select any of the 86 examples from the (filterable) list on the left, either by name or thumbnail.
  • Inspect Source. Expand the source panel (built on the awesome Monaco code editor) on the right to inspect any example’s source code.
  • Edit and hot reload. Edit any example and hit the Play button to refresh the running example. Monaco uses PlayCanvas’ Typescript definitions to provide inline API hints.
  • Embed links. Want to embed PlayCanvas examples in your own site? Simply hit the embed icon and copy the URL!
  • Share to Twitter. Want to share a specific example with the world? Just hit the Twitter icon!

If you would like to request an example to be added to the browser, submit an issue here. Or if you’re feeling creative, submit a pull request of your own to the repo! Stay tuned for newly added examples in the coming months. Enjoy!

WebGL Case Study: Rebuilding the Star-Lord PBR Demo

Way back in 2014, PlayCanvas was the first WebGL Engine to integrate PBR (Physically Based Rendering). To mark the event, we built the Star-Lord tech demo:

In the intervening 6 or so years, PlayCanvas has moved on dramatically. So we decided to leverage all of the latest engine features and republish it.

The most significant improvements are related to load time. Let’s start out by comparing some key stats:

Star-Lord 2014Star-Lord 2021% Change
HTTP Requests22039↓ 82.3%
Preload Transfer (MB)10.15.6↓ 44.6%
Total Transfer (MB)13.79.9↓ 27.7%
Total Resources (MB)26.012.1↓ 53.5%
Load Time (s) *1.81.2↓ 33.3%
* Cache disabled on 100Gbps connection

Those are some pretty significant wins! So what are the differences between the two builds of the demo? Let’s step through them one by one.

Convert JSON Meshes to GLB

In October 2020, PlayCanvas officially switched from JSON to glTF 2.0 (GLB) for storing all model and animation data. While gzipped GLB is reasonably similar in size to gzipped JSON, it is up to an order of magnitude faster to parse a GLB file once it has been downloaded. Plus, a GLB file occupies less system memory than the equivalent JSON file. Converting all of the assets from JSON to GLB is a simple process. First, flip the project setting ‘Convert to GLB’ in the ‘Asset Tasks’ group to true:

Now, simply reupload all FBX files and a .glb asset will be generated rather than a .json asset. The last step is to use the Replace command in the right-click context menu to replace the .json asset with the .glb asset (plus any materials as well).

You can then delete the old JSON asset (plus any unreferenced related materials).

Basis Compress Textures

Last month, we announced the integration of Basis texture compression into the Editor. Star-Lord was originally configured to use DXT, PVR and ETC compressed textures. A download size comparison is as follows:

Texture FormatDownload Size (MB)
DXT7.56
PVR6.09
ETC17.18
Basis2.38

This explains much of the download savings in the updated version.

Fortunately, applying Basis compression to the app’s textures is literally a two-click operation:

Prefilter Cubemaps in the Editor

When PBR first arrived in PlayCanvas, the Editor could not prefilter cubemaps. This conversion had to be performed externally with RGBM format cubemap faces being added to the Editor:

Each cubemap had 6 mip levels with 6 faces for each level. And with 5 different cubemaps, that meant 180 of the demo’s 220 HTTP requests were for these PNGs!

These days, the Editor makes is super easy to import 6 HDR cubemap faces, build a cubemap and then prefilter it.

So instead of loading 180 PNGs, the demo now loads just 5 DDS files. Much faster. 🚀

Asynchronously Load Assets

To achieve an optimal load time, it is important to only load what is required to make your app functional. It is arguable that music is not strictly a necessary precondition for your app to start. Therefore, the demo now asynchronously loads the mp3 asset that contains the music track and auto-plays it as soon as it is downloaded. It is 3.9MB which accounts for nearly 40% of the app’s payload! So be sure to carefully audit your app for assets that can be streamed instead of preloaded.

Read more about preloading and streaming of assets in the User Manual.

Useful Links

PCUI 1.1.0 Adds Tree Control and Array Control

Back in October, we launched PCUI, an easy to use framework for building web-based tools. It already powers the PlayCanvas Editor and glTF Viewer applications.

Today, we’re excited to announce our next major release for the library: PCUI 1.1.0. Check out the release notes for the details. But let’s take a look at some of the highlights.

TreeView – Tree Control

Many web tools display data in a hierarchical or tree-based representation. But building a tree control in HTML and CSS can be tricky. PCUI 1.1.0 introduces a very easy to use tree control. And it incorporates some useful features such as:

  • Drag and drop of tree view items
  • Built-in ‘double-click to rename’

ArrayInput – Array Control

Also arriving in PCUI is ArrayInput. It allows you to create input controls for arrays of numbers, strings, booleans or vectors.

Resizable TextAreaInput Control

The TextAreaInput control has been augmented with a new resizable property that can be set to ‘none’, ‘horizontal’, ‘vertical’ or ‘both’.

To get started making awesome web tools with PCUI, here are some useful links:

Introducing PCUI – An Open Source UI Framework for the Web 🚀

Today, PlayCanvas is launching PCUI: a new, open source front-end framework for the web.

PCUI is designed with tools developers in mind. It is particularly well suited to building viewer and editor applications, providing a rich set of beautiful and consistent controls. It already powers the PlayCanvas Editor – the world’s most powerful WebGL production tool.

Here you can see tree controls, panels, buttons, checkboxes, toolbars, menus and more. The Editor also relies on PCUI’s observer system, that makes it easy to synchronize the state of your application’s UI with that of the underlying data. Plus, it has a built-in support for history to make implementing redo/undo a breeze.

Also built on PCUI is the PlayCanvas glTF Viewer, a tool for inspecting glTF 2.0 scenes.

Check out the viewer’s GitHub repo to see how a Typescript-based web application leverages PCUI.

If these applications inspire you to build your own browser-based tools, why not get started with PCUI today? Here are some useful links:

PCUI works great with vanilla JS projects, Typescript projects and React-based projects. It’s open source so we encourage you to get involved and help us advance PCUI.

If you’re building any kind of browser-based tool application – definitely check it out today and share your thoughts on the forum!

PlayCanvas launches glTF 2.0 Viewer Tool

Today, the PlayCanvas team is excited to announce the release of a brand new browser-based glTF viewer application.

Try it now: https://playcanvas.com/viewer

Or click these links to preload some classic glTF models: Boom Box, Damaged Helmet and Fox.

The viewer is open sourced under an MIT license and the code can be found on GitHub.

Fork it now: https://github.com/playcanvas/playcanvas-viewer

The viewer allows you to drag-and-drop any glTF 2.0 file and inspect it in detail. We challenge you to find one that doesn’t work! The viewer has the following features:

  • Visualize wireframe, skeleton, bounds and normals
  • Adjust scene lighting and skybox
  • Drag and drop equirectagular images (including HDR files) or six cubemap face images.
  • See how a model performs on both the CPU and GPU via the viewer’s real-time metrics panel
  • Play animations (including skinned and morphed meshes) – unlimited morph targets are supported
  • Visualize animation curves in real-time as graphs in the 3D view
  • Load models via drag-and-drop or by passing a URL query parameter
  • Support for Draco mesh compression

The release of the PlayCanvas Viewer coincides with the engine reaching 100% glTF 2.0 spec compliance! PlayCanvas passes every single core test in cx20’s glTF Test suite. We are now turning our attention to supporting the full range of glTF 2.0 extensions. The engine already supports:

  • KHR_materials_pbrSpecularGlossiness
  • KHR_materials_unlit

The engine itself can parse and render glTF 2.0 files incredibly quickly. You can expect glTF parse time to be approximately one tenth of that loading the equivalent JSON model.

Give it a try today – you’ll be impressed!

Porting a Large ES5 JavaScript Library to ES6 Modules and Rollup

Since 2011, the PlayCanvas engine sourcebase has adhered strictly to the ES5 JavaScript specification. Since then, the JavaScript language and the surrounding tools ecosystem has moved on considerably. But PlayCanvas has steadfastly stuck to ES5. Why? Internet Explorer 11.

IE11 was released on October 17, 2013. But even today, StatCounter reports that IE11 has 2.43% of the global desktop browser market. Since PlayCanvas content is viewed by 100s of millions of end users, this is a pretty big deal.

Over time, the engine codebase has grown significantly. It’s now nearly 100,000 lines long. Maintaining and building such a large codebase can be problematic. To help bring some level of consistency and structure, we imposed the following pattern:

Object.assign(pc, (function () {
    var SomeClass = function () {
        this.other = new pc.OtherClass();
    };

    Object.assign(SomeClass.prototype, {
        someFunction: function () {}
    });

    return {
        SomeClass: SomeClass
    };
}()));

pc is the PlayCanvas library namespace. So a developer would create instances of this class as follows:

var thing = new pc.SomeClass();

To build the engine, we wrote a node.js script which would parse a list of dependencies (JavaScript filenames) and concatenate them. There were several problems:

  1. The pattern above is overly verbose making it harder to inspect the code.
  2. Object.assign needs to be called 250 times when the library is initially executed by the browser, once for each module. This increases app start-up times.
  3. In internal engine code, all class names and constants need to be accessed via the pc namespace. This is because the internals of the pattern above cannot see the internals of other modules and vice versa. This bloats the engine code and slows things down.
  4. The dependencies file had to be carefully manually ordered to ensure things were declared in the right order.
  5. The build script itself was about 1000 lines of JavaScript which carried its own maintenance overhead.
  6. Unused code was being included in the published engine.

We believed the solution to these problems was to migrate the engine codebase from vanilla ES5 to ES6 modules. This would transform the original module pattern to:

import { OtherClass } from './other-class.js';

var SomeClass = function () {
    this.other = new OtherClass();
};

Object.assign(SomeClass.prototype, {
    someFunction: function () {}
});

export { SomeClass };

Much better!

  • No more needless calls to Object.assign to the pc namespace.
  • No further need to use the pc namespace within modules.
  • Dependencies are explicitly described in each JS file.
  • Only what is necessary is exported from modules (and the overall engine).

But what about IE11? It doesn’t understand ES6 module syntax! 😱 PlayCanvas still needs to ship as a strictly ES5 library. To transform the entire codebase from ES6 module format to ES5 UMD format (PlayCanvas is used in both the browser and Node), you simply need to leverage a JavaScript bundler.

There are many options for selecting a JS bundler. In the end, 3 options were tested: Rollup, Parcel and ESBuild. You can see the PRs for each here:

In the end, Rollup was selected over Parcel and ESBuild. In testing, Parcel needed up to 16s for an initial build, while Rollup only required 3s. And we were reticent to adopt ESBuild since it was far less established and battle tested compared to Rollup. But we may review this decision in the future. Now that the engine is ported to ES6 modules, switching bundler is fairly straightforward.

With Rollup, the build script reduced from ~1000 lines to ~100 lines. Quite a saving. Rollup’s plugin system made it incredibly easy to write custom handling for GLSL files and also run a C-like preprocessor in order to build debug, release and profile versions of the engine.

What’s Next?

Now that we have merged the ES6 Module port, where do we go from here?

First up, Rollup is kindly informing us that circular dependencies exist in the PlayCanvas codebase.

We want to clean things up and eliminate them. What’s the motivation for that? It makes it easier for the bundler to employ tree-shaking to remove unreferenced code from the engine. At the moment, the engine’s Application class imports pretty much everything. And many classes import the Application. This makes it hard to build a version of the library which doesn’t include the particle engine, say. Or maybe the physics engine.

Beyond that, we are keen to explore leaving ES5 behind and fully embracing ‘modern’ JavaScript, or maybe Typescript. Rollup can trivially run Babel or the Typescript compiler as plugins, thereby ensuring we can still ship an ES5 library. We’re looking forward to making that decision based on your feedback. So feel free to let us know what you think on the forum!

TANX lives! Popular WebGL online game returns

In the early days of PlayCanvas, we published a game called TANX, an online multiplayer tank battle game.

To us, it was the perfect illustration of why the web makes such a great platform for gaming.

  • Bite-sized fun with drop-in/drop-out gameplay.
  • Nothing to download – just follow a hyperlink to stream the game in a couple of seconds.
  • True device independence – play on your phone, tablet or desktop.
  • Easy social sharing – get your friends into matches by posting your personal game URL to Twitter in real-time!

So we decided to keep developing the game. The first iteration above just had primitive tanks driving around an empty environment. v2.0 brought upgraded tank models, a new UI and a proper level:

And the game’s popularity continued to grow. It even hit #1 on Hacker News one lazy Friday afternoon!

By now, the PlayCanvas engine was rapidly evolving and had recently gained support for physically based rendering (PBR). We were desperate to upgrade the game to show off these new capabilities. So not long afterwards, we developed v3.0:

The game also leveraged PlayCanvas’ run-time lightmapper to generate the level’s shadows.

Not long after the upgrade, we decided to focus all of our resources on developing the core PlayCanvas engine. In the end, we didn’t have enough time to maintain the game and so, with heavy hearts, we took it offline.

Until today.

We’re really excited to announce that TANX is back! You can play it at:

https://tanx.io

Or alternatively, you can find the game hosted on Miniclip and Itch.io.

Keep your eyes peeled for a follow up article outlining how we rebuilt and deployed the game’s back-end!

A New UI for the PlayCanvas Editor

The PlayCanvas Editor has been around since 2011. Way back then, it was called the PlayCanvas Designer. It was built on Sencha’s ExtJS front end framework and looked like this:

As you can see, it sort of looks like a Windows XP application. If you think it looks retro now, it actually looked retro then! But you can more or less recognize it as PlayCanvas. The Pack Explorer is now the Hierarchy panel on the left. The Attribute Editor is now the Inspector. You can even see the ‘Who’s Online’ bar to the bottom right, which is still around today. We decided quite quickly to drop the WinXP aesthetic by adopting a darker theme in September 2013:

This refresh was definitely an improvement and it was the start of the Designer finding a personality of its own. But after this, the team was struggling to iterate quickly. We took the very difficult decision to throw away the entire ExtJS-based Designer application and rewrite it from scratch using the incredible Vanilla JS framework. And thus, by early 2015, the PlayCanvas Editor was born:

This initial version of the Editor should be much more recognizable. The toolbar and panels are all still in the same location. But today, the Editor packs in far more functionality and is much more powerful.

It was originally written in ES5 and a subset of CSS that would enable the Editor to work in browsers all the way back to IE11. Late last year, we embarked on the next major overhaul for the Editor, with the following goals:

  • Create a clean, structured underlying Editor API (more on this later)
  • Adopt ES6 (let’s get with the times!)
  • Adopt CSS grid to make managing the Editor’s layout easier
  • Refresh and refine the front-end design

We’ve slowly been phasing in the new front-end over the last several months, first deploying an updated Hierarchy Panel and then a new Inspector Panel. Today, we’re proud to announce the final step in the rollout – the new Asset Panel:

To the end user, the most obvious change is the addition of the Asset Panel’s Details View. As an alternative to thumbnails, you can now see a linear list of assets and even sort them on size and type.

We expect that this will rapidly become the default view for most PlayCanvas developers. No more mouse hovering to read long filenames!

So what’s next? Earlier, I mentioned that this completely rebuilt Editor front-end is built on a new, clean, object-oriented API. It is our plan to release this API publicly, once it is ready. This will enable you to write extensions and customizations to the Editor that will culminate in a full plugin system. Stay tuned for further details of that. But in the meantime, let us know what you think by joining the conversation on the forum!

Introducing the PlayCanvas Localization System

Are you shipping your PlayCanvas app or game in just one language? You may be preventing international users from enjoying it! Today, we are happy to announce the arrival of a localization system built right into the PlayCanvas Editor!

PlayCanvas-powered Bitmoji Party localized into English, Spanish and French

The system works in tandem with PlayCanvas’ text element component and it’s super-easy to use. The text element interface now provides a ‘Localized’ property and when checked, you can enter a Key instead of a Text string.

New text element properties for enabling localized text

The Key is the string used to look up a localized string based on the user’s currently selected locale. The localized string data is stored in JSON assets and is documented, along with the rest of the system, here. You can even preview your localized User Interface by choosing a locale in the Editor Settings panel:

Locale setting in the Scene Settings panel

We look forward to playing your newly localized games!

Arm and PlayCanvas Open Source Seemore WebGL Demo

Cambridge/Santa Monica, August 1 2019 – Arm and PlayCanvas are announcing the open sourcing of the renowned Seemore WebGL demo. First published in 2016, the graphical technical demo has been completely rebuilt from the ground up to deliver even more incredible performance and visuals. With it, developers are empowered to build their projects in the most optimised way, as well as using it to incorporate some of its performant features and components into their own projects.

PLAY NOW

EXPLORE PROJECT

“I’m so excited to be relaunching the Seemore demo. Open sourcing it in partnership with Arm will bring a host of benefits to the WebGL development community,” said Will Eastcott, CEO of PlayCanvas. “It’s an incredible learning resource that provides many clean, easy to follow examples of some very advanced graphical techniques. Sharing this project publicly is going to help move web graphics forwards for everybody.”

“PlayCanvas and Arm have always strived to push the boundaries of graphics and the original demo is a testament to that,” said Pablo Fraile, Director of Developer Ecosystems at Arm. “It’s encouraging to see how PlayCanvas have advanced mobile web rendering performance since the original demo. This re-release provides a unique resource into graphics for the mobile web that is both easy to follow and incorporate into your own projects.”

The Seemore demo was originally created as a graphical showcase for the mobile browser and takes full advantage of Arm Mali GPUs. It has been upgraded to utilize the full capabilities of WebGL 2, the latest iteration of the web graphics API. Some of the main features of the demo include:

  • Physical shading with image based lighting and box-projected cube maps.
  • Stunning refraction effects.
  • HDR lightmaps.
  • Interpolated pre-baked shadow maps as a fast substitute for real time shadow-mapping.
  • ETC2 texture compression to ensure that highly detailed textures occupy only a small amount of system memory.
  • Draw call batching.
  • Asynchronous streaming of assets to ensure the demo loads in mere seconds (approximately 5x faster than the original version).
  • Fully GPU-driven mesh animation.