Learn how to pack various data for a shader in the 3 channels of vertex color using Houdini’s easy yet powerful nodes.
WarningThis website and its contents are work in progress. In the meantime, please visit the YouTube channel.
In this tutorial I’ll show you how to store numbers in the vertex color of a mesh. It’s a great way to provide more information to a shader. I used this method to assign certain masks and randomized properties to a modular building wall.
In computer graphics there are several common attributes that can be stored in every vertex. The position is the obvious one, a surface normal is another and most software also supports color. Nothing prevents us, though, from utilizing the color attribute to store 3 individual numbers – any numbers.
Assuming that we’re dealing with RGB color (no alpha), we can pack 3 values in the respective red, green and blue channels. My building shader uses:
- Red to mark places where user-chosen color should be used instead of the texture. Value of
1is for the glossy wall paint,
0for everything else.
- Green to choose colors from a palette. The number between
1.0decides which one to pick.
- Blue as the multiplier of position randomization. Walls are
0.0, which means “stay where you are”.
To learn how to use such data in an actual Unreal Engine material, read/watch the tutorial: Good-looking randomization for procedural buildings.
For such data-wrangling on mesh assets I use Houdini as my tool of choice. It’s a 3D modelling and simulation package that has procedural approach at it’s core. If you haven’t used it already, I hope this tutorial will be a nice introduction to what you can do with the software. If what you’ll read makes you interested, you can start right away with an introduction book from the developer.
In Houdini every action is a procedure – a “recipe”, if you will – described with a set of nodes. It’s very similar to how Blueprint or materials work in Unreal Engine. Even manual actions are captured and inserted as nodes. While this may be redundant for a complex one-time job, it’s brilliant for the kind of work that requires going back and tweaking the process. It also frees the user from remembering the parameters used to get the given outcome.
Vertex color as data
In 3D graphics a color is just a three-component vector. Its components are the brightness of red, green and blue – but you can think of them as a collection of three numerical values. The meaning is arbitrary. The only caveat is that each of them must fit in
So vertex color is just data. This is probably easier to see in Houdini than it is in other editors. Here you can view any attribute (be it position, normal or color) as raw numbers, thanks to the Geometry Spreadsheet window. So instead of using vertex color directly for colorizing the textures, I decided to pack masks into each channel.
Houdini will only be used here to calculate and store data. The actual usage happens in an Unreal Engine shader, which I create in the procedural building tutorial I mentioned.
Assigning vertex color in Houdini
Let’s begin by creating a Geometry node in the object context (obj). The first node should be a File SOP, which allows to load an FBX, Alembic or OBJ. A Color SOP adds a vertex color attribute (
Cd in Houdini). Set it to black – to fill our vertex color channels with zeroes. Also choose the Primitive class (instead of the default Point) in the node’s parameters.
Red – mask of wall paint
We’d want to assign full red to every painted wall – so excluding the decorations and windows. Red was to meant to be our mask between the primary and the secondary color of walls. Create another Color SOP. In its parameters set the value to
1.0, 0.0, 0.0.
Now find the Group text field and press the arrow button to the right of it. Houdini will start the selection mode. In the viewport’s toolbar enable Group Selection, then set the group type to UV Islands. With these settings it should be easy to add all the walls, just by holding
Shift and clicking all relevant pieces of the mesh.
Enter key should get you out of the mode, with the numbers of selected polygons written into the Group text field.
Green – random for each decoration piece
For the green channel let’s use a more fancy method. We need varied values in it, so that the shader in Unreal can use them to control randomized features – like changing the color of each decoration.
It’s time for a node called Attribute Randomize. It can assign random values within a given range to any attribute. We’d like it to write into color –
Cd. It should be default setting of its Attribute Name parameter. Initial Min Value of
0, 0, 0 and Max Values of
1, 1, 1 will give us totally random colors across the RGB spectrum. Let’s change the Max to
0, 1, 0. Now it chooses only from pure green colors. Set the Attribute Class to Primitives. That will make it assign a value to each polygon instead of per vertex.
Is something incorrect here? Of course! We need the green value to be chosen for the entire decoration item – that is for a single sock or a cloth. The algorithm of the node can do that, but first it needs to understand what do we mean by an item. That’s where the Connectivity SOP comes to the rescue. It creates a new attribute (called
class by default), in which a common number is assigned to every piece of geometry that’s physically connected. If there’s any kind of gap between the pieces, they will be assigned different values. Now we only need to tell the Attribute Randomize node to use these numbers as a seed.
Random seed is a number that marks the beginning of a pseudo-random sequence. The same seed always leads to the same “random” result. In some case, for example, a seed of
7 will always produce
0.1232 (I just made the values up). This is basically a way to get deterministic randomness (we’ll get back to it when adding noise in the shader). To use seeding, go back to Attribute Randomize, open the Option tab and enable Seed Attribute. Type
class – or whatever you chose in the Connectivity SOP. Done. Each connected piece of geometry should get it’s unique shade of green.
Blue – strength of random position offset
For the blue channel you can use the same treatment as for the green. Change the Operation to Add Value – because there’s no problem with assigning an offset to the items that will use the color randomization feature in the shader. I also used the range of
0.5. Due to the fact I used the SOP only on a specified Group, that will leave most polygons with the old value of
0.0 (walls, window frames etc.) That will allow me to optimize the shader, by skipping new position calculation for anything with blue equal to
Exporting FBX from Houdini
At this point we’re done with populating vertex color with data. The last step is to export the mesh. In File → Export choose Filmbox FBX. For Unreal Engine disable ASCII format. Select the geometry node of the mesh in the Source Objects area and leave the other options at their default setting.
The mesh is ready to be imported into the game engine. I hope the tips will be useful when you’ll be looking for ways to utilize vertex color in your own shaders!
- Easy Way To Pack Textures Into RGB Channels — A similar idea but in the texture realm. Packing is even more beneficial there, as it allows to save space and retrieve 3 textures with a single read operation.
- UE4: Detailed Texture Blending with HeightLerp and Vertex Painting — Using vertex color to store masks of material layers. Intensity of the red channels sets the opacity a moss layer on top a stone wall.