Ray Casting in Web Assembly part I

2.5D Ray Casting in web assembly with some light and fog.

This article was co-authored by Thomas Kjeldsen.

As a C++ programmer it is very compelling to write your code and test it nativly and using Emscripten you can publish and use your code directly on the web.

But there is a learning curve to everything so to make a relevant and fun “Hello World” Application. That actually uses some CPU power i decided to do a Wolfenstein Ray Casting demo. This is a cool an relativly easy technique and there are interesting design choice where to devide the computation between Java script and Web Assembly (c++).

Prerequisites

I asume a bit knowledge about C++, web development and javascript.

Scene setup

The scene is a 2d array of integer, that determine if there is a wall, light or empty space. This is done by tracing a 2d ray inside the scene using a DDA algorithm (explained below) that step through each grid cell and find the distance to an intersected wall.

Ray Casting Algorithm

The basic idea is to render a 2.5 D image like in wolfenstein, where you render the image by finding intersection in 2D between a ray and the scene. Instead of true ray tracing where each pixel is calculated, by only tracing each collumn is much faster. But it also limits the rendering to walls of the same height.

My idea was to make the rendering simple and output the correct 3d Depth that later can be used for texturing and lighting.

But the first issue is finding the depth of the first intersection with the walls. In a lot of other tutorials i have seen there make this problem kind of difficult using trigonometric functions. But here i precent a simple ray casting (stepping) method.

My hand notes on 2D Ray Casting (Ipad pro rocks!)

In C++ pseudo code

DDA code

Pretty simple right? Ok with the depth for each pixel collumn ready then we need to calculate the pixelheight of the wall and the 3D depth. This is based on the camera field of view and the image dimension. In the demo i added some linear fog calculations. And the input to the fog is the depth from the camera. To make this consistent i calculate a ray traced wall, ceiling and floor depth. But that will be explained in the next episode. (Advanced lighting in ray casting).

Web Assembly

With the algorithm in place and tested, it is time to move the C++ to the web using Emscripten. Here i have designed the interface between Javascript and C++. Such that JS takes care of player input and C++ (Webasm) takes care of ray casting the final image thats is presented on the screen. Don’t consider this deep knowledge and there is a fair amount of handwaving because this is my first Webasm projekct. But is seems that the more work you offload to webAsm the better.

First you have to download and install Emscripten. Here you have to follow this guide https://emscripten.org/docs/getting_started/downloads.html

We have experimented i bit with the interface between Emscripten and Javascript, but here we us “Embind” even though it creates a big Javascript file that glues stuff together, as shown below. “RayLib.h” is the core ray casting class that exposes 3 methods that Embind can create javascript bindings for.

CMake and Emscripten

It is possible to use CMake for both C++ and WebAsm development. Over time CMake really grows and it is so nice to have a way to quickly generate the right solution files for Visual Studio regardless of versions. Emscripten uses “make” to compile so on windows you need to install that. I use “MinGW” and for reasons i use Git bash to run make and other scripts.

To use CMake gui to generate the make file for Emscripten, you need to use the following setup after selecting your source and build folder.

Please download and play with the source code and let me know it there is something missing. Notice that we use NPM and Webpack to handle Javascript dependencies and bundeling the generated code. This is not my strongest competence so i hope it make sense. But i have made to small bash script that are included in the project.

Source code

https://bitbucket.alexandra.dk/projects/CG/repos/raykarstenwebasm/browse

References

https://alexandra.dk/dk (Where i work)

https://webassembly.org/

https://emscripten.org/index.html

http://www.mingw.org/wiki/MSYS (for make)

https://www.permadi.com/tutorial/raycast/rayc1.html (Great ray casting tutorial)