Back to Project
Gradient Mapping Character Shader
Technical Art

Gradient Mapping Character Shader

Created a gradient mapping shader for stylized character rendering with team color support

Context

This is an overview of the shader that I created for the art team of Rift Wars. At the time of creation, the game's character shader used a color tinting method to give enemy units a red tint. This blending method resulted in heavily limited, washed out, and monotone results.

Original character shader
Original character shader

What is Gradient Mapping?

Gradient mapping is a powerful shader technique used in game development to remap the grayscale values of a texture to a custom gradient of colors. This method involves converting an original texture to grayscale and then applying a color gradient to it using a shader. In tools like Unity's Shader Graph, this is achieved using the 'Sample Gradient' node, which allows developers to define a custom gradient that replaces the grayscale values with new colors.

Headhunters from Rift Wars using the gradient mapping character shader
Headhunters from "Rift Wars" using the gradient mapping character shader

How Does Gradient Mapping Work?

  1. Grayscale Conversion: The original texture is converted to grayscale, where each pixel's intensity ranges from black (0% intensity) to white (100% intensity).
  2. Gradient Sampling: The shader uses these grayscale values as keys to sample a custom gradient. For instance, a pixel with a 50% grayscale value would sample the color at the midpoint of the gradient.
  3. Color Replacement: The sampled colors from the gradient replace the original grayscale values, effectively recoloring the texture based on the defined gradient.
  4. Combining Vertex Colors with Gradient Mapping: The shader can use vertex color information as input for gradient sampling. This means that the vertex color can determine which gradient to use on various parts of the mesh. This is incredibly valuable for complex models that consist of different "materials" within the texture itself. For example, skin and clothes on the same texture can have two entirely separate gradients.
High level overview
High level overview
Channel mapping example
Channel mapping example

The Tricky Part

Shader Graph does not support the data type gradient by default. This means that it cannot be easily exposed in the inspector for artists to interact with.

Chroma: Easy Pro Shaders

https://assetstore.unity.com/packages/vfx/shaders/chroma-easy-pro-shaders-231313

Chroma does support gradients as a data type, and they can be exposed in the inspector. Unfortunately, this is accomplished through the generation of a texture for each gradient. Remember, a large part of our goal here is to reduce draw calls and memory overhead, and we are trying to apply up to three gradients on each asset. Those extra draw calls are not going to do us any favors.

Detailed overview
Detailed overview

Gradient Atlas

One alternative, which requires some custom tooling, is to author a gradient atlas. In this atlas, each row contains a 1-pixel-tall gradient. The limitation here is the resolution of the texture; use the smallest resolution possible to reduce file size and memory load.

The shader can then sample an index property to reference a specific row. This allows each vertex channel to use unique gradients.

Single-channel example
Single-channel example
The gradient atlas holds 1024 gradients
The gradient atlas holds 1024 gradients

The Filter Mode of the gradient atlas must be set to Point (no filter)

Performance

At the end of the day, we are trading some performance for agility. This technique is never going to outperform a standard unlit character shader as we are, at minimum, adding an additional texture to hold gradients and creating branching for each vertex color. Your results may vary based on target-device, but for me, the cost here has been more than acceptable for how much is gained.

XCode GPU Trace, iPhone 14 Pro Max
XCode GPU Trace, iPhone 14 Pro Max
XCode GPU Trace, iPhone 14 Pro Max
XCode GPU Trace, iPhone 14 Pro Max

Workflow Benefits

Gradient mapping offers several advantages. It allows for dynamic color customization, enabling artists and developers to adjust colors in real-time without the need for new textures. This flexibility accelerates the iteration process and facilitates rapid prototyping. Additionally, it ensures a consistent style and quality across different assets since the same gradient can be uniformly applied, enhancing the visual coherence of the game.

Managing a single grayscale texture per asset simplifies asset management, reducing potential errors and making the project easier to maintain.

Lastly, gradient mapping opens up creative possibilities for effects like dynamic color shifts, player-customizable colors, and thematic changes (e.g., day-night cycles) without requiring additional textures.

Reusability & Variety Examples
Examples of reusability and variety achieved with gradient mapping