Ludvig Lovén showed us how he created the Tetris simulation with UE5's Niagara, talked about the challenges of programming game logic on the GPU, and demonstrated the layers of the screen.
Hello! My name is Ludvig Lovén, and I’m the CEO and founder of Arvikasoft. We are a software services company focusing on Unreal Engine and digital twins. Recently, we got accepted into the Unreal Engine Service Partner Program, which is a huge milestone for us!
Before I found Unreal I trained as a Civil Engineer. In my work, I did 3D visualizations as well as application programming for CAD systems.
I first got into Unreal Engine in late 2014. I was working at a Swedish engineering firm called ÅF (now AFRY) as a BIM Strategist. The Swedish Transport Administration needed a high-fidelity interactive model of a 160km-long railway, so we started looking for software that could handle this. After evaluating different game engines and other software, we settled on creating a custom application in Unreal Engine.
As time went on I got more and more in-depth with Unreal and transitioned into a Lead Developer role.
Later, I worked at WSP where we created the ADTLink plugin for Unreal, linking Azure Digital Twins to Unreal. It was funded by an Epic MegaGrant, and I hosted a webinar for Epic Games called “Visualizing Data in Digital Twins”. This was also the first project where I used Niagara particles.
Last year, I started Arvikasoft together with my colleague Samuel Engström, who has also worked on all the projects mentioned above.
Unreal Engine 5
There’s no quick and easy way to master Unreal Engine. The engine is huge and it’s almost impossible to keep up to speed on all the different systems. I learned by doing research, solving problems one at a time, and building up my bank of knowledge over the years. Basically googling “Unreal how to” times 1000. It helps if you have a solid foundation in computer science and math.
The biggest motivator is of course having paid work where you need to accomplish something, but if not, I would suggest setting a goal for yourself (I am going to create XX using YY) and seeing how far you get.
I would say one of the biggest strengths of Unreal is how fully featured it is. Blueprints is a very capable tool, so for most projects, you don’t need to touch C++ at all. There are also tons of built-in tools for animation, modeling, sound, and so on.
The Tetris Project
As mentioned above, you can do a ton with just Unreal. For example, in the Tetris project, I created all sound and music procedurally using Metasounds. The only external piece of software I used was MS Paint for the art.
MetaSounds graph for the sounds and music in the project
The idea for the Tetris first came to me after I saw the Snake material that Alon Rubin created. At the time, I wanted to do a project in Niagara but didn’t know what. I had previously created some Niagara GPU sims for other projects, and I wondered how far it was possible to take it.
When I started the project, I wasn’t sure it would be possible to achieve a playable game. I had no examples to look at so had to figure it out myself, one thing at a time.
The challenge with programming game logic on the GPU is that it works very differently from CPU coding. It’s not object-oriented in the same way so the concept of a “Tetris Piece Class” does not exist, and each step of the simulation needs to iterate over all 200 spaces on the board each step. Also, you can’t do loops or breakpoints.
On to another reason why I wanted to do this. A challenge we are faced with as a company is that the cool work we do for clients is almost always under NDA, meaning we can’t show it or talk about it publicly. Projects like this are a way for us to get some visibility and show off what we can do.
The first thing you should do with a big problem like this is break it down into smaller ones. I started solving problems one by one. First things like rendering a tetromino, handling input, and moving pieces. On to more difficult problems like clearing rows and checking if rotations are valid.
I am using a 10x20 tile Render Target to represent the persistent state of the board. I have separate emitters for the background, next piece render, level lines, and score counters, and one for the main Tetris board.
For the GPU simulation stages, I’m using another 10x20 Grid2D, which has separate attribute layers for the current piece, the current piece if it were rotated, and a “working area” layer for clearing lines before the result is drawn back to the persistent render target.
For each frame, the simulation goes through the stack of GPU simulation stages in the emitter. It checks if I’m pressing an input key, if the move I’m trying to make is valid, and if a piece has landed and should be rendered to the persistent render target.
Then it checks if I have completed a row and updates the score accordingly.
For the sounds, I am using a Particle Data Export interface to blueprint to check if pieces have moved or rotated or the board state has changed and a sound should be played.
Niagara and emitters
Ray tracing is built into UE5, so you just check some boxes in the project settings, lights, and materials and you’re good to go. Then you need to set up your materials to be physically accurate and react to the light properly.
The screen is made of three layers. First, a solid color background, then the LCD pixels, and finally the screen glass. Each of these is a separate object, with physical distance between them. I tried to set everything up as physically accurately as I could so that the pixels cast soft shadows on the background, similar to what would happen on a real LCD screen.
I did not keep track of the exact time spent but I’d say it was around 80 hours including creating all textures, sound, and music. If you count the time lying awake at night thinking about how to rotate a Tetris piece, there's a lot more.
On our website, you can find a playable demo for download as well as a YouTube video where I walk you through the whole project.