Announcement

Collapse
No announcement yet.

Asm.js, WebGL, and game engine (UE4)

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Asm.js, WebGL, and game engine (UE4)

    I wrote a detailed post about how game engines take advantage of asm.js and WebGL to take your compiled C++ code and run in the browser at near native speed. You can find it here.

    The formatting may appear a bit odd in the forum because I don't have the links, images, and videos embedded, but here goes:

    asm process
    Unity, and Epic’s Unreal Engine, the popular middleware tools frequently used by game developers are not limited to creating compiled applications that run as an executable.

    Unity previously had a web player, which was a downloadable plugin that used ActiveX. Chrome killed support for NPAP (Netscape Plugin API), but announced it over one year ago. Unreal did not previously use a web player.

    In April, with the release of Chrome 42 stable, they finally put the axe to it. There are a number of reasons as to why, but most notably they stated “hangs, crashes, security incidents, and code complexity. Google suggests using web standards instead, such as WebGL, which I will explain below.

    Microsoft is following suit and deprecating ActiveX, VBScript, attachEvent, and other legacy technologies in favor of web standards. The need for ActiveX controls has been significantly reduced by HTML5-era capabilities, which also produces interoperable code across browsers.

    With the advent of WebGL and asm.js, developers can now harness much of the power of their computing device from within the browser and access markets previously unavailable.

    Why compile to JavaScript?
    JavaScript is the only language which works in all web browsers. Although only JavaScript will run in the browser, you can still write in other languages and still compile to JavaScript, thereby allowing it to also run in the browser. This is made possible by a technology known as emscripten.

    Emscripten is an LLVM based project that compiles C and C++ into highly performant JavaScript in the asm.js format. In short: near native speeds, using C and C++, inside of the browser. Even better, emscripten converts OpenGL, a desktop graphics API, into WebGL, which is the web variant of that API.

    How is this code turned into WebGL?
    Unity recently did some performance benchmarks of their software running on WebGL as well.

    Having code cross-compiled (often called transpiling as well) is not without its pitfalls, however. Common performance-enhancing techniques found in statically typed languages, such as multi-threading (JS is single threaded) and SIMD (Single Instruction Multiple Data) are not available yet.

    Mozilla, along with several other leading tech companies, have been working on SIMD.js though, so increased performance and reduced power usage could be something of the near future. Read more about it here. Instead of those performance tweaks above, Unity is relying on their new scripting runtime, IL2CPP (In Line 2 C++). That’s a story for a different post, but Unity has been doing a fantastic web series every few weeks to illustrate how IL2CPP works. With Unreal we do not need to do this at all, because Unreal gameplay code is already written in C++.

    IL2CPP has two distinct parts:

    An ahead-of-time (AOT) compiler
    A runtime library to support the virtual machine (VM)
    The Intermediate Language (IL) from .NET compilers is compiled to C++ source code via the AOT compiler. Services and abstractions such as platform-independent access to threads and files as well as a garbage collector are some of the benefits the runtime library provides.
    1. Look at it this way:
    2. il2cpp-toolchain-smaller




    When you run a .exe on a Windows machine, it is not actually byte code(0s and 1s) at that point. It is still in a binary that the VM reads at runtime, which is then turned into bytecode. The DotNet CLI on a Windows machine is an example of a Virtual Machine which may read this binary. The CPU cannot comprehend anything other than binary, therefore this additional step is needed to take place.

    Still confused? This post explains more about the difference between machine code, byte code, and VMs.

    How does asm.js fit into the picture?
    Asm.js, short for Assembly JavaScript, is a subset of JavaScript. An asm.js program will behave identically whether it is run in an existing JavaScript engine or an ahead-of-time (AOT) compiling engine that recognizes and optimizes asm.js—except for speed, of course!

    In terms of speed, it’s difficult to offer a precise measurement of how it compares to native code, but preliminary benchmarks of C programs compiled to asm.js are usually within a factor of 2 slowdown over native compilation with clang, the compiler frontend for C, C++, and Obj-C programming languages. It’s important to note that this is a “best” case for single-threaded programs. More on this limitation of the JavaScript language below.

    On the backend, Clang uses LLVM, which is a library for constructing, optimizing and producing intermediate and/or binary machine code (those 0s and 1s again). LLVM can be used as a compiler framework, where you provide the “front end” (parser and lexer such as Clang) and the “back end” (code that converts LLVM representation to actual machine code)

    Further reading: Alon Zakai of Mozilla has a fantastic slide deck which goes into further detail about how this all works.

    So how cool is asm.js? Well it has its own Twitter account, @asmjs. While the asm site is a bit sparse, it does cover the W3C spec, in addition to having a thorough FAQ. Even better, Mozilla coordinated the Humble Mozilla Bundle in 2014, which allowed you to buy a bunch of gamest that took advantage of asm.js.

    Why not just turn your JavaScript code into asm.js?
    JavaScript can’t really be compiled to asm.js and offer much of a benefit, because of its dynamic nature. It’s the same problem as when trying to compile it to C or even to native code – a VM with it would be necessary to take care of those non-static aspects. You could write asm.js by hand, however.

    If one could already translate standard Javascript in a fully static manner, there would there be a need for asm.js. Asm.js exists so for the promise that Javascript will get faster without any effort from the developer. It would be very difficult for the JIT to understand a dynamic language as well as a static compiler.

    To better understand this, it is important to comprehend why asm.js offers a performance benefit at all; or why statically-typed languages perform better than dynamically-typed ones. One reason is “run-time type checking takes time,” and a more thought out answer would include the enhanced feasibility of optimizing statically-typed code. A final perk of going from a statically typed language such as C is the fact that the compiler knows the type of each object when it is being compiled.

    Asm.js is a restricted subset of JS that can be easily translated to bytecode. The first step required would need to break down all the advanced features of JS to that subset for getting this advantage, which is a bit complicated. But JavaScript engines are optimized and designed to translate all those advanced features directly into bytecode – so an intermediate step like asm.js doesn’t offer much of an advantage.

    What is WebGL doing?
    WebGL (Web Graphics Library) is a JavaScript API for rendering interactive 3D computer graphics and 2D graphics within any compatible web browser without the use of plug-ins. WebGL has three distinct advantages:

    Tasks
    Drawing reflective materials or complex lighting generate a ton of overhead, and seeing that JavaScript is single threaded and CPU bound, why not offload some of that to the GPU in your device and have that do the heavy lifting?
    Performance
    Utilizing hardware acceleration (the GPU built into your device), WebGL is a great fit for games or complex visualizations.
    Shaders
    Complex visual effects can be produced with small programs known as “shaders”. This may be as simple as producing a sepia coloring effect, or more complex simulations such as water or flames. Visit Shadertoy for a showcase of some examples which really highlight this.
    When you build a WebGL project, Unity will create a folder with the following files:
    • an index.html file that embeds your content in a web page.
    • a JavaScript file containing the code for your player.
    • a .mem file containing a binary image to initialize the heap memory for your player.
    • a .data file containing the asset data and scenes.
    • some supporting JavaScript files to initialize and load the player.
    • You can also customize the style of the page to better suite your game, although taking advantage of the Fullscreen API is recommended to get a more immersive experience.




    Interested in learning WebGL? Look into WebGL Academy for a complete course.

    What’s missing from WebGL?
    WebGL is a subset of the OpenGL ES spec. This is the graphics API you frequently see on mobile devices, such as Android and iOS devices. That ES (Embedded Systems) spec is actually a subset of OpenGL, the graphics API available to desktop machines and consoles, such as Playstation and Wii. Because WebGL is not a direct 1-to-1 match with OpenGL, some features will be missing.


    This is where things get crazy. You can try out two of their WebGL demos right here. You need to use a browser which supports asm.js. As of this writing (July 2015), asm.js support is as follows:
    • Firefox
    • Chrome
    • Edge
    • Safari


    It’s important to note that the asm.js spec is not implemented 100% in all of the browsers though, so results will vary. Unfortunately, asm.js is not listed on the popular feature-checking site CanIUse.com, so it’s difficult to get a clear understanding of how well it is supported in each browser. This will not work on mobile browsers as they currently do not support asm.js, although several support WebGL. I wrote a piece about the current state of WebGL on mobile devices in November of 2014.

    What about performance?
    You can try Unity’s benchmark suite in your browser to see how well their C# to JavaScript conversion performs. This covers everything from the Mandelbrot GPU test to 2D physics and particles. This post from Unity in October 2014, before Microsoft’s Edge browser was announced, also highlights some interesting finds:

    In almost all benchmarks, Firefox with asm.js is faster than both Chrome and Safari, and is currently the best browser to run Unity WebGL content.
    When you are mostly GPU-bound, you can expect WebGL to perform very similar to native code.
    In some areas, WebGL will actually outperform native code significantly. This is the case for tests which rely a lot on script performance (Mandelbrot and CryptoHash, which both implement their algorithms in C#), as IL2Cpp can produce more optimized code (More info in this post).
    Native code can still be several times faster than WebGL for areas heavily optimized to use multi-threading and/or SIMD, such as the 3D physics tests (PhysX 3.3 in Unity 5.0 is now fully multi-threaded). Compared to that, 2D physics is very close to parity when comparing Firefox to Native (Box2D is not multi-threaded). We hope that the future will bring SIMD and multi-threading extensions to JavaScript, at which point this may change.
    Well what does this mean for you, as the developer? Naturally there are some areas where WebGL is significantly slower than native code, such as areas which make use of multi-threading, but WebGL performance is decent and only improving by the day. In fact, the W3C, the international community which works to develop web standards, just announced WebAssembly, a new intermediate representation for safe code on the web. “Wasm” for short, is a new binary syntax for low-level safe code, which will run alongside asm.js for the time being. This will further improve the performance of JavaScript applications running within the browser.

    Alon Zakai wrote a post in March outlining how the speed of asm and JavaScript overall has been improving in the major browsers over the last year.

    Case Study: Owlchemy Labs’ Aaaaa! converted to asm.js from Unity
    hacks-Aaaaa

    The team at Owlchemy labs converted their game Aaaaa! In 2014 and put together a great postmortem about the process. Using the pre-alpha version of the WebGL exporter in June of last year, they were able to take all of their C# code and turn it into one JavaScript file which was more than 1 million lines of code long!

    Aaaaa! Has over 200 levels with more than 300 assets that can be spawned at runtime, in addition to 38 full-length songs. On PC/mac they were looking at a 388mb uncompressed file, so as you can imagine, having to download all of this each time someone wanted to play the game would be a bit of trouble.

    One of their biggest size savers was Unity’s AudioClip streaming solution, which could stream music at runtime on demand.

    When completed, their final compressed WebGL build size, which includes all loaded assets as well as the Unity engine itself, ended up wat 68.8 MB. The compressed standalone PC build was almost 3x that size, at 192 MB.

    There were certainly some UX changes that needed to be made, including rebinding the escape key, which in many games would display a pause menu, but inside the browser would exit full screen mode release mouse lock. Additionally, because browser’s security model forces these games to be sandboxed, saving large chunks of data to disk or loading custom audio from a user’s hard drive could prove problematic.

    Finally, it would be important to consider some sort of cloud sync feature, as gamers often will not play web based games on only one machine. It would be far more convenient for a consumer to load into their profile from any machine and have their settings / saves just appear.

    Are any other middleware tools taking advantage of this?
    Epic’s Unreal Engine 4 exports to WebGL and takes advantage of asm.js as well. You can find step-by-step instructions here. Their process is nearly identical to that of Unity’s minus that first C# step, as the code you write in Unreal Engine is already in C++.
    Epic’s current showcase piece is Tappy Chicken, a Tappy Bird type game which is also available on iOS and Android.

    They first illustrated UE 4 working within Firefox at GDC 2014:



    At GDC the year before that, Mozilla and Epic surprised everyone at one of their talks when they revealed that UDK (Unreal Engine 3) was working within the browser after only one week of work with their Epic Citadel demo.



    Monster Madness from NomNom Games, was the first commercial Unreal Engine 3 game published on the Web, using asm.js.

    What does the future hold?
    WebGL isn’t limited to games. Application could easily take advantage of this technology as well.

    Get a glimpse of the Unreal Paris 1.2 demo, where users can walk through a meticulously designed apartment. (Download link)


    Imagine working as an architect or designer and trying to pitch this to a client. You can run it on the fly, inside of the browser. Even better, the user does not need to download the entire application.
    Look at something like Age of Ascent. Download 54 Mb and you can start playing the app because it only streams what you need right then can cache it locally using a technology such as IndexedDB , so you do not need to download it again. Users can be up and running in seconds. I interviewed the team at Ilyriad games in December to get a better understanding of how they put their technology together.

    On the other end of the Spectrum, we have Star Citizen, which starts at 70Gb.That’s a huge barrier to entry to many folks, especially in places where they may not have quick broadband.

    For developers who perhaps do not want to use C or C++ to write your applications, you can still use a WebGL framework and write it all in JavaScript. BabylonJS is one example of this, which includes a physics engine for both 2D and 3D applications, as well as handJS which funnels all input types (click, touch, pen) into pointer events.

    Are there other alternatives?
    But of course! PlayCanvas is a fantastic WebGL based framework which uses asm.js for physics. Even better, it has excellent documentation and tutorials, on top of a browser-based editor.

    PlayCanvas

    For tools such as this, you’d need to use a wrapper of some sort (such as Cordova or PhoneGap) to port this to an app store such as Google Play, the App Store, or Windows Marketplace. ManifoldJS.

    ManifoldJS aims to make the life of a mobile developer easier than ever, by utilizing Web App Manifests, which allowing websites to declare app-like properties. ManifoldJS uses that standard for those platforms that support it, but falls back to Cordova for those who don’t. Cordova is great, but the W3C also considers work done at Mozilla (Firefox Open Web Apps), Google (Chrome Hosted Apps) and Microsoft has done (Windows 8 had local web apps, Windows 10 extends over to hosted web apps). With this, we can now wrap websites and creating hybrid applications which can be deployed in the various app stores, while still taking advantage of many native aspects for each device (contacts, calendar, file storage, gyro, GPS, etc.)

    When we combine the two, we can create applications at native speed which can be deployed in a number of app stores, and utilizing largely one code base. There is no silver bullet for mobile dvelopment, but this certain makes the process easier.

    Conclusion
    Unity outlines the process of exporting your title to their WebGL player in their docs. Browser support for both WebGL and asm.js is constantly improving, and Firefox was even showcasing features of WebGL 2.0 at the Game Developers Conference in San Francisco earlier this year. WebGL 2.0 comes with a number of improvements, including the ability to render up to 32 textures at one time, as opposed to the current standard of 8, in addition to developer access to antialiasing and multiple render targets.

    The advantages of porting a Unity game to WebGL are numerous:
    • Distribution through sources other than curated app stores
    • Often a smaller package size
    • Easily demo or share projects



    Developers have already proven that the model works, as illustrated by the Aaaaa! Case study and Mozilla Humble Bundle, so it’s an opportune time to take advantage of what the browser can finally offer and have additional exposure for your work.
    Last edited by DaveVoyles; 07-08-2015, 02:44 PM.
    Tech Evangelist & video game person at Microsoft | @DaveVoyles
    Other games I've created and my UnrealScript tutorials
    Author: UnrealScript Game Programming Cookbook

    #2
    The thing is, a game made with UE will be over 60mb (without the assets) and with no lazy loading who's gonna bother dl? Assuming the browser won't freeze due to javascript's garbage collection not clearing.

    Comment


      #3
      60mb? That's tiny!

      I get 125 Mbps, so that's less than a second to download an entire game. Not bad. Even better - I don't have to go through the crazy process of installing / uninstalling when I don't want it anymore. Not tweaking my registry either.

      As a developer I am free to distribute it however I'd like too, and update it at will! No more messing with the app store requirements uploading images, getting approval from Apple, etc., paying $100 / yr for developer licenses, waiting 1 week to get it approved (that is, IF they approve it).

      The question you raise is not uncommon though. If you look at it as a big website, then yes, it is massive.

      If you look at it as a game, it is tiny.

      Let me ask you: When you go to Netflix or YouTube to watch a video, do you sit there and think "This page is 1.4gb! Madness!"?
      Tech Evangelist & video game person at Microsoft | @DaveVoyles
      Other games I've created and my UnrealScript tutorials
      Author: UnrealScript Game Programming Cookbook

      Comment


        #4
        Originally posted by DaveVoyles View Post
        60mb? That's tiny!

        I get 125 Mbps, so that's less than a second to download an entire game. ...
        Uhh... pretty certain your calculation is wrong there (i get 8Mb line speed and get 800k/s download speeds... bits and bytes remember, confusing business) Also, not EVERYONE in the world has that speed.

        Originally posted by DaveVoyles View Post
        Let me ask you: When you go to Netflix or YouTube to watch a video, do you sit there and think "This page is 1.4gb! Madness!"?
        Netflix etc. streams the data down, there's a difference. You can not do that with this.
        OP:

        All in all an interesting post. I like the way gaming is going and also it could be used for all sorts of other apps too. Emscripten is like voodoo magic!
        Last edited by paulv2k4; 07-09-2015, 02:41 AM. Reason: Im a numpty who cant spell or type early in the morning
        Currently working on PARGSoft Football

        My day job is a C# ASP.NET Developer, I wish it was a games developer

        Comment


          #5
          Originally posted by DaveVoyles View Post
          60mb? That's tiny!

          I get 125 Mbps, so that's less than a second to download an entire game. Not bad. Even better - I don't have to go through the crazy process of installing / uninstalling when I don't want it anymore. Not tweaking my registry either.
          You're less than a minority with that speed.

          Originally posted by DaveVoyles View Post
          As a developer I am free to distribute it however I'd like too, and update it at will! No more messing with the app store requirements uploading images, getting approval from Apple, etc., paying $100 / yr for developer licenses, waiting 1 week to get it approved (that is, IF they approve it).

          The question you raise is not uncommon though. If you look at it as a big website, then yes, it is massive.

          If you look at it as a game, it is tiny.

          Let me ask you: When you go to Netflix or YouTube to watch a video, do you sit there and think "This page is 1.4gb! Madness!"?
          Netflix or YouTube stream the data + they correct the quality automatically.
          Who's going to dl over 100mb (min) every time they need to play the game? Unless you're building it as a Chrome Packaged App that works offline, you might as well put it on Steam.

          Comment


            #6
            Great Post DaveVoyles.

            Although I would like to jump in clarify the size issue - default engine Javascript Shipping "binary" is around ~10mb ( it has increased over few iterations of the Engine, although a custom build can cut down the size even more) when compressed. the code part makes it the SMALLEST of any platform UE4 supports.

            all modern browsers support gzip, there is no reason at all to not serve compressed javascript.

            That being said, we have have listened to our users, as of our upcoming 4.9 release we will emitting out compressed javascript from HTML5 packaging. Also, we will be shipping the SDK with the Engine, which makes HTML5 export trivial with no configuration needed which is currently required for current releases.

            Comment


              #7
              I agree, I am definitely the minority when it comes to having speeds like 125mbps. You could always allow for caching the data too. Now you do not need to download the data each time you want to play. I agree that I didn't do a very good job of illustrating that here, but I updated my blog post to reflect that, so than you for pointing that out.

              Streaming vs. a total downlaod is a good comparison too. Currently these compiled apps (UE4, Unity) do not allow for it, I believe. You can stream WebGL games however, as Age of Ascent does exactly that. I saw the folks from Illyriad Games give a talk about that during an internal tech event at Microsoft and it blew our minds.

              @Ankitkk, what could I write to clarify this?

              Awesome to hear about the 4.9 release, too!
              Tech Evangelist & video game person at Microsoft | @DaveVoyles
              Other games I've created and my UnrealScript tutorials
              Author: UnrealScript Game Programming Cookbook

              Comment


                #8
                This thread helped me learn a lot. Thank you.

                Comment


                  #9
                  Also, you've got 125 mega bits per second, whereas the package was stated to be 60 mega bytes. So it wouldn't have been less than a second, it would be less than 4 seconds, assuming perfect network speed, which almost never happens.

                  Comment

                  Working...
                  X