Welcome back to our latest developer update and the second part of the character editorinsight series, in which we are giving you a look behind the curtains of our character art pipeline as well as its main challenge: Creating a gorgeous-looking, visual art style for our characters, while at the same time meeting the strict performance goals that we set ourselves (to ensure good performance for all of our players).
While in the last part of the series (#1 The visual art challenge: Bringing your heroes to life), we investigated the visuals of our characters, in this part we will focus on the features of the character editor as well as the technical details that come along with it.
So, let’s dive right into it!
The Technical Setup
To build the fundamentals of our character editor, we first had to determine the parts of the character that we wanted to be able to modify. So, we started by defining separate regions on the characters' face and their body, that should be swappable. These regions include body features like hair, eyes, and ears, as well as clothing such as chestpieces, gauntlets, or boots.
Another fundamental decision that we made for our character editor was that the clothing pieces should fit all classes:
If a wizard wants to wear heavy chainmail, why not let them?
Now, with our zones identified, we were able to swap out each of them individually. In theory, our characters can now mix and match their outfits with different hairstyles, chest pieces, boots, gauntlets, etc.
Character editor completed & adventure finished?
Sadly, far from it! With this system in place there are two main issues that still exist and need solving:
- Layered clothing
So, let’s take a deeper look into these two problems: Why do they exist and how did we solve them?
When we compare our existing barbarian design with the design of this monk over here, we can already see one fundamental difference:
The zones we have defined for the barbarian are completelydifferentin size compared to the monk. Not only are the monk’s sandals much shorter (barely going above the ankle), than the barbarian’s boots (almost reaching up to the knee), but the barbarian’s boots are also much thicker than the monk’s sandals! Now, what would happen if we simply swapped out the barbarian’s boots with the monk’s sandals?
By default, if we would swap out the boots with the sandals, there would be missing information for the shin region, leading to a rather disturbing result:
Of course, the easiest solution here would be to simply disallow shoes to come in different sizes! That would mean creating a system where all clothing pieces are of the same size.
While a system like this would fix the problem and is also commonly used in other games, we wanted to push the amount of flexibility not only for our artists but also for the players, when designing their characters. So that we can allow a wider variety of character designs:
So, after investing some time into R&D we came up with a much more flexible solution:
By creating a layered clothing system, we allowed our clothing assets to be created independently of the region's sizes.
That means that our artists can create overlapping clothing pieces (e.g., very high boots, very long pants) and dynamically cut away the unwanted areas of each clothing piece depending on the other equipped clothes.
Normally overlapping clothes create frequent clipping (see image below), but by tagging each component with identifiers as well as a thickness level, we can compare these thickness levels and cut away the thinner component.
In the following example, the boots are thicker than the pants, so the pants should be tucked into the boots. Without a layered clothing system, the pants and boots would look like this:
In our case, the layered clothing system that we have created automatically hides the pants at the region, where they would intersect!
While this looks quite simple, the system actually needs to do quite A LOT of technical-art-magictm to handle all the edge cases that come along with the layered clothing (What happens if you have skin showing through a clothing piece? What happens to assets that vary in thickness within their own region: e.g., a knight’s gauntlet that has very thick hand elements but only thin cloth elements above the wrist?)
Nevertheless, our team was able to overcome all of those challenges and we are very happy with the current pipeline and its flexibility regarding layered clothing. Awesome job everyone!
However, with this issue solved, there was yet another main problem to be tackled:
“This all sounds very cool and customizable but will it run without burning through my graphics card?” you may ask.
It is very true that performance is critical, especially for VR games. Thus, a lot of thought went into the process of optimizing our characters and their clothing. Given that optimization is a completely different topic in itself, we want to focus on the main bottleneck with this system: Draw calls.
“What are draw calls?” I hear you asking.
A great indicator of the performance cost is how often the CPU (Processor) has to tell the GPU (Graphics Card) how and where to draw meshes on the screen, usually referred to as “draw calls”. Since those commands to the GPU are quite expensive, when it comes to performance, you try to reduce them as much as possible.
Now, that our characters are made up of almost dozens of individual meshes, stitched together, you can already see where the problem is: Our character who was just 1 draw call before now needs over 10 draw calls for each of their regions! Additionally, each “material” (the textures that give colors and patterns to our character) requires 1 additional draw call, leading to a sum of around 20 draw calls!
This means with 10 characters on screen we would have almost 200 draw calls instead of 20 (including draw calls for the materials)!
While the example above is quite simplified the main issue is clear: we need to reduce the draw calls!
So, what did we do?
We were able to lower the number of draw calls to a minimum by combining the textures and meshes of our character. This means that instead of one or more draw calls for every region (which would be the case if every region had its very own texture or mesh), the CPU issues just two draw call for the whole character!
This combining does come at a cost though! While the runtime performance (when actively playing) is much better now, the actual combining and merging of the character are fairly resource intense, which means additional loading times. However, the process of combining meshes and textures happens within the CPU itself. We can actively optimize it and run those calculations in parallel for a significantly better performance!
The result is a much more efficient character editor that can craft performant characters with little to no loading times.
We could continue for hours about various technical details and optimizations that we deployed (like our solution for optimizing textures), however, given the length of this post already (comment “Rolling constitution saving throw!” if you are still reading!) we will end this community update on this note.
Nevertheless, we hope that this insight wasn’t too technical for you and that you enjoyed reading about our character editor! Of course, we will beactive on Discord for feedback, questions, and just, in general, hanging out with you guys!
And if you haven't already: Don't forget to wishlist DfD on Steam to support the development team!
Thank you very much for reading this community update, and as always:
We are truly looking forward to seeing you inside DFD!
- Your TxK Gaming Team