Hi everyone,
I'd like to share a material node setup for procedural radial tangents to generate a brushed or machined metal look.
Maya 2020 Material
I setup some extra attributes in the material node. There also is a small explanation in the notes of the node, in case the anisotropic effect doesn't show up correctly on your meshes.
You basically need to make sure the pivot point is set to the rotation center of your object and apply "bake pivot".
Input Values
"Line Density" and "Streak Density" are the main controls to the noises that make the brushed metal look.
"Rotation Axis" needs to be used like a selection. [1,0,0], [0,1,0] or [0,0,1] are possible options. Other values will produce artifacts.
"Color Base" = value of the base color
"Roughness Base" = value of the base roughness
"AnisoRot Base" = value of the base anisotropic (which is locked at 0.25).
"Color Noise" = Contrast of the noise in the base color
"Roughness Noise" = Contrast of the noise in the base roughness
"AnisoRot Noise" = Contrast of the noise in the anisotropic rotation
They all use a noise to spread the values around the corresponding Base value.
"Bump Height" can be used as an alternative to the Contrast-Aniso. Set the z-value of Contrast Col Rough Aniso to zero and turn up the Bump Height value.
It needs 30% more render time on my end, is more noisy, prone to produce artefacts and usually not worth the effect.
If you see facetting artefacts (hard edges on a smooth shaded surface) try turning up the Epsilon value in the aiBump3d node.
Node setup radial noise
It consists of 2 noises mixed by normal direction. One aiNoise node that gets streched by the "scale" input for the outside surfaces.
The Second aiNoise node with the distance to the rotation axis connected to the "time" input, will have the rotation effect.
Note that this noise is 4 dimensional, it has a vector3 input called P and Time as the 4th. In Blender you need to switch the Noise Texture node to 4D mode - the "W" input is the time equivalent.
You could do it with a 3D noise, by feeding one dimension with the length from the two other position values. like: Noise position = (Po * (1 - InputAxis)) + (lenght(Po * (1 - InputAxis* InputAxis)))
How radial tangents work
I basically rebuilt a node from the open source software Blender. Blender has a standard material node called tangent.
In the node you can select the mode UV or Radial. In Radial mode you can select if the rotation axis should be X,Y or Z (in object space).
I looked into the source code of Blender and found blender/intern/cycles/kernel/osl/shaders/node_tangent.osl
the important part happens here:
else if (direction_type == "radial") {
point generated;
if (!getattribute("geom:generated", generated))
generated = P;
if (axis == "x")
T = vector(0.0, -(generated[2] - 0.5), (generated[1] - 0.5));
else if (axis == "y")
T = vector(-(generated[2] - 0.5), 0.0, (generated[0] - 0.5));
else
T = vector(-(generated[1] - 0.5), (generated[0] - 0.5), 0.0);
}
T = transform("object", "world", T);
Tangent = cross(N, normalize(cross(T, N)));
With a lot of trial and error I was able to bring it to a from that is using a vector as axis input.
Sadly I don't know how it would be mathematically possible to freely rotate this system and get correct tangents.
At the moment it only produces corerct outputs with axis aligned inputs [1,0,0], [0,1,0] or [0,0,1].
Pseudo code:
N = geometry normal in worldspace
Po = geometry Position in obejtspace
axis = Rotation Axis, user input [1,0,0], [0,1,0] or [0,0,1]
temp1 = cross(Po * ([1,1,1] - axis), [-1,-1,1] * axis)
temp2 = SpraceTransform(ObjectToWorld, temp1)
tangent = cross(N, normalize(cross(temp2, N)))
Open Shading Language (OSL):
shader radial_tangent(vector axis = vector(1.0, 0.0, 0.0),
output normal Tangent = normalize(dPdu))
{
vector Po = transform("world", "object", P);
vector temp = cross(Po * (vector(1.0, 1.0, 1.0) - axis), vector(-1.0, -1.0, 1.0) * axis);
temp = transform("object", "world", temp);
Tangent = cross(N, normalize(cross(temp, N)));
}
The code can be a one liner if readability is not important 😉
Edit: Added 3ds max mateial version
Unfortunately I wasn't able to achieve this in 3ds Max. Instead, after some trial and error, I've got this interesting metal material:
No osl/scripting involved. Each object has its own uvw map settings.
Very nice! Thanks for sharing!
Hey,
I added a 3ds max material to my original post if you are interested. I'm not very familiar with 3ds max, so I don't know how to use parameters or something like that. For now the input values are User Data nodes.
by the way: The only way I found to bake the pivot is to use the search by pressing "X" and search for "reset xform". But this applies the whole modifier stack of the object. Feels like another one of these oversights by autodesk.
Can't find what you're looking for? Ask the community or share your knowledge.