Pages

Saturday, 8 April 2017

Tutorial : Let's Get Dirty

As you may or may not know, I've jumped on board the VR bandwagon. In order to create 360 3D VR content with Blender you have little choice but to use the Cycles rendering engine, which for me at least is a fairly steep learning curve from the old material editor. Recently I got quite frustrated trying to use Cycles to do the trivial task of using one stencil to act as a stencil for another, so here's a quick, basic tutorial on how to do this from the perspective of someone new to Cycles but used to the original Blender Internal engine and material editor. I don't guarantee that this is the best way to do things, just the one that makes the most sense to me.

A very nice tutorial on some slightly more complex materials can be found here, but it's an hour long video. I won't cover nearly as much as that in this short post, but hopefully I'll give enough of the basics that the Cycles workflow won't seem so scary by the end. It really isn't that different to creating standard materials, it's just that you have to think more about what each button is doing and configure those buttons yourself.

I'll assume a basic working knowledge of Blender (where all the buttons are, how to organise windows etc.) but little or nothing about Cycles materials. I'll cover :

  • How to create standard image and procedural textures
  • How to use bump mapping
  • How to mix textures using different shaders or by mixing their colour/alpha information directly
  • How to use one texture as a stencil for another, with some Cycles-specific quirks to watch out for
  • How to arrange things to make the Cycles node window seem less intimidating.


1) Getting started

First, change the rendering engine to Cycles (top menu bar, the drop-down menu that says "Blender Render" by default). Then set up a window environment suitable for editing the materials. In Cycles this is done almost entirely via nodes, so we're going to need a nice big window for that. I like the following setup :
The left section shows the 3D view of the scene, the middle one is the node editor, and the right is the standard properties window.
Notice that on the left I've set the shading method to "rendered" (the little sphere at the bottom of the left panel, next to "object mode"). This gives a realtime preview of the scene. I've got a single Sun lamp pointing at an angle to the plane, but in more complex scenes you'll see the full effects of shading so this can be a great way to see what you're material will really look like. This setting is also available for the standard Blender engine. You also get a preview of the material in the usual panel, just like with the regular rendering engine.

A word of warning : the realtime preview can be unstable. Save your work often, and if in doubt, revert to the classical technique of rendering after making changes to the material. In the Rendering menu there are various options you can set to speed up rendering time; for this example, try lowering the number of samples in the Sampling panel.

Anyway, select your object and add a material just like normal. In the node editor you'll see the following :


What is this ? The "Diffuse BSDF" thing is scary and not at all an intuitive label. What it is is the way in which the diffuse component of the material is constructed. This is then linked to the material's output, in this case to the surface. I won't look at volumetric materials or displacement settings in this tutorial, just the regular surface shaders. We also don't need to worry about any of the material settings on the right, though it can be helpful to open the "preview" panel, here shown closed.

The first thing to understand about this Diffuse node is that it contains more information than colour. If you were to create a node containing only colour information, such as an image file, and link it to the material output surface socket directly, it wouldn't work. It needs that other information contained in the Diffuse node, even if all you wanted to do was set the colour.

Fortunately if you do just want to set the colour, that's easy. You can click on the colour picker in the Diffuse node and set it there directly. Or, more usefully, you can generate the colour from other nodes (in very complex combinations) and use that as the input to the node. Let's start with an image texture node : Shift+A -> Texture -> Image Texture. Use the file selector in the Image Texture node to choose the image file to use. Then connect the Image Texture node to the Diffuse node by clicking on its colour output socket and dragging the line to the input colour socket of the Diffuse node.


But, confusingly, although the material preview will look correct, the render preview won't. Thing is this setup by itself doesn't work. Just like with regular materials, we have to tell Blender what texture coordinates we use. So now add a Texture Coordinate node : Shift+A -> Input -> Texture Coordinate. Draw a line from its "generated" output socket to the "vector" input socket of the Image Texture node, and both the render and material previews should be what we'd expect.


Hooray ! Now you may be wondering about the other sockets on the Diffuse node. "Roughness" changes the shading style but its effects are subtle so let's not worry about that. "Normal" is used for bump maps. The way you set this up is to add a "Bump" node (from the "Vector" section of the Add (shift+A) menu) :


Just like trying to connect the image texture directly to the material output, if you'd tried to connect it
directly to the Normal socket on the Diffuse node, it wouldn't work - the Bump node converts the data into a format it can process correctly. But note how here I've cheated by using the colour of the material as a measure of its height. This works quite well in this case, and in many other cases too, but you could also use a completely different source for the bump information - another image or a procedural texture, for example.

You might also be wondering how we can alter the texture scaling. For that we need to add a Mapping node from the Vector submenu. A useful trick here - first move the Texture Coordinate node a little way off to the left. Then add the Mapping node and position it over the connecting link between the Texture Coordinate and Image Texture nodes. Notice how the link turns orange. When you left click to accept the new node, the links will be set up automatically. Then you can alter the texture scaling parameters in the usual way.

Now it's starting to look quite a bit like a regular Blender material, except that you can both see and control how each part relates to the rest.
One final extremely useful thing to be aware of : frames. Frames are (sort of but not really) meta-nodes, a way to group nodes together so they can be easily moved in blocks for tidy screen organisation. They also let you label blocks of nodes so you can see at a glance what each part is doing. Add a frame from the Layout option of the add menu. Then you can stick the nodes inside it just like parenting objects together : (shift) select the node(s) you want to add in the frame, then shift-select the frame and press CTRL+P. The frame automatically reshapes to hold the nodes. You can un-parent them in the usual way with ALT+P.

Label the frame with the N menu and edit the "Label" parameter near the top. I got rid of the Mapping node here because it's not necessary for this example.
If you select the frame you can move all its nodes around at once. Obviously this isn't much use for this simple material, but, as we shall see, it becomes essential for more complex materials - especially if you re-use them months later !

Now that we have the very basics out of the way, let's get on with setting up multiple textures in different distributions.


2) Multiple textures

Note how I chose the frame to include the whole shader in the above example. That's because one way of mixing different textures is to generate a new shader and then mix them together, so it makes sense to have each frame contain a complete shader. But we don't have to do it that way. A perhaps more intuitive method is to generate the other texture and have the colours combined before they're input into the Diffuse node. You can have shaders made up of multiple textures mixed with other shaders, so things can get extremely elaborate - and far more powerful than what you can do with Blender's standard material editor.

For example, let's add a second texture on top of our image texture. Let's first create a simple procedural noise texture on its own. For this we need two additional nodes : Noise Texture (from the Texture submenu) and the ColourRamp (from the Converter submenu for some reason - I'm not sure the layout of the add menu is particularly sensible, but never mind). Set them up like this :

You can have multiple Material Output nodes if you like, so you can create this node setup without having to remove the existing one. The output nodes that's used (i.e. the material that's displayed) will be the one that's active.
It should be fairly self-explanatory - the parameters are very similar to Blender's standard internal noise textures.

Now comes the interesting part : overlaying the noise texture on top of the original concrete texture. Let's first try this by using a different diffuse shader for each texture and mixing them. We only need to add one more node to do this - the Mix Shader node from the Shader submenu. The base layer (the concrete in this case) goes into the top socket and the overlaid "dirt" - the white fuzzy noise goes into the top. The really important bit is that the "Fac" socket which controls the mixing should come from the Alpha socket of the dirt colour ramp.

This alpha-based mixing was automatic in the original Blender materials. Now we have to specify it, which is a bit more work but also gives us more control.
You can see that this gives us exactly what we'd expect - a concrete texture with some white splodges, with the dominance of the white controlled exactly by its alpha value (if you need to modify that alpha value, send it through a Math node (Converter submenu) before it goes into the Fac socket). Places which should be totally white are totally white. All is well with the world.

Now let's try the other approach of mixing the colours before we send them into a single Diffuse node. We eliminate the Diffuse node of the dirt texture and (optionally) unparent the Diffuse node from the concrete frame. Then we add a MixRGB node (colour submenu) and, equivalent to what we did before, we put the colour output of the concrete texture into the first slot and the colour of the white patches into the second. Again we use the dirt's alpha channel to control the mixing.


Uh-oh ! This has sort-of worked, but very badly. The dirt is mixed, but now its dominance is not properly determined by its alpha. Parts which should be totally white still clearly show the concrete image. Why is this ? Watch what happens if we eliminate the Bump node :


Ahh, now we see what's going on. It wasn't that the colours of the concrete image were showing through, it's that the normal map was causing bumps that were independent of the dirt texture. If we insist on using the mixing colours rather than shaders method, there is a way we can keep the bump mapping - we use the dirt texture to set the strength of the bumps. We need to use the alpha output of the dirt for this, but since we want the white patches to be smooth we need to invert it (Colour-> Invert).


A bit messy, but it works. The nice thing about this is that by altering the "Fac" slider in the Invert node we can change the strength of the effect, so that you could still see the bumps of the concrete in the white patches a little bit if you wanted to. You could get the same effect with the mixing shaders method too, just by dragging the output of the Bump node to the second Diffuse shader as well as the first.

Of course you don't have to use a simple noise texture - you could use a Musgrave, which has a lot more parameters, or a wave (equivalent to the old "Marble" texture)... or more interestingly, you can link another texture to the input scale and distortion sockets. You can get arbitrarily complicated effects like this. And because of the node setup, you're no longer limited to arranging things in the strictly-linear manner of the original material editor.


3) Controlling where the dirt appears

We might be happy having great white splodges all over the place, but we'll often prefer it if they only appeared in a few places on the material. That is, we want patches controlling where the patches appear. Especially for very small patches of dirt - you might not want a uniform coating of dirt, flecks of paint of whatever over your whole material.


This had me stumped for the longest time, and then I felt very silly when I realised how easy it was. Then I felt a bit less silly when some kindly soul pointed out to me that a small mistake can have big consequences here.

All we need to do is make another texture that defines where the splodges appear and use this to multiply the colours of the dirt. So our distribution texture should be white where we want the dirt to appear and black where we don't. Or we can use its alpha channel, which is slightly simpler that setting the RGB colours, but it doesn't really matter. Then we use a Math node to multiply the two alphas (or colours) together, by setting the method to "Multiply" instead of the default "Mix".


The colour of the dirt is generated by a single noise texture, and it's mixed with the base material in the same way as when we had a single texture. The only difference is that now the alpha mixing is done not by the alpha channel of the dirt itself, but by a multiplied combination of the dirt's alpha and the dirt distribution texture alpha. So dirt distribution section only affects the distribution of the dirt and nothing else.

You can download the .blend file here. Play with the scale parameters in both the the dirt distribution and dirt textures to see what effect they have. If you change the dirt distribution scale, you should change the large patches where the dirt appears, whereas if you change the dirt scale, you should change the size of the smaller sub-patches.

But be careful ! There are two pitfalls here :

1) To see the effect really clearly, there should be a large difference in the scale parameters - the dirt scale should be around 10x larger than the dirt distribution (larger scale means more texture within the same area). But if you go to the other extreme, you can break it - a larger scale of the dirt texture than its distribution scale means you won't see any sub-patches.

Keeping the scale of the distribution texture at 1 but altering the scale of the dirt texture from left to right (10, 25, 50).
Keeping the scale of the dirt texture at 50 but varying the scale of the distribution texture from left to right (1, 25, 50). The distribution scale has the strongest impact at small values - once it gets as high as the dirt scale everything becomes uniform, so varying it just shrinks the size of the individual patches rather than controlling where those patches appear.

2) The position of the colourband sliders matters. Keep the distribution colourband unchanged and try moving the dirt colourband sliders around. If you move them too far to the right, the sub-patches can become too small to see or disappear entirely. Too far to the left and the sub-patches become larger than the patches, so changing the scale doesn't have any affect. A similar problem happens if you move the dirt distribution colourband sliders - it can seriously screw everything up.
A good guideline is to start with both the colourbands having markers in the same positions, then tweak it from there. So if you're making your own material, start simple and gradually build up the complexity - make sure each stage has the effect you think it should have.

Keeping all the texture scales constant but varying the position of the dirt colourband controllers (keeping their relative offset the same but moving them both to the right). In the left image the size of the gaps in the dirt are so small that they're barely visible, whereas in the right they're so large that the dirt is barely visible. This is not what happens with a single texture, where you'd have to move the colourband markers to the extreme ends to get such a strong effect - here you get unexpected behaviour if the markers are just a bit too far from the centre. And in those situations altering the scaling of the textures will give some very strange results. 

Well that about wraps this up. There are lots more aspects to creating materials, obviously, but hopefully that's enough to break the ice and show that Cycle materials aren't so scary. Since non-video tutorials are in short supply, I'll try and do more of these assuming that stuff doesn't keep getting in the way.

No comments:

Post a Comment

Due to a small but consistent influx of spam, comments will now be checked before publishing. Only egregious spam/illegal/racist crap will be disapproved, everything else will be published.