Saturday, April 21, 2012

Blender Wood Texture part 2

In the last post we developed a wood texture that is based on the actual growth process of trees. It looks pretty good, but it lacks any variation that would make it look like wood taken from a real tree: the rings are circular, and the rings follow a strict logarithmic progression in which the interval between each successive ring is smaller. In real life, there is a lot of variation in the ring pattern. The trunk is not necessarily circular, for many reasons, including but limited to: the tree species, presence of nearby trees, prevailing wind direction and strength, and ground slope. The spacing between rings depends on the weather in a given year.

We won't attempt to model the phenomena behind these variations, but we can simulate them as random processes. In computer graphics, "random" usually doesn't mean completely random, because truly random values would introduce horrible artifacts. Instead, we use a source of randomness called Perlin noise. This is an effect that varies a random value (or vector) smoothly in space. A 2D slice of Perlin noise looks a lot like the surface of a cloud; indeed, the Blender Perlin noise texture is called "Clouds." We can access a cloud texture using the generated coordinates from our 3D timber objects, and we can also use any other value we wish to noisify, such as distance from the center of the trunk or tree age, to do a look-up in the cloud texture.

Ring Distortion

The first new variation we will introduce is to the shape of the trunk. We want to slowly change from circular rings at the center of the tree to something that might be quite distorted at the outside. After some experimentation, I've found that it works best to scale the radial distance, which use as the input to the age calculation, by a factor based on the angular position around trunk. We implement this by normalizing the radial vector to a unit circle, doing a lookup in the cloud texture, scaling the noise value down quite a bit to a value near 1, and multiplying our radius value by this. Here is the modified material node network:

and the results:
Although I'm exaggerating the effect in order to show it clearly in the rendering, the results are not bad here. The variation in the circular shape of the rings is indeed more pronounced in the outer rings, and it has introduced interesting changes in the grain pattern on the long surfaces of the timbers. The waviness in the rings apparent on the square timber may not look much like any real tree, but we will see later how we can vary the effect's intensity to achieve the desired look.

Growth Variation

Next, we will vary the distance between rings with a similar node setup that scales the output of our age calculation:

For our test render, I've turned off the previous effect in order to see only the new one:
which is pretty successful. While we have preserved the basic trend of the rings getting closer together at the outside of the tree, there is significant variation in the ring spacing.

After putting the two effects together and reducing the amplitude of the radial variations, we get this:

This is very close to a good wood texture, but there is still a lot of repetition, particularly in the visible grain where a surface grazes a dark ring, such as directly over the center of the tree trunk in the flat board. We can break up this repetition by introducing a bit of noise all over, which we can justify by considering tree growth as an organic process. The noise is introduced at the end of the node network, using 3D position as the input to the noise texture:
and gives an appearance that we will happily use in our technical illustrations:

Node Groups

The final node network is fairly complicated:

It would not be convenient to copy this for different wood materials. We can use Blender's group feature to gather all the nodes into a single block that can be used in many materials in a file, and be linked or appended into other Blender files. Select all the nodes in the material, except for the coordinate input node and the material and output nodes at the end. Then, use the "Group" command from the Node menu. Our network uses two coordinate inputs, but we can have one input to the group and route that value where it is needed inside the group:
When we are done editing the group, the network looks like this:
Much neater, but perhaps not very useful to an artist. For our final refinement, we will expose all the parameters that would be useful for achieving different wood effects as inputs to the group as well as the value used to mix the early and late colors. The new group is impressive in its collapsed state:
The interior of the group is now fairly complex and is starting to strain the ability of the screenshots to illustrate what we are doing. On the left:
and the right:
Some implementation details have been changed because Blender doesn't allow inputs to mapping nodes other than the vector to be transformed.

So, that's our wood grain material. You can download the blend file here and play with it yourself. Time to do some more carpentry illustrations!

No comments: