XaiJu
oakfells
oakfells

patreon


Deep Dive - Clothing Color Customization

The 0.5.1 update introduced a big redesign of the clothing system, namely the separation of clothing into tops and bottoms, and customizable colors for every single piece of clothing. And to get to that last one, I went on a bit of a journey. A journey I thought would be interesting to share, especially for anyone interested in the actual process of game development, including the hurdles.

This one's a bit longer of a read, I ended up writing it as a sort of surface-level introduction to some basic concepts in art and image processing, so strap in!

How do you even do customizable colors in a game?

Before the clothing system update, the only clothing options in the game were the T-shirt, and a set of button-ups that were plain white, red, peach and finally dark blue.

Every single one of these shirts was edited and pre-rendered in painting software, meaning there were separate PNG files for all 4 shirts in the game files. This isn't great for several reasons:

This was the most straight-forward solution at the time: just create separate images for everything and leave it at that. However, if I wanted to do anything fancier, I was going to have to be smarter about things: I would have to change the color at run-time using code. Let's take a look at one of the ways we can do that.

Color Tint/Modulation

The game engine used by CoG offers a built-in solution to this called "color modulation". In practice, what it essentially does is tint the image using a color you give it.

This is actually what the game uses to color most of the player character. The hair, skin and eyes are all colored using this method.

If you're curious what this actually does on the technical side of things, it's just a Multiply filter. That is to say, it takes the RGB values of the original image, and multiplies them with the RGB values of the color.

There are quite a few shortcomings to this method, one of which is the fact that it's mostly only good at making images darker. Because of how it works, it works best when used on bright images, and in case of parts that are pure black, it is actually completely unable to affect it in any way.

However, there is one other, even more glaring issue.

Here comes a quick primer on color theory

Take a look at this: another version of the orange T-Shirt. I'll put it next to the one using the color tint so we can compare them:

They look quite different, but in reality they both actually use a similar base color. Despite that, the example on the left is far more vibrant, isn't it? Why don't we isolate some of the colors so we can take a closer look at what's going on?

Here are two palettes, each created from 4 colors: highlight, base, shadow, and finally the outline color.

Since we're already in the color theory learning territory, allow me to take you on a brief tangent about a pretty important color fact:

Notice how the outline color is also... well, a color, rather than pure black? Non-artists have a tendency to use pure black when drawing lines, because it seems like the obvious choice. In reality, you almost never want to resort to using pure black, unless making a conscious stylistic decision. There are several reasons for this:

And so ends my brief rant on the use of pure black in art. Now back to the shirts!

We know that they both have the same base color, and now we can also see the reason why they look so drastically different: it's because of the other surrounding colors.

In actuality, the base color means nearly nothing on its own . Color is heavily contextual and completely dependent on its surroundings. If you're familiar with a certain infamous dress taking the internet by storm back in the day, the discourse surrounding it was caused by exactly what we're talking about here.

Now let's take a look at the color palettes individually and see what they're doing:

Here's a chart that begins at the base color, and describes how the color changes as it gets brighter to the left, and darker to the right.

Now let's take a look at the tint's palette.

Ah... well... there's not much going on.

There are many "color models": ways to notate and write down colors using numbers that unambiguously describe said color. One of the most common models used by artists is HSL: Hue, Saturation, Lightness.

All of the issues of the palette mentioned above are caused by the same problem: the hue and saturation both remain the same across all four colors. The only thing that changes with each color is that the shade gets progressively darker.

If we mark the colors on a HSL color wheel, the pattern becomes obvious. The colors basically follow a straight line down. It's straight-forward, monotonous and uninteresting. This is a pretty common mistake many non-artists make when using MSPaint or the like: they simply drag the color down or up using the color picker.

Because all the colors have the same hue in this case, they can easily be written down in a single chart like this. But as for the mystery palette...

Well... it's not really possible to visualize properly in one image, so here are four color wheels, one for each of the colors. I've marked them in a way where you can see where each color stands in comparison to the three other ones.

If you take a look at the curve, it's almost like the colors used in the image tell an entire lil' journey of their own. That, coupled with the fact that they're all so much harder to even visualize as a diagram speaks volumes about the added complexity this palette has compared to the tinted one.

And to make it clear: the specific shifts in hue and saturation in this example aren't necessarily accurate to how they happen in real life, nor are they the only "correct" way to do it. For example another artist might choose to make the light part less saturated, or shift it towards a color other than yellow, or depending on how a scene is lit.

The main takeaway from this is that there is more to shadow and light than just... making the color lighter or darker. Hue and saturation are both very important factors because they're vehicles through which you can add a lot of variety and nuance.

Ok, so what now?

I've sold the color tint method short; clearly that wasn't the solution I went for. So then what other options are there? Next I decided to step back, and look into image processing and filtering options inside my image editing software to see if I could find some inspiration or new methods for playing around with color.

HSL Adjustment

This is one was a very half-assed solution I entertained for a bit. It does exactly what it sounds like: it takes all of the colors in an image and shifts their hue, saturation and lightness values by a specified amount.

It's a very clunky solution using a technique that... definitely isn't meant to be used for something like this.

It requires the base image to already be colored (...or else there is no color to shift in the first place). In the example above, I used a blue base, but something like light white with subtle blue-ish coloring would also work, and would most definitely be easier to work with, especially when attempting to shift it into some of the lighter color.

It'd still be awful all around though, as it often creates strange and unpleasant color hue combinations, and in some cases even off-putting color artifacts.

(Womp womp.)

Ah yes, the hue combinations. The only redeeming quality and the reason why I entertained this idea in the first place. Because we're shifting all of the colors around, this method retains the hue and saturation variety included in the original image.

... but even that positive was completely nullified by the fact that the direction of the hue change from base color to shadow was unchangeable.

In the base image (blue), the shadow moves towards purple, or "to the right" in a sense. Because of this, in the one of the bad result examples, the shadow of the olive shirt shifts in the same direction: towards yellow, rather than in the opposite direction towards red as I would want it to if I painted it by hand.

(Extra fact: notice how the olive color isn't green, like one might perceive. On the hue chart, it's actually nearly orange. Another practical example of how misleading and contextual color is.)

Alright, anyways: direction of the hue and saturation shift. Add that to the list of hurdles we need to overcome. What's next then?

Other color blending techniques 

If you're familiar with image editing software, then you're likely familiar with layer blending modes. The multiply used by the color tinting method is in fact one of the more basic and commonly used layer blending modes. So then I tried to see if any other blending modes could be of help.

However, every single one of them ran into the exact same issue as the earlier methods: strange hue and saturation changes, too bright/dark highlights or shadows, and just all around being unsuitable and duct-tapey solutions to this problem.

P A I N

There was also another issue with all of the above methods that I haven't mentioned until now: and that is the fact that all of them only work well for either light colors, or dark colors, but never both.

This is because light base colors tend to have more pronounced shadows, whereas darker base colors are already dark to begin with. It's this kind of difference in balance between light and shadow that really throws things it all off.

There is also the matter of certain colors inherently looking darker than others. For example yellow is inherently brighter than blue, which is inherently dark.

And with the hue shifting happening between the shadow, base and highlight, that only serves to make things more complicated.

At this point, it's become obvious that a different approach has to be taken. The reason why all of the above fail is because of one thing they have in common: they all just adjust the image as one whole. Color tinting tints everything in one color, and HSL adjustment shifts all the colors in the image by a certain uniform amount, same with any method that tries to blend the image with a single color.

No, what I need is far beyond simple color correction. I need to have full control over every color in the palette: base, shadow, highlight and outline. That way I can just manually deal with whatever intricacies each color comes with. So... is there any technique that can let me achieve something like that?

Say hello to "Gradient Mapping"

If you've used an image editing program or two, you may have heard of this before. It's a technique that was somewhat new to me at the time. I had heard about it from some of my artist acquaintances and played around with it for a few minutes, but ultimately I didn't see much of a use for it and promptly ended up forgetting about it.

... until now.

In short: gradient mapping is a technique that looks at all the pixels of a picture in black and white (+ the greys in-between) and maps them to a corresponding color on a gradient... that doesn't seem like a particularly great explanation, but hopefully the diagram gets the point across.

And... there we go! It's the perfect solution that does exactly what I was looking for: it allows me to map the shadow, base, highlight and outline to exactly the colors I need them to be. We got our solution, so now it's time to implement it.

Unlike the color tint, Godot has no built-in feature for gradient maps, so I'll have to make this one myself.

Luckily, there is at the very least a built-in Gradient type I can use, so all that's left to do is implement the algorithm that maps the gradient to the image at runtime.

When it comes to visual effects like these, a special type of code is used called shaders. Without getting too deep into it, shader code is very different compared to normal, conventional programming languages. It's incredibly hard to get into if you've only had experience with imperative programming, as it requires you to completely change the way you think about and approach things.

Thankfully I have a tiny bit of experience with shaders from playing around with them in my free time, the results of which you can even see in CoG in two places: the water in the fishing minigame, and the blur that appears during some of the hospital scenes.

(Both of these are done using shaders!) 

Not just that: the gradient mapping algorithm isn't even all that complicated! All it has to do is retrieve the brightness value from the image, and then use that to get a color of equivalent value from the gradient that's given to it. All of these are basically built-in functions of the shader language and can be done in no more than 12 lines of code!

Once that was done, all that was left for me to do was define the gradient for all... 44 colors of the palette that I ended up doing. Here are a few gradients for some of the colors available in the game!

 ... this part ended up being quite a hassle, because I ended up going through all of them several times and tweaking them day after day because I was almost never happy with how they looked. Even now, I'd say there's a very high possibility some will be tweaked at some point.

There's also one final thing we need to address with this solution, and that's clothing with more than one color. This can be seen on the hoodie with the inside of the hood and the drawstrings, but most notably the funky colors used in the plaid shirts:

Requiring multiple colors means separating the images into multiple layers. That way each part of a clothing piece can be colored separately.

Before, the game just loaded the clothing sprite on top of the character model, but now, multiple layers meant having to turn all the clothing into actual objects in the game that would then get spawned on top of the player character model.

In case of something like the plaid shirt, a piece clothing could have as many as six layers:

There's the shirt itself, then three different grid-esque layers to make up the plaid pattern, and finally the buttons and the T-shirt beneath.

Letting every single aspect of the plaid pattern be color customizable would be a nightmare from both an implementation and organizational/convenience standpoint... can you imagine how absurd the purchasing and equipping UI would look with that?

So I instead opted to go over all 44 of the colors from the palette and hand-pick the color combinations for each of them myself, resulting in 44 unique plaid colors. I decided to get quite wacky with some of them, so I hope someone out there with strange taste in color appreciates those.

Phew... and with that, the implementation was finally finished. Woo!

... the implementation that is.

The final steps

In reality, there was a massive amount of work waiting for me to be done before the update was ready to be pushed out, and it involved all of the old, existing clothing sprites - including glasses and hats.

None of them were in black and white, and because the gradient mapping method requires that all clothing uses the exact same, consistent values to map the 4 main colors to (base, shadow, highlight, outline), this meant that I had to go through each of them, convert them to black and white, and then adjust the contrast.

In some cases, simple level correction wasn't enough to fix it, meaning I had to actually sit down and put in the work to paint over the old sprites, which at least serendipitously led to me just completely scrapping and re-doing some of the more horrendous older sprites, such as the ball cap.

And after all that: finally, it was over...

Quite a lot of old code was rebuilt and updated in v0.5.1, but this one was probably one of the biggest ones. Because there was also the matter of separating clothes into pants and shirts, it pretty much meant I had to re-do the entire code architecture for handling clothes... which resulted in quite a few clothing-related glitches popping up in places where they didn't use to be.

Still, I'm very happy with the result. Putting all the sprites into the engine and plopping in the gradient to finally see the result after so much work setting it up was probably one of the most satisfying moments I've had working on this game.

Now the only question is... will I convert the rest of the player avatar pieces to this system? At the top of the post, I just so happened to mention before immediately brushing past the fact that the hair, skin and eye color customization all still use the old color tint method.

...

.. well, I'll take a break from retouching hundreds of old sprite assets for now.

But until then, thank you so much for reading this frankenstein of a post, and as always, thank you for supporting the project!

Deep Dive - Clothing Color Customization Deep Dive - Clothing Color Customization Deep Dive - Clothing Color Customization Deep Dive - Clothing Color Customization Deep Dive - Clothing Color Customization Deep Dive - Clothing Color Customization Deep Dive - Clothing Color Customization Deep Dive - Clothing Color Customization Deep Dive - Clothing Color Customization Deep Dive - Clothing Color Customization Deep Dive - Clothing Color Customization Deep Dive - Clothing Color Customization Deep Dive - Clothing Color Customization Deep Dive - Clothing Color Customization Deep Dive - Clothing Color Customization Deep Dive - Clothing Color Customization Deep Dive - Clothing Color Customization Deep Dive - Clothing Color Customization Deep Dive - Clothing Color Customization Deep Dive - Clothing Color Customization Deep Dive - Clothing Color Customization Deep Dive - Clothing Color Customization Deep Dive - Clothing Color Customization Deep Dive - Clothing Color Customization Deep Dive - Clothing Color Customization Deep Dive - Clothing Color Customization Deep Dive - Clothing Color Customization Deep Dive - Clothing Color Customization Deep Dive - Clothing Color Customization Deep Dive - Clothing Color Customization Deep Dive - Clothing Color Customization Deep Dive - Clothing Color Customization Deep Dive - Clothing Color Customization Deep Dive - Clothing Color Customization

More Creators