DirectX 12 as a cross-platform graphics API?

I think it’s best to use graphics API directly instead of using wrappers like bgfx, sokol, Diligent Engine and so on. Best performance and latency can be achieved by fine tuning the rendering flow (especially with modern API’s) when using graphics API directly. And then on top of that, have a clear specification to work on. But those wrappers provide one big benefits, cross-platform support. Also one big downside with modern APIs is that one needs really to know what you are doing with it to get the benefits over DirectX 11 or OpenGL.

So Vulkan is known to be cross-platform but what about DX12? With some help it seems that it can support every popular modern platform, but PS4/PS5?

Thanks to rising popularity of Linux gaming the quality of DX12 to Vulkan wrapper VKD3D-Proton is very high so I would not hesitate in using it.

  • Windows 10+ and XBOX directly trough DX12. Windows can be also provided with Vulkan backend through VKD3D-Proton.
  • Linux, Nintendo Switch, Steam Deck and Android trough Vulkan using VKD3D-Proton.
  • MacOS and iOS trough Metal using MoltenVK and VKD3D-Proton.

It would be interesting to test this in practice. MacOS and iOS might be bit stretching it to get to work and debug through two layers.

Paradox of choice in software development

There is so much to choose in today’s software world even compared to 10 years ago. And it’s growing very fast, new libraries and languages pop up everyday. Should thing A be built from ground up or just use library X, Y or Z instead? What about programming language? Do I need to support this and that, etc.

I think the only way to make good choices is to have actual experience in said choice. But in the end, I think every choice is valid if one has right justification for it. And what right is comes down to one’s feeling, experience and company guides or culture. If one can find clear focus and zen of choosing then software development becomes much easier.

It’s hard or impossible to make right choices as in the end, you don’t know what you don’t know 🙂

Thoughts on efficiently solo developing a game without an game engine

I started prototyping a 2D game with Unity. And soon ran to performance and scalability issues using the build-in systems (Tilemap etc). To battle those issues I would need to build custom systems for those anyway, so I again decided to move to just plain C++. The game world is procedurally generated so luckily I don’t need a dedicated editor. As the project begun, I tried to focus on building a game instead of starting building a game framework (entity systems, filesystems, other abstractions etc..).

To reduce boilerplate as much as possible and to make refactoring fast and easy, I don’t use C++ headers for my code. I have one .cpp file that is compiled. That file includes all other .cpp dependencies I have. Much of the game code resides in a single .cpp file which is now around 5000 lines long. I have a build.bat that just uses the MSVC compiler and only use Visual Studio for debugging purposes.

In my code I don’t use classes at all. Just plain structs and functions. I do use templated structs and functions for arrays. I don’t use STL at the moment. Basically, I only use dynamic or fixed array as a container, so I wrote support that myself. I avoid abstraction as much as possible and only do it when it clearly improves code readability and understanding. I do use third-party libraries such as SDL for windowing and input, stb_image for image loading, stb_truetype and fontstash for ASCII text rendering and bgfx for graphics.

This way has worked well for me, keep iteration time low and motivation up. Results come up fast and I don’t spend time thinking code structuring, abstractions, system refactoring. Or should the new class name be XYZManager. At the moment, time to compile and run the game is much lower than script reload and play in current Unity!

Lightmap baking on CPU using Embree and OpenImageDenoise

I wanted to have a portable lightmapper that is part of a custom map editor that I was building in C++. Thus I chose to build CPU powered lightmapper.

And to my amazement, it is really fast as OpenImageDenoise works like magic and the noisy CPU path tracer result gets smoothed out. The lightmapper is based on design described by the creator of Bakery-addon for Unity.

First, it creates the lightmap UV space GBuffer with multipass rendering to emulate conservative rasterization. Secondly, it offsets the sample position by raytracing from each sample position. It checks if the sample position resides inside geometry and offsets it to redure shadow leaks. Thirdly, using Embree it path traces from the sample positions and builds the lightmap. Finally, the lightmap is filtered using the OpenImageDenoiser.

The only downside is that the OpenImageDenoise is huge. The .dll takes around 45 megabytes (compared to my exe ~700KB). Anyway, I think it is worth having as it speeds up the path tracing result significantly. Here is a screenshot of preliminary result.

Denoised lightmap result in 20 seconds on Intel i7-5820k

Developing own custom game engine from scratch in 2021

Unreal Engine 5 is soon to be released with new groundbreaking features, Unity dark mode is finally free and Godot 4 plans to take over the indie gamedev community. Why as an indie dev, would you skip all of those (plus many other production-ready game engines) and build your own custom game engine in 2021?

Next, I go through some decision reasons of choosing between Unity / Unreal / Godot vs Custom Game Engine. Lastly, I go over the reasons why I did choose to build my own custom game engine for my game project.

When it is better to use Unity / Unreal / Godot?

A cross-platform game

Cross-platform is hard to get right even for seasoned developers as there are many moving blocks and undefined behavior. Most popular game engines are already tested and have built-in workaround for many issues.

Proper asset content pipeline

If your game depends on many imported 3D models, animations, collision and materials it is crucial to have working content pipeline and asset authoring system. Content pipeline transform the imported 3D models and textures to game engine specific data format. If you want to import wide amount of different 3D model formats and have working texture compression, you might want to use off-the-shelf game engine.

Realistic or next-gen graphics

As an indie, it would be hard to stay at the same levels or even bring a new game engine to the levels of current off-the-shelf game engines.

Build in the shortest time possible

It is hard to beat time-to-market with a custom engine. This doesn’t need any explanations.

Find people with existing skills to use the engine

When you bring new people to the team in the later stages of the game’s development, you will be better of when they would have experience from the game engine you are using.

Mobile game that ships for Android

It’s pain in the ass to develop OpenGL ES for Android. Be prepared for graphics issues. There are so many different phones and OpenGL drivers with undefined or wrong behavior. I would chose proven game engine for mobile games (Unity / Defold).

No specific or good reasoning for building a custom engine

Lastly, if you don’t find any good reasons business or game design wise to develop a game engine.

When it is viable to build a custom game engine?

Fine-tuning underlying technical side

You need to tinker the fine details to have the minimal possible game distribution size and achieve the best performance. When you have access to source code, you can customize or optimize the whole stack from raw input to rendering. This is also possible on off-the-self engine, if you have access to the engines source code.

Needs are well known before building the game

You can estimate the features needed for the game engine to build the game. This way you can have rough estimate, how long it will take to build the engine. And how big of a job it is to build the game engine.

Content pipeline is simple and limited

For example, if your game design allows you to stick with one 3D model format and exclude textures with alpha.

No next-gen graphics

This is self-explanatory. Sometimes less is more.

Game development will take more than two years or you want to provide updates for the game many years after the game release

After starting to build with Unreal / Unity / Godot, those will receive updates and the upgrade process for your game can bring game breaking changes that would need reworking levels and/or game mechanics. I have seen this happen for AAA game.

Why I have chosen to build custom game engine for my game project?

Achieve lowest possible network and input lag

I need to have full control over the rendering loop, present swapchain and also input polling to fine tune the input and network latency.

Ultra-light and ultra-fast

I want the game to be small in distribution size, have ultra-fast start-up time and minimal loading times. Also the game performance should be excellent on low-end machines. I want the game to be non-intrusive, lightweight and accessible by people with low-end machines.

Simple visuals

This is both a game design choice and it also enables us realistically to develop custom game engine. I believe that visuals are very important but highly-realistic or candy graphics distract the core gameplay. Simple visuals also means simple content pipeline and simple rendering engine for the game engine.

Provide a map editor for the community

Yes, you can also build map editor with Unreal / Unity / Godot. But this comes as a bonus while building the map editor for the engine. It brings a bit more extra work to polish the editor for external users but I think it is worth it.

Long term project!

It is much easier to support future Windows versions and fix upcoming issues related to new hardware when I have control over the whole stack. If I would have chosen Unity or Unreal I would be stuck with the version we started to design with. If they would, for example, change the ray casting engine, physics engine, AI navigation engine or any core part of the engine in future versions, it could potentially change the gameplay drastically and to unwanted directions!

PC-only game

It easy to focus developing the game engine to support only single platform. By focusing on single platform, I miss the headache of developing cross-platform abstractions and separate implementations.

Software engineer first, game designer second.

In the end, I just like to tinker, read and develop things around new techniques and possibilities.

Sound and audio in competitive FPS game

Lately, I have been thinking sound design in my a multiplayer FPS game prototype.

Audio is very important in games. Sounds gives clues and reference about the current game situation and environment the listener is in. Both silence and high volume sounds have their places, but is important that the audio volume levels are correct.

In competitive FPS game, 3D positional audio plays important role when locating opponents. Headphones are must have to be competitive in multiplayer FPS game.

When working on the audio and sound design for my multiplayer FPS game, I take account the importance of audio occlusion, clues, directivity, effects and more.

Audio occlusion

Occlusion happens when there is physical obstacle (medium) between listener and audio source. Often the sound doesn’t completely get blocked because the sound either reflects from nearby walls which bounce the sound waves to the listener. Also lower frequency sound waves are good at traveling through mediums.

In games, audio occlusion test is often implemented using raycasting. Most likely a good estimation of audio occlusion is done by raycasting multiple lines from the listener to points near by the audio source. Path tracing can also be used to compute better reflection and realistic audio directivity.

In multiplayer FPS games, I argue that realistic audio directivity will cause confusion for the player. For example, gun shots or footstep audio should be seemed to be coming directly from the true audio source and not reflected from walls. Although it isn’t realistic, it is important from gameplay perspective to avoid confusing the player.

In my FPS game prototype, the audio occlusion implementation is still work-in-progress. Currently I use multiple raycast testing to define audio occlusion. The audio is simply low-pass filtered and reduced by volume depending on the obstace medium size.

Improving audio directivity with HRTF

For audio, I leverage OpenAL Soft audio library. It comes with an excellent HRTF (Head Related Transfer Function) implementation. In short, HRTF simulates how ears will hear the sound from a certain point in 3D world. Headphones has to be used when HRTF is enabled. With HRTF player gets much better immersion of the sound direction, especially on the up/down axis.

Minimizing input latency for games

I feel that input latency should be as minimal as possible. Input latency affects the game feel and is especially important when the game requires fast reactions, such as fast-paced multiplayer FPS game or racing sim.

I’m currently working on a project with custom game engine where low input latency is important. I take input latency seriously and do my best to minimize it. One part of minimizing input latency is to make the frame rendering as fast as possible.

How to minimize input latency

In order to minimize input latency, the game needs to postpone the frame’s input processing as late as possible before frame present. Also the game should only have single buffered present.

Naively by default, games use triple buffering. Triple buffering is best choice when smoothness and larger frametime budget is required. For example, when using single buffered present with 60hz screen, both the CPU and GPU must have computed the frame under 16.6ms to be ready for the next vblank.

When using double or triple buffering, both GPU and CPU have 16.6ms of time to process the frame, giving the best throughput with cost of additional latency. Thus single buffered rendering reduces the system parallelization. CPU has to wait for GPU to complete the present and then GPU has to wait for CPU to start pushing rendering commands.

In my current project, I use single buffered rendering. The game waits for GPU to complete present before processing input for next frame. This achieves theoretical input latency between 16.6ms – 33.2ms on 60hz refresh rate.

Angle Level – a simple level tool for iOS

At some time ago, I was looking for a level / clinometer app for iOS that could present the result with six digits of precision, with four decimal places (e.g. 12.3456). I could not find any, so I decided to build one myself.

It was already some three years ago I did my last iOS dev work with Obj-C. Angle Level would be my first complete app to be released at the App Store using Swift. SwiftUI was on its infancy still and some basic UI features was missing, so I went with the goold old UIKit. I build the UI completely in Swift code and aimed to look like a native app. To test how viable App Store is for this kinds of apps, I also monetized the app with basic IAP. Full precision with four decimal places can be unlocked using the IAP.

The final angle measurement is computed using temporal filtering. The app gathers result from 100+ accelometer samples and ditches the samples that deviate with predefined amount from the gathered samples. The measurement is complete after predefined minimum deviation threshold is achieved.

More detailed info of about the Angle Level app can be found at App Store.