A reusable apple material in Blender 2.79b


The Facebook group Blender Procedural Textures holds biweekly contest to construct procedural textures. A recent challenge was

You will try to come as close as possible to an apple, BUT I would like the nodes to be structured, grouped and user friendly, so that you can dynamically change your apple to green or red, mix colors or decide how many lines and spots the peel should have. In short… a perfect “apple peel material” that you can set in the hand of a non node expert user and they should be able to use it .

My entry renders as


A render of two apples created with the same apple node group.

This is a brief discussion of how I created the materials. I created this with Blender 2.79b.  It should work for any version of Blender that has the node groups I used. It can be improved in later versions of Blender by using microdisplacement.


What color is an apple?

The first rule of creating objects or materials for 3D rendering is to look at examples. The US Apple Association has a nice collection of large images of apple types and a Google search will turn up many images as well, although it will also turn up a lot of copies of Apple’s logo.

It appears to me that an apple peel may have

  • A basic color
  • Variations on that color
  • Vertical blemishes
  • small dots

There are other aspects as well, but providing these four things will produce a pretty good apple (material).

Modeling an apple.

I am taking Stephen Wood’s Complete 3D Artist course on Udemy. In one lesson, he creates an apple.  Using that technique, I created an apple for the contest. It’s simply a modified sphere, sculpted to have the form of an apple, with a stem extending from the top.



You can search YouTube and discover Apple How-To Tutorials


Changing the lighting in a scene will change the way materials in scene will appear. Gleb Alexandrov has a nice series of lighting tutorials on YouTube.  You can also look for tutorials on photographic lighting, as the principles are the same.

That said, I decided to be lazy and use an existing lighting set up. I grabbed the Modified_b.m.p.s.ByRobinMarin.blend file and stripped it down to its basic lighting.

Building the material

The contest instructions suggest that the nodes to be structured, grouped and user friendly. I decided to make an apple node group that generated the apple color, but did not include the shader to be used. Here are two examples of using the node group to create a red and green (really yellow) apple material.

A limitation of using a node group like this is that there is no way to control the handles of a color ramp that is embedded in a node group, unless you want to change every material that uses that group. This greatly influences the design of the node group.

Basic skin color

The skin of an apple isn’t a single color, but rather runs a gamut of shades of the same color. An easy way to produce this effect is to use a Musgrave texture to control a mix factor.

Commonly, a color ramp is used to tune the pattern provided by the Musgrave texture. But color ramps won’t work within a node group, so a MixRGB node is used instead.  This provides an acceptable approximation of the basic color.


A Voronoi texture can be used to produce random dots. A Voronoi texture creates cells. Each cell has an intensity that varies from one at the center to 0 at the edges in a circular pattern. We can use the Voronoi to control the mix.

A simple Voronoi mix

A less than node creates circles from the Voronoi  This works well if you want precise circular dots, but the dots on the apple aren’t that precise.  A workaround is to use a color ramp rather than the less than node.

But we want to control the size of the dots as a parameter of the node group, so a color ramp won’t work. I have a node group that will do this.  It is described in Faking a color ramp in Blender 2.79.


There are a few ways to go about adding random stripes. Since these stripes tend to run in a vertical direction, it makes sense to use a noise texture scaled in X and Y as the factor for a mix RGB node.

Putting it all together.

So far I’ve shown each aspect separately.  It’s easy to put them together with mixRGB nodes.


Two factors contribute to the bump map.  The skin has an overall bumpiness.  This is easy enough to represent with a noise texture.The dots also contribute additional bumpiness. We need to balance these out, so we multiply the noise texture by a factor before adding it to the bump data from the dots.

The multiply balances the relative strength of the bumps from overall bumpiness and the bumps from the dots. The strength parameter of the bump map controls the overall strength of the bumps.

Making the node group

There are no color ramps in the material, but it does use a vector mapping node.  Vector mapping is another node that doesn’t fit well into node groups, so we perform our own equivalent.  In this case, we only need to scale the vectors, not translate or rotate them. Scaling a vector is accomplished by separating the X, Y, and Z values, multiplying each by its scale factor and recombining them to make a new vector
This is useful enough to make into its own node group

The finished material

Converting to a node group

I like to create a node group in stages.  First I determine a parameters I want to expose. Next I add an input node to hold the value of that parameter. Then I give the input node a label that represents what I think will be a good name for the parameter in the node group. I repeat this until I have all of the parameters.  Then I select the nodes that will make up the node group and make the node group.

There are twenty nine input sockets in the finished material. It would be possible to expose all of them, but the node group would become unintuitive and unwieldy. Here are the choices I made

  • Base colorIn an fBM Musgrave, offset and gain have no value. Because the basic shape using the default detail, dimension and lacunarity are sufficient, controlling only the scale seems sufficient.  Of course, the two colors used by the mix RGB node have to be parameters.
  • Dots the X0, Y0, and Y1 values of the linear equation are specified by the problem design.  Likewise the clamping parameters are specified.  This leaves only the dot size, which is the position of the White pos in the equivalent color ramp, and the scale, which sets the density.
  • StripesThere is no advantage to changing the Z scale, nor is there any real value in setting the X and Y scales to different values. The noise texture default detail and distortion are sufficient, so the only parameter for it is the scale.
  • Bumps The default detail and distortion serve well enough. The multiplier value was explained above.
  • Now we’ve set the input parameters, we choose the output parameters, in this case the final color mix and the height map.  If we leave out all of the input parameters, the bump map, shader, and material output nodes, we can create a node group

Cleaning up the node group

Creating the node group has a couple of problems.

Externally, the parameters don’t have good names or default values. This is resolved by the tedious task of editing each parameter interface slot, setting its name and giving it reasonable defaults. Eventually you end up with a node group with its own name, and with (hopefully) meaningful names for its parameters

Internally,routing can make a spaghetti mess of the node group layout

Everyone has their own way of organizing node groups so that they are readable.  I like to use frames to group functionality, to use reroutes to clarify routing and to use reroute labels to help tracing the routing.

The entire node group

Faking color ramps in Blender 2.79

How to fake a two handle black and white linear color ramp.

If a color ramp only has two handles, the left one is black and the right one is white, it acts like a gradient texture except that moving the handles changes the slope of the gradient. That is, it implements a two point form linear equation.  We can do that with math nodes.

Visualizing 2D equations

Suppose we want to draw the line representing where the X coordinate of a plane is equal to the Y coordinate.  The easiest way to do this would seem to be to use a mixRGB node. The top color would be used for the points where X is not the same as Y and the bottom color for the points where they are equal.

Unfortunately, Blender doesn’t have an equals math node. To make one, consider that X is equal to Y is the same as saying that X is not greater than Y and X is not less than Y. Blender also doesn’t have logic nodes either, so we have to fake the logic.  We get a node group

But this won’t show our line, because there is no thickness to it. Let’s make the line wider, by using a delta factor.  If Y is close to X use black, otherwise use white. That node group looks like this

From left to right

  • The Texture Coordinate node provides a vector giving the X, Y and Z values of the location of a point on the surface of our object.  In this case, Z will always be 0, since it is a flat plane.  X will vary from 0 on the left to 1 on the right.  Y will vary from 0 on the bottom to 1 on the top.
  • The Separate XYZ node gives us the individual values.
  • We add a constant to X to give us the upper bound, and subtract the same constant giving the lower bound.  Using the same constant for both will give us a strip that is centered on the actual line. The size of this constant gives the width of the line.
  • We compare Y to each of these.  The compare Math nodes return 0 if their expression is false and 1 if it is true.
  • We apply the minimum operator.  If Y lies outside either range, the minimum will be 1. If it is inside both ranges it will be 0.
  • Not shown: This reverses the result we want.  The top input of the mix node will be used if Y is outside the range, the bottom will be used if it is inside.  There are at least two ways to fix this. Subtract the result from 1 or use a color invert node between the minimum and the mix node.  For this discussion we’ll leave it as is: Black will be inside, white, outside.

A color ramp

If we add a color ramp to the X value, we can control where the line enters and leaves the image.

Since the black handle is at position .25 and the white handle at position .75, the ramp returns 0 outside that range, and a linear value within it.

The color ramp then is returning the result of a linear equation.  It provides us with two points (x=handle 1 pos, y= 0) and (x = handle 2 pos, y =1). The equation for the line can be found on the web, for instance, here. We can use that equation to produce the same results as the color ramp would. Here is the node group for this

But the result isn’t exactly the same as the color ramp

that’s because the color ramp clamps the results.  Anything to the left of the black handle is set to 0 and anything to the right of the white handle is set to 1. Two nodes will resolve that

Since these node groups are fairly useful, I’ve made node groups of them.


Procedural Archimedean Spirals in Blender – Part 2: Creating a node group


In a previous post I developed a material that has a spiral pattern. In this post, I convert that material’s spiral nodes into a node group. The tutorial was prepared using 2.79b but the texture will work in any version of Blender that supports the math node and node groups.

We’ll clean up the material, making it more suitable for creating a node group. We’ll create the node group. We’ll incrementally improve the interface and layout of the group. In the end we’ll have a node group that provides a wide range of control over a spiral texture.

Clean up

Magic Constants

There are math nodes that have constants as one of their arguments. It is not apparent why they have the values they do or if they are related in any way.  Programmers call such numbers magic constants. We finished part 1 with this material.

The new Math nodes as well as the multiply Math node to the left of the top added Math node all have constant values as arguments, as does the the divide Math node below the gradient Texture node. These numbers are related to each other. Changing one without changing the others will break the spiral pattern. This addition corrects that.

Now we have a single Value node that is the source of the other constants.

Bad parameter values

If we set the new density parameter to anything that is not an integer value, the spiral will stutter Here is a render with density set to 1.5 Similarly, setting the number of arms to anything but an integer will break the spiral.

We can’t fix this, because Blender has no integer only input value, but we can work around it using the round Math node.

The node ignores its second argument, so we haven’t introduced new magic constants.  Now, any value between N-.5 and N+.5 will be rounded to the integer value N.

Separating Parameters

We can make it easier to see which nodes belong in the texture node group by moving the nodes that act as values away from the nodes that will be part of the node group. Clearly this contains all of the Value nodes. The vector that it uses to calculate should also be a parameter. Moving nodes gives us

What nodes go into the node group?

We’re creating a texture, not a shader, so the Diffuse and Material nodes are clearly not to be included. Everything else that is not a parameter, except the color ramp is required to create the texture.

Do we include the color ramp?  Normally I would not, because there is no way to control a color ramp that is in a node group, except by opening the group and modifying it.  Doing that will modify every material that uses the node group.

In this case, I’ll make an exception. The color ramp has a very specific purpose that’s unlikely to change, and there is a parameter that can be used to tweak it. The node group starts out as

and our material now looks like

This is a good time to give the node group its own unique name.

Merging parameters

Creating a node group this way has the annoying feature that parameters, in this case the Vector and spacing parameters are duplicated.  Merging those gives us

Naming parameters

The node group has several “value” labels for its parameters.  Better names will make it easier to remember what each input does.

Assigning defaults and limits

Each input parameter of a node group has default values and limits. If there are specific values that make sense, use them. Here are those for the spiral node group

Spiral parameters

Vectordefault for typeminimum for typemaximum for type
Spacing.50maximum for type
Lower Bound00maximum for type
Upper Bound10maximum for type
Groove Width.50maximum for type
Density10maximum for type
Arms11maximum for type
The default and limit values of the parameters to the spiral node group

The wording “… for type” means that that parameter is set to the value it has by default when you make the input parameter.

The default value for the Vector input is a problem.  Because it is 0, if you don’t connect a Texture Coordinate node output to this input, the node group will not produce a useful result. It would be nice to use the Object output as a default, but doing so is very difficult.

All of the parameters have maximum values of “maximum” for type. This is because there is no easy to describe upper bounds for most of these values.

The default and minimum values for all except the Vector input can be selected in ways that make sense, so they are set.


It’s a bit difficult to figure out where each connecting line goes. There are various ways to make it easier to read a node group and there as many opinions about them as there are node group developers. The one that’s right is the one that makes the group most readable to you. I like the way printed circuit diagrams look so my node groups tend to end up looking like that.

Recently I started adding labels to the reroute nodes, so my final version of the node group looks like this.

Here’s a closeup of part of the reroute



Sticking to a handful of rules about how you lay out node groups in the node editor will make it easier for you to read your own node groups later when you’ve forgotten what they do. Here is a set of rules that work for me.

  • Give the node group a meaningful name.
  • Give the input and output parameters meaningful names.
  • Set the defaults and limits on parameters.
  • Center the node group.
  • Align the nodes into evenly spaced rows and columns.
    • Use the rows to indicate flow through a section of the group.
    • Use the columns to group similar operations.
  • Use frames to visually group sets of nodes that act together to perform a function.  This tutorial describes the function step by step, so doing so is left as an exercise for the reader.
  • Use reroutes to clarify the flow.
    • Minimize connectors crossing each other.
    • Minimize connectors crossing nodes.
  • Label reroutes.
  • Use a frame containing a text to document the node group. Also left as an exercise for the reader.


I have described my usual workflow for converting a group of nodes into a reusable node group. It is only one of many. It may not be the best for you, but it can serve as a starting point.

  • Fix “magic” constants.
  • Filter parameters.
  • Separate parameters from node group.
  • Determine what nodes belong to the group and create it.
  • Merge parameters.
  • Name the node group and the parameters.
  • Give the input parameters reasonable default, minimum and maximum values.
  • Lay out the nodes within the group to make it more readable.
  • Add frames to visually group nodes within the node group.
  • Add a frame with text to document the input and output parameters

I have not described how to collect node groups into files so that you can easily add them to blend files as needed. I have a method, but it doesn’t work very well. Please comment if you have one that works well for you.