Warning: Below text contains technicalities. If You are just interested in playing Creatura - TL;DR: Update is coming, performance will be better, unique order of words and numbers achieved this. Thanks for the attention, now for the actual post:

When my work on Creatura started in 2016, the priority was to keep the game performance high. In a game where selecting plants is part of gameplay, the amount of plants that can be displayed at once becomes bound to difficulty level, giving advantage to people with rigs powerful enough to render millions of nodes without the simulation slowing down to keep the frame rate stable.
Over the course of 5 years between the prototype and 1.0 release, computer hardware got more powerful, the game gained many more features, and became more complex visually. While the performance would be considered good enough by ~2015 standards, now with screens capable of 300FPS+, Nintendo Switch release coming soon, and the GPUs limited availability, 60FPS is just not good enough anymore. An optimization was necessary.
Any framerate improvement in an already developed game is a success.
A 20%-40% gain can be considered a huge optimization. Anything beyond requires a radical new approach to code functionality, since no simple solutions (like just reducing the number of operations per frame) can itself help that much. For computationally heavy tasks there is always the premise of multithreading, but in the case of Creatura, most of the weight was put on the GPU, required to render thousands of different plants, composed of thousands of unique nodes in various states of growth.
One of the solutions was to reduce the draw calls count. Instead of drawing each leaf and stalk, one after another, the game combined all of the growing and grown nodes from a plant into a single mesh, in theory cutting the need for a graphics card to just perform one draw call per each plant in the tank. However, this solution had many issues. Still growing nodes couldn't be efficiently combined, to avoid further increasing number of draw calls material variations in a single plant were considerably limited, and the whole system was incredibly complex, with a constant stream of meshes coming in and out of combine queue, and GPU memory was bogged down with moving around millions of vertices every frame. Countless hours went into creating and maintaining it, even more were required to fix the problems it caused, and frankly - it simply wasn't good enough.
Everyone likes grass.
After the implementation of grass bags, the statistics were obvious - players were attempting to cover the ground with grass or algae, with thousands of simple, but still draw-call consuming plants. With some micro-optimizations, code reduction, or straight trickery, I could probably find an additional 10 to 15 more FPS, but that's just not much room for growth (literally). Even on fairly beefy computers, the built-in benchmark would bog down to around 80FPS, with many milliseconds short to achieve modern refresh rates. My initial approach to optimization was correct, reducing the number of draw calls was an answer to high draw calls count, but the original "fix" was too naive, and wasn't scaling up. I could however, stop batching plants, and start to batch unique node types together.
In Creatura, many plant nodes share the same mesh. The textures are different, giving them unique shapes and aesthetics, but the vertices positions are uniform. This allows mesh batching. While there are some variations (hardwood leafs have different shape to softwood, stalks use unique meshes, etc) the total number of unique plant meshes in game is still under 100, much below the number of plants an involved player can grow at once. Even in most complex vivariums, consisting of tens of thousands of plants, the performance should still be comparable to a tank with less than 100 plants. And that would be a massive improvement.
No solution is perfect.
By skipping the rendering pipeline built into the engine and tapping directly into the GPU API, manual memory and render management is required. That creates overhead, and doesnt work on the very old machines without compute buffers support. Performance-wise however, the benchmarks seem to show improvement in order of 2x to 3x. This isn't the gain of a couple frames per second here and there - the frame rate realistically has at least doubled.
There are still quirks to iron out, and undoubtedly this solution will introduce many bugs to fix, but it seems to be more than worth it. Vivariums consisting of many more plants can radically change the gameplay experience, and allow new features to get implemented. Lower-end machine should be now able to play in comfortable, constant high frame rates, and the more powerful rigs will be able to run Creatura much smoother, with less energy consumed, perfect to let it run in a window on a side.
Creatura 1.1 should be available for testers on the nightly branch soon, and the update will get hopefully released early next month. Thanks, and hope Youll have soon a lot of fun with much more filled tanks.
[ 2021-06-22 20:48:51 CET ] [ Original post ]