ipfs-webgl

View the Project on GitHub gpudemo/ipfs-webgl

WebGL with IPFS acceleration

A hobby project by Zephyr Yao

Environment: Ubuntu 20.0.4, amd64

WebGL provide online 3D supports comparable to local games, but unfortunately, online 3D games is rare because file transfer from server to browser is slow. The Inter-Planetary File System (IPFS) is a peer-to-peer protocol designed to store file in blockchain in a decentralized manner. In this project, we explore the possibility of using IPFS to accelerate WebGL games.

diagram

This diagram shows how the project works. On the left, a traditional WebGL program downloads both the WebGL page and WebGL data (e.g., shaders, textures) from a remote server. The download speed is limited to the connection bandwidth. On the right, we redirect the WebGL data to IPFS. IPFS serves the data directly to the browser.

Steps to run WebGL with IPFS acceleration

1. Setup local IPFS

Before installing IPFS, please make sure you have Golang installed (https://golang.org/doc/install). Download the most recent IPFS release from https://dist.ipfs.io/#go-ipfs, and unzip the tar ball. After unzipping, add the path to ~/.bashrc, and update the bash environment with command source ~/.bashrc.

Now, you should have IPFS installed. To verify, run command ipfs version.

Environment variables

Add IPFS_PATH=~/.ipfs to ~/.bashrc. This ensures that we will be using our local ipfs network settings.

Add export LIBP2P_FORCE_PNET=1 to ~/.bashrc. This environment variable will forbid ipfs from connecting to the public ipfs network. In this guide, we will only use a local ipfs network.

Initialize and config IPFS

Run the following commands,

ipfs init
echo -e "/key/swarm/psk/1.0.0/\n/base16/\n`tr -dc 'a-f0-9' < /dev/urandom | head -c64`" > ~/.ipfs/swarm.key
ipfs bootstrap rm --all

The bootstrap settings instruct program where to connect. Since we will be using our local ipfs network, we need to remove all existing bootstraps and add our own.

First, find your LAN ip address with ifconfig.

Then, find your peer ID with ipfs config show | grep "PeerID".

Finally, add bootstrap with the following command (replace PeerID and IP),

ipfs bootstrap add /ip4/<ip address>/tcp/4001/ipfs/<peerID>

Enable LAN gateway

By default, ipfs only allows web access from localhost. To change this, edit ~/.ipfs/config, find “Gateway”. You will see "Gateway": "/ip4/127.0.0.1/tcp/8080". Change it to "Gateway": "/ip4/<LAN IP Address>/tcp/8080".

Also, please make sure ufw or other firewalls allow for 8080 port access.

Run IPFS

Open a new terminal, run

ipfs daemon &

2. Serve WebGL Game

Clone project from GitHub

git clone https://github.com/gpudemo/BoxShooterGame.git
cd BoxShooterGame/

Add WebGL data files to IPFS

# Assume now we are in BoxShooterGame/
cd IPFS-accelerated/
ipfs add Build/*.unityweb

You will see the files are being saved to ipfs,

added QmcZwVoqmMsstEMFjBEhwqbxf79KA1okDL12QU76RxKr6L unity-original/BoxShooterGame-main/Build/WebGL.data.unityweb
added QmYmfFZF5wVBprnwkADsXrpdUcsr487N9CWFrSjQ19ptfs unity-original/BoxShooterGame-main/Build/WebGL.wasm.code.unityweb
added QmNuGXCqDLG5EQ3BxxFAi4Xy8u5sM7RUhedbPadztjsxDH unity-original/BoxShooterGame-main/Build/WebGL.wasm.framework.unityweb

Modify Unity WebGL loader script to load from ipfs

We already made change to UnityLoader.js to accept absolute WebGL data path. Now you can simply insert the web gateway paths of these files to Build/WebGL.json.

Open Build/WebGL.json,

{
"companyName": "Dhruv194",
"productName": "BoxShooter",
"productVersion": "0.1",
"dataUrl": "http://<LAN IP addess>:8080/ipfs/QmcZwVoqmMsstEMFjBEhwqbxf79KA1okDL12QU76RxKr6L",
"wasmCodeUrl": "htp://<LAN IP addess>:8080/ipfs/QmYmfFZF5wVBprnwkADsXrpdUcsr487N9CWFrSjQ19ptfs",
"wasmFrameworkUrl": "http://<LAN IP addess>:8080/ipfs/QmNuGXCqDLG5EQ3BxxFAi4Xy8u5sM7RUhedbPadztjsxDH",
"graphicsAPI": ["WebGL 2.0","WebGL 1.0"],
"webglContextAttributes": {"preserveDrawingBuffer": false},
"splashScreenStyle": "Dark",
"backgroundColor": "#231F20",
"cacheControl": {"default": "must-revalidate"},
"developmentBuild": false,
"multithreading": false,
"unityVersion": "2019.4.18f1"
}

Update <LAN IP addess> with your local IP address, and update the file hashes with the ones you received from ipfs add command.

Host WebGL Game

Open a terminal, and cd <path to BoxShooterGame2/IPFS-accelerated> . The game will be automatically hosted on port 8081 with Python3’s SimpleHTTPRequestHandler.

python3 run.sh

###3. Run IPFS-accelerated WebGL game

To launch the IPFS-accelerated game, open the URL, http://<IP Address of the hosting machine>:8081 with any Chromium-based browsers (such as Chrome). If everything is successful, the WebGL game should run.

See the difference

WebGL loading speed comparison

We show the IPFS-accelerated WebGL loading is much faster than retrieving the WebGL data files from a remote server. In the experiment, we setup the IPFS local host and WebGL host on one machine, and launch Chrome browser on another machine connected to the same LAN network.

The DOM content loading time for the baseline WebGL is 459 ms, and for the IPFS-accelerated is 137 ms. IPFS-acceleration DOM loading is 4.81x faster. Overall, the webpage loading time for the baseline WebGL is 2510 ms, and for the IPFS-accelerated is 597 ms. The overall speed is 4.2x faster.

Interestingly, Chrome browser won’t fully download IPFS-accelerated WebGL data files, but it does fully download the baseline WebGL data files. In the net profile, the downloaded size is 650 KB for IPFS, and 7.4 MB for the baseline. It benefits us because our IPFS-accelerated page downloads less data. But how can it be? WebGL data are XHR files that are dynamically loaded behind the scene. It is possibly because IPFS is fast enough for the browser to load it on the fly. But for remotely hosted WebGL content, Chrome loads them before launching WebGL.

References

https://github.com/Dhruv-194/BoxShooterGame

https://medium.com/@s_van_laar/deploy-a-private-ipfs-network-on-ubuntu-in-5-steps-5aad95f7261b