# Procedural random/different colors based on normal direction

## What I have.

A simple subdivided Cube with circular holes in it - every side, six of 'em. Holes have they own material, and each of the hole has different color. Holes are completely flat.

I have managed to color them dumb way (in other words - my way) by separating XYZ and assigning pairs of colors to opposite sides. Not to shabby. It's working after all and working well, I reckon. But... Only for this particular example.

## What I want.

I would want to achieve the same result (similar, but this I'll explain later), with one Color Ramp and math-node-vector-fu so the color would be assigned based on Normal direction. Randomly or not, it's not so important, as far as every hole/face group would have different color - providing same number of colors in ramp as there are holes.

And a little catch.

It would be nice if it will be possible to use it on more face groups and with different angles.

## What I've tried.

To be honest. Many things. I've tried to use Normal Coordinates mixed and added and crossed with other ones. I've tried to use multiple setups from different sources regarding "different color for faces". I've multiplied the hell out of it. Nothing worked. The best try was to have 3x3 different colors (3x reds, 3x blues).

Disclaimer: I would rather avoid Python scripting, Vertex Painting, UV Unwrapping, Texture Painting, assigning materials by hand for each face group and 3rd party add-ons. This whole question is about understanding Cycles more and pushing it to limits.

Master build or 2.8 branch answers are welcome.

## Edit.

Result from Ed Tate answer:

## 2 Answers

Technique #1

A psuedo-random color can be assigned to a range of normals (needed if there are small variations in face normals) and stay with the object as it rotates. The normal vector for the object faces is transformed to local coordinated, then rounded, then passed through a noise texture, and finally a color ramp.

For the sample model in the question, the geometry for the lights was separated from the original mesh and simplified so the faces for the light were approximately flat. To illustrate how the colors are assigned based on normals, a sphere with random colors is shown along with the disco ball.

Solution (tested on 2.79)

• Create a shader for the random face colors. The input will be the geometry node followed by the vector transform node. The vector transform node allows the object to be rotated without the normal changing (See Cycles normal input relative to object's rotation ).

• Add logic to the shader to quantize the normal values for x,y, and z. The values for x,y, and z are rounded so they have a fixed number of values. The input at the bottom controls how many different levels of normal values are considered. This keeps faces that are almost flat a single color.

• Changing this value changes the number of normal ranges that will result in a unique color.
• For a value of 2
• For a value of 10
• For a value of 100

• Finally, the quantized normal is input into a noise texture, then through a color ramp and to an emissions shader.

• Putting it all together, the complete shader is shown below.

• The geometry as shown in the question needed one change for this to work as expected. The lights mesh needed to have flat areas for the colors. The way the geometry was created, results in curvature around the edges of the lights which results in small areas with different normals. Applying this shader as-is to those areas, resulted in unwanted artifacts.

• By separating this mesh and removing the modifiers, the light meshes are flat and get a single color.

An example blend file:

Technique #2

The advantage of this technique is that a texture can be used to assign the colors to the normals. A psuedo-random color can be assigned to faces with unique normals by converting the normal to spherical coordinates, then using a procedural noise texture and color ramp to set the colors.

Solution (tested on 2.79)

• The key to make this work is to convert the normal for face from a vector into two angled using spherical coordinates (see Wikipedia - spherical coordinates). To do the conversion, the atan2 function is needed, but not available in 2.79, so this is done using math and the arctangent function (see atan2 in Blender).

• The spherical coordinates are converted into a value between 0 and 1 by scaling using radians.

• The coordinated are used as a lookup into a texture. To test the mapping the default blender UV texture is used. Using smooth shading on a sphere shows the mapping works as expected. The colors for the faces can be assigned using an image texture.

• To procedurally assign the colors, a noise texture is used. The spherical coordinates are input to the noise texture. Using the default settings, the colors are not independent and blend together.

• Changing the settings helps make every face's normal have a difference color.

• Finally, a color ramp can be used to control the colors assigned. Add a color ramp between the noise texture and the shader. The output of the noise texture is scaled to use all of the range of the color ramp.

• The complete procedural shader for this is shown below.

Sample blend file -

• Nice technique, +1. Would this also work well on non planar islands or groups of faces where the normals are inconsistent? – Duarte Farrajota Ramos Oct 13 '18 at 23:05
• Very nice. Do you even need to translate the Normal into spherical coordinates? The'll already describe a unique point on a sphere in texture space (a sphere with centre 0,0,0 and radius of 1). Can that not just be used directly as input to the Noise texture? – Rich Sedman Oct 14 '18 at 7:24
• @DuarteFarrajotaRamos, I think this answer now addresses the two points you raised. First, the geometry can be islands and this is shown in the answer. Second, if the islands are not perfectly flat, the quantizing (using the round function) assigns one color to a range of normals. – Ed Tate Oct 15 '18 at 2:39
• @RichSedman - thanks for the comment on just using the normal coordinates. Since Perlin noise is a 3D function, it was not necessary to convert to 2D coordinates. – Ed Tate Oct 15 '18 at 2:40

True random per face/geometry colors is something I have frequently tried to achieve but never found a real acceptable solution.

The closest I have got was this UV based solution, which sadly requires previously unwrapping any required mesh parts.

The basic principle is to use UV coordinates for each chunk of mesh different enough from each other that a texture applied to them would seem random. Basic workflow is as follows.

Create a new UV map just for this purpose, select only the different islands you want to have random materials applied to (mark seams if necessary, in this particular case it is not), leaving out the rest of the mesh. Use the Select Grouped > Material operator to ease the work.

Unwrap it using something basic like U > Unwrap just to obtain separate islands for each group.

In the UV Image Editor switch to Islands selection mode and change the transform pivots to Individual Origins. Now scale all islands down to a factor of zero.

This will essentially make every point of each island share the same UV coordinate. Any texture using this UV layer would essentially give a single color per island.

Now just use any procedural texture of your choice running through your "master color node" to give apparent random colors per island. Choosing a repeating texture with a uniform color distribution, like say a Wave texture, will give more even results.

• Good idea. I've tried using textures with generated coordinates but it wasn't successful. Thanks for idea, but as I said I would rather want to learn pure cycles method. – cgslav Oct 12 '18 at 9:27