How to create a skydome for your game with Blender.


In my latest game Get off my Lawn! I added a skydome that shows a rendered image. Because the styles of the 3D geometry and the game itself are the same it looks as of the entire world is rendered. I have worked as a 3D modeler in the past but have never done anything like this before. I’ve learned everything in this tutorial recently and I believe it might be useful for more people to add great background to your 3D games and apps.

Equirectangular Image

This game is built with the Town Pack from Synty Studios . In the end, I pretty much recreated everything for the game to reduce a lot of polygons. But, for the background, I used an example scene from the pack. I just removed everything I didn’t want in the render. So the rendering process would be a bit faster and not have things in the rendering that otherwise would be too close to the camera.

By default, there’s no background in the renderings in Blender. I wanted to have a clear sky. Luckily there’s one in Blender. To add one, you’ll have to go to the World Properties and add a Sky Texture by clicking on the yellow dot next to Color. Make sure the render engine is set to Cycles in the Render Properties otherwise the sky won’t render. Then, I kept changing the value of the Sky Texture until I was happy with the way the sky looked. I made the Sun Size a lot smaller and lowered the Air and Dust values. I changed the Sun Elevation and Sun Rotation in such a way that the sun would appear in the same place as the light in the scene would originate from.

Now that there’s a scene and a background it’s time to render the skydome. A normal camera won’t work in our use case. Luckily there’s a camera setting in Blender that can be used for these cases. In the demo scene, I placed a camera roughly where the player would stand while playing the game. Under Lens select the Panoramic Type and Equirectangular Panorama Type

To get the background sharp and crisp we need to render a very big image. I’ve set mine to 4096 by 2160 pixels.

After rendering the image should look something along these lines. It’s an image that can be projected onto the inside of a sphere and can be around your 3D scene. Keep in mind that this image might be pretty big in size.

Creating a Skydome

Depending on the framework you are using it might not be needed to create custom geometry for your skydome. For example, A-Frame has a Sky component that can be textured with the skydome texture we just created. But, for anyone that doesn’t have that luxury, here’s how to use the skydome anywhere.

First, we need to stay in Blender for a little bit longer and create a new Blendfile with everything deleted. Next, create a sphere. A big one. In Get Off My Lawn! the sphere has a 100m radius, thus it’ll be about 100m away from the player in every direction. This way there’s never anything clipping through the sphere. I added the previously rendered image as a texture map to the sphere. (If anyone has trouble doing this, let me know and I’ll do a separate post on UV mapping.).

Now before we export, there’s one tricky thing we need to do. It’s not visible in Blender by default, but most engines only render the front side of the faces of the object. Backsides are normally not visible. But since we will be standing INSIDE the sphere we need to see all the backsides. So, we’ll need to flip all the faces of the sphere. To do this, select the sphere in Blender and hit Tab to enter edit mode. Hit A to select everything and then hit ALT+N to get to the normals menu. Select Flip to flip all the normals around, thus making them point inwards.

Normals are used to determine the in- or outside of the faces. It’s very hard to see this in Blender, but there’s a little trick to make it really visible. This can also be used to “debug” issues with faces in models. To see the orientation of the faces you can enable the Face Orientation Overlay. This can be found by clicking on the overlay dropdown on the editor.

By checking that little checkbox the editor will add a blue or red color to the faces, where the blue faces are pointing towards you and the red faces away. In this case, when we look at the entire sphere from the outside it should be completely red.

And when we move inside the sphere, everything should be blue.

Great! The last thing to do is export the sphere to FBX through File->Export->FBX.

The sphere is ready to use now.

SkyDome in Wonderland

To use the skydome in Wonderland Editor just drag and drop the .fbx file into the /models folder. And then drag and drop it into your project. We don’t want the skydome to be affected by lighting. We need to make sure the pipeline of the material of the skydome is set to Flat Opaque Textured. You can do this by selecting it in the dropdown.

Now your skydome is ready to be admired in VR and all that there’s left to do is add everything else to make it into a game.

To hide the horizon of the skydome I used a big fence that fits the game perfectly. If you don’t have that option you might want to add other geometry close to the camera to hide it.

Wrap up

That’s pretty much all that there’s to it. If you want to have a look at this skydome in action, go to Get off my lawn! at Construct Arcade . Let me know if you have any questions or if you have requests for other tutorials.

Making money with your WebXR games


Making some money with your WebXR can be really tough. Selling any web game is already hard, but doing that in a VR headset is near impossible. Unless you maybe add your credit card to Facebook or type it into the browser in your headset. Traditional ads like Google Ads are also not going to work. There are only shown in desktop mode and are not going to work in VR. They also look really bad most of the time and have very low payouts.

Zesty solves this problem in a very modern and unique way using blockchain technology, NFTs, and smart contracts. This sounds really complicated, but you don’t have to know any details about all of this to use it in your apps.

This blog post is not sponsored. I believe in the platform and think it can become a really big thing. With more people joining the platform and more games using the ads, we all benefit.

How does it work?

On the Zesty Market developers can create spaces they can auction for ads. Other people can have their ad shown in that space in VR in your app. Think of this as renting out a billboard.

The Zesty Market uses a Dutch Auction model where the price declines over time until it reaches 0 at the moment the space expires. You can specify the price, the timeslot, and the moment the auction starts.

The ad spaces are tokenized into NFTs. NFTs have a really bad name from people selling stupid images for millions of dollars, but there’s more to it than just that. NFTs are a safe way of storing anything digital, including music, drawings, or ad spaces.

The goal of Zesty is to provide creators with a method of capturing the value they create on a decentralized platform. They hope to one day be able to exit the community and have the platform owned by the community of creators and advertisers.

How to use it in your game?

To use an ad space in your game, you need a few things. First of all, you need a crypto wallet. I use MetaMask connected to the Polygon network .

By connecting Zesty to your wallet you are logged in and you can start creating your ad spaces. To create an ad space on the Zesty Market you’ll need to enter a few things like an example image, a name, the URL to your game, and a description. I usually create a screenshot from VR with an ad shown in my app by just using an example code and edit something in the same spot afterward. When everything is entered you need to approve and deposit the NFT to the Zesty Smart Contract. At this point, you need to have a few Matic in your wallet. Every interaction with the network will cost a couple of cents in fees, also known as gas. You might have looked at NFTs on the Ethereum network at some point in time. Gas prices on Ethereum are 10s of dollars, sometimes even 100s. On the Polygon network, it’s 0.01s of dollars. If you like to read a more detailed tutorial on creating an ad space, you should check out the Zesty documentation on the subject .

Now that you have an ad space, you need to integrate it into your WebXR game. Well, I mention WebXR game, but you can also use the ads in your website, in Unity games, on Crytovoxel, Decentraland, or Muse and even OBS is supported. Integration in WebXR is supported in the most used frameworks, like A-Frame, Babylon.js React Three Fiber, Three.js, and Wonderland Engine (as shown in the image below).

You don’t have to struggle with figuring out how to get the integration with one of these frameworks to work. Zesty is generating examples on the fly with the spaces you created. In the screenshot below you can see an example of how to integrate it into an A-Frame project. All you have to do is copy-paste a few lines of code to get it to work.

From that point on you can integrate the ad into your VR world. You can place it in a nice visual place below the main menu for example. I prefer to really find a nice spot, like a picture on the wall. This way the ads are not annoying like they are on most web pages that have ads.

Whenever an ad is shown or when a user clicks on it there’s a notification sent to Zesty. When you have the Beacon turned on anyone can see how the ads are doing. To have people place their ads in your space you have to create an auction time slots. You decide the duration of a timeslot and you decide how long before the slot expires the auction starts. I’m still experimenting a little bit with different durations. But, for my best performing game Back to Space , I have time slots of 1 day. I recently started opening the auctions 1 week before the slots expire. You have options to start directly or 3 days to 4 weeks before they expire. Don’t be afraid to experiment with different prices. Mine range from 10$ to 25$ a day. As the auction runs the price will drop until you accept the bid.

Now that you have rented out a space and that time has passed you get the amount of money you sold it for. You can find this on your dashboard. You can find the amount that you can claim and the amount that is coming through time slots that are not expired yet. These show in $, but the payout will be in USDC , a digital coin linked to the US Dollar. The amount will go to your wallet, MetaMask in my case. I’m not sure if I’m using the most efficient path, but I convert the USDC to Matic on MetaMask and then go through the Kraken exchange to get to euros and into my bank account as ‘real’ money. Keep in mind that every interaction with your crypto-money will cost a small fee. The route I’m taking only costs a few $, because I stay away from Ethereum.


If you have any questions on how to set things up feel free to ask. Just hit me up through the Zesty Discord and I’m happy to help you get going on the platform.

VR Controller Haptics in WebXR


You might have noticed that when you are playing games on your VR headset, you can feel the controller vibrating. This haptic feedback is a great way to get a little bit of extra feeling when you are playing. Here’s how you can add it to your WebXR game. In this tutorial, I’m showing how to use haptics in a Wonderland component, but the part that is actually sending a pulse to the controller is not specific to Wonderland. If you’re looking for an example in A-Frame, you can find it in a game I build a while ago for the GameDevJS Game Jam.

Haptic Feedback API

In the WebXR Device API, there’s no support for haptic feedback, but instead,you can use the Gamepad API for it . The support is still experimental, but since it is implemented in the Meta browser it should be safe to use. The slightly difficult part is that you need to get access to the Gamepad API, luckily you can get that through the WebXR Device API.

Getting to the Gamepad API

As an example, I’m going to add a little vibration of the controller to a shooting component. To handle the input from the controller I’m using the default Input component of Wonderland. When the ‘gun’ component is added to the same object as the input component we can access it very easily.

I’d like to “shoot” my gun when I pull the trigger of the controller. There’s an event on the WebXR session we can subscribe to, the ‘select’ event . This event is not specific to any framework. We can get access to the WebXR session in Wonderland when the app switches to VR mode by using WL.onXRSessionStart. The ‘session’ object is passed as a parameter to the callback function. You can see this in context in lines 6 and 8 of the code example below .

To get access to the gamepad, we get use the parameter ‘inputSource’ of the ‘select’ event callback. The ‘inputSource’ contains a lot of information about the input, but we are only interested in the ‘gamepad’ property and the ‘handedness’. The ‘handedness’ is either the left or the right hand and we just use this property to check if we are about to vibrate the correct controller.

Once we have the gamepad object we pass this off to a function that will handle the haptic feedback, pulse in this case.


The get the controller to vibrate we use the <code>pulse</code> function . This function takes two parameters, the first is the duration of the pulse and the second is the strength of the pulse. The strength is a value between 0 and 1. The duration is in milliseconds. The pulse function can be found on the ‘hapticActuators’ array on the gamepad object. There could be more than 1 haptic actuator, but we’re just going to assume we only need the first one. If there’s none we just return out of the pulse function. You can find the entire function in lines 20 to 26 in the example below.

Complete Example

The example below shows a component I’ve reused in pretty much all my Wonderland games in some shape or form. Extra to the description above, I’ve made sure the ‘select event’ is only added once. If the app switches to VR a second time, the initialized variable is already set thus the event is not added again.

Assets from Unreal in WebXR


Although it’s not possible to export from Unreal to WebXR, there are a lot of very nice assets available in the Unreal Marketplace that could be useful for your WebXR game. The license allows you to use these assets in your game, except for products that have been created by Epic Games themselves. But, since Unreal Engine uses its own format for assets it’s not straightforward.


There are a lot of great free assets in the Unreal Marketplace. But, they can even get better. Every first Tuesday of the month, there’s a new set of assets available for free that would normally cost money: Free for the month . Even if you don’t need the assets right now, they might become handy at a later moment. If you’ve bought them for free they stay yours after the month is over and they return back to their normal price.

Unreal Engine

I’m going to assume you never have really used Unreal Engine before, otherwise, you probably won’t have ended up here. It could be a little bit of work to get everything to work, especially if the textures are in TGA format. But, it’s worth it. My Christmas-themed game Santa&rsquo;s Workshop is built using an Unreal asset. I took the gamble to buy it and it worked out great.

First of all, you need to have the Unreal Engine installed on your computer. You can download it from here .

New Project

Now that you have the engine installed it’s time to launch it through the Epic Games Launcher and create a new project. As options, I just select Games, the Blank Template, and Blueprint. I don’t think it matters since we’re not using anything of Unreal except the exporter. I usually name the project after the asset I’m going to export.

Add Asset

To add the asset we want in a WebXR project, we need to go back to the Epic Games Launcher and look it up in the marketplace, or the library if you have already bought it. After you’ve found it you just click Add to Project and select the project you want to add the asset to. If you haven’t used the asset before it will be downloaded.

Export Models

Now that the assets are in the project you need to open it again and look for them in the content browser, usually at the bottom of the screen. Once you’ve found the folder containing the models or meshes, you need to select them all. This can be done by hitting CTRL+A. Then you Right Click and from the context menu select Asset Actions -> Bulk Export. You need to select a folder you want to export the assets to. Keep in mind that you can only export one folder at a time. You need to repeat the process for every folder. There are a few options you need to disable in the export. You don’t need Level of Detail, Collision and Preview Mesh as these will add geometry you probably don’t need.

Export Textures

The textures are not inside the models, therefore you need to export them separately. The process is the same as the models. The folder structure is the same as the folder structure in the asset pack. If you place the textures in the same place as you did with the models they end up following the correct structure.

Convert .tga to .png

There’s a big chance the textures you’ve exported in the previous step are in .tga (Targa) format. The tool you are going to use the models with is probably not going to support .tga files. If you’re going to build a level in Blender and bake your lighting it’s not necessary to convert the textures, because Blender supports TGA and in the export of the bake you can select to use .png.

For converting the textures I use a free tool called XnConvert, which can be downloaded here . In that tool, you can select a folder and it will recursively search for all the .tga files and convert them to .png.

After selecting the folders you can go to the output tab, change the format to .png

Use the assets

Now that you have the assets you can use them in your game. Keep in mind that the materials on the models are broken since they’re converted to .png. You need to fix them manually in the game engine you’re using.

Custom templates for Wonderland Editor


A lesser-known feature of Wonderland Engine is the ability to use custom templates. In this quick post, I’ll show you how I created my own.


If you’re just here for the download 👉 This is the Template .

Extract the zip file in %appdata%\Roaming\WonderlandEngine\Templates and you’re good to go.

The Template

By default, a template in Wonderland is not any different than a normal project. The easiest way to reuse something is to just copy a project to the %appdata%\Roaming\WonderlandEngine\Templates folder. You don’t need to copy the deploy folder since that is automatically created when building the project. Scripts and assets that you often use can be included in the template.

When instantiating a new project, Wonderland renames the .wlp file and renames it internally as well.

But that’s not enough for me.

Sorskoot Template

In my projects, I use a little bit more. I’m using npm to manage my dependencies and I’m using RxJS to manage state in my games. I have a global object that is named after my game and I’m not even using the default esbuild to build the project but have some custom Webpack set up. And then there are a couple of components and utilities I use all the time, for music, sound effects, and other things.

To get this to work I created a little Gulp script. The biggest challenge in this was to run it automatically. I’m pretty lazy when it comes to things like this. It’s the whole reason I wanted my own template in the first place. Luckily for me, it turned out there’s a default npm script that is executed when after an npm install, postinstall. If that script is defined in your package.json it will be executed automatically.

My little Gulp script renames the main bundle file I’m using. It reads the name of the project from the .wlp file (this is just a nice json file 😊). After that, it scans all .js files and a few .json files for the SorskootBasicTemplate, the name of the template. It then replaces this string with the project name found in the .wlp file. It checks if the bundle is there with the original name, to prevent the script from running twice.

Current limitations

Wonderland does not run npm install automatically when a new project is created. This means you’ll have to exit the editor after creating the project and run it. After the installation can restart the editor and load your project.