This tutorial is part one of a series.

The Contour Line Material

A tool I use constantly while developing my planets is a material similar to the "Atlas Gradient" found in the 2.0 library. The two key advantages of a material like this are first that it gives a good idea of the overall shapes of the terrain and second that it's pretty fast for both RTR performance and test rendering. This is not a material to use on a final render, it's a tool to help you judge the shape of your world while you're creating it.

It's also a semi-coherent way to throw a bunch of MojoWorld concepts at you all at once with some hope of making sense of it all.

Check out this side-by-side comparison of two views of the GPS globe in the Navigation Editor - the first with the default grey material and the second with the Contour Lines material this tutorial will create. The first gives almost no information at all about the shape of the planet, while the second looks like a world already.

Similarly, here are two renders of the v2 default planet terrain, first with the plain grey material and second with the contour line material. The red contours are every 200 meters, the yellow contours are every kilometer. The thing I find terribly interesting about this pair is how the elevation-based coloring gives so much more information about the height and depth, but the plain grey allows much more of the surface detail to come through.

Getting Started - A planet to work with

It's far more interesting to try this material out on a real terrain, not the perfectly flat planet you get after File->New, but I think it's more important to explain this material before I go explain how to make terrain functions. I recommend starting with File->New, then loading the v2 default planet terrain texture from the library. Starting fresh like this means there won't be extra complex clouds, moons, water, etc. slowing down any test renderings.

All of the action in the contour lines material happens in the diffuse color texture of a single 'Displacement Material' leaf. Open the Material Editor for the planet. The default plain grey material has a single material leaf. Open that leaf's control stack. Set the diffuse color to a texture. A texture editor will open. Choose 'New Texture' off the menu and then enable the first texture leaf.

Anatomy of a Texture Leaf

The texture leaf kickstand consists of four parts. Data flows from the bottom of the kickstand upwards. It often helps to ask, 'what sort of input do we have and what do we want to do with it?' when creating textures in MojoWorld. What I hope I can do over the several parts of this large tutorial is explain how to figure out the answers to those questions and to give you an understanding of why we want to ask them in the first place.

  • Input: The bottom-most item is the 'input coordinates'. It defaults to 'World Position' but for almost all of the texture leaves in part one, we'll be setting it to 'Altitude'. 'Altitude' is one of the many inputs that are not available for textures used to define the terrain shape. A general rule is that color textures are a lot more forgiving than the terrain shape texture. More about that in part two on terrain textures and in part three on distortions.

  • Distortion: This defaults to 'None' and for now we'll leave it that way. Part three covers this in more detail.

  • Main Fractal: The default here is 'Monofractal' but we'll be setting it to 'None' for every leaf we make in the Contour Line material. More details on this will follow in part two when we talk about terrain textures.

  • Output Controls: What you get for output controls depends on what kind of parameter this texture is connected to -- usually. One major source of confusion for new MojoWorld users is that there are two kinds of textures - color textures and value textures. The way you tell the difference is in the output controls. A value texture will have only an Input Curve. A color texture will have an Input Curve, a Gradient and an Output Curve.

    If the texture is connected to a color parameter (diffuse color, glow color, etc.), then a new texture will be a color texture. The DDLB in the upper left corner will list all color textures first, then after a dividing line, it'll list all the value textures. Similarly, as each new texture leaf is created, they will be color texture leaves and the DDLB for that leaf will list all the color texture leaves first, followed by the value texture leaves.

    If the texture is connected to a value parameter (displacement, shinyness, etc.), a new texture will be a value texture. The DDLB in the upper left will list them value textures first, then the color textures. New leaves will be value leaves and their DDLBs will list value then color leaves.

    Because the DDLBs list first the one type then the other, it's possible and easy to use color textures in value contexts and vice-versa. There's reason to want to do that, which is why MojoWorld allows it to be done. There are also some pitfalls and confusions that can happen, too. Those are the sorts of things cleared up by understanding what the input is and what is going to be done with it. There will be more specific examples of what I mean here in upcoming sections.

The first leaf - belowsea

Open the kickstand of that first texture leaf. Name the leaf 'belowsea'. Set the coordinates to 'Altitude' instead of 'World Position'. This tells the texture that it should base the color on the altitude of the point being colored. Set the fractal to 'None'. The name is 'belowsea' because it'll provide the overall coloring for altitudes that are at an absolute elevation of 0 or below.

The important work of this texture leaf - and indeed of all the texture leaves in this texture - is done in the Output Controls, in particular the Input Curve and the Gradient.

It's easiest to look at the gradient first. That's colors, something artist-types can understand pretty quickly. Here's what it looks like:

This will create sandy areas just below the sea level and then will get blue and dark blue to indicate areas of ocean bed.

Next, into the Input Curve. This cryptic beast is something I'm going to try to explain again and again until _I_ understand it! ;) If y'all can follow it too, so much the better. This is where the rubber meets the road in answering that question of 'what input do we have and what do we want to do with it?'

In this particular input curve for this particular texture leaf, the range of input coming into it depends on the various Altitude values created by the mountain height texture. That was specified by setting the input coordinates to 'Altitude' at the end of the kickstand.

Now that we know our input is the altitude, what we want to do with it is assign it a color based on the value of the altitude itself. To keep it relatively sane, we'll use an Earth-like scale. On the Earth, the deepest ocean trenches are about 10,000 meters deep, so for the minimum input, use -10,000. For the maximum input, we'll use 0 because by definition, this is going to color all the areas below sea level.

When 'Altitude' is chosen as the input coordinate to a texture leaf, there's an extra parameter on the 'Altitude' node, the 'Use Sea Level?' checkbox. For now leave this off, since we're interested in mapping relative to the absolute sea level. With the 'Use Sea Level?' checkbox checked, the material would be relative to the ocean primitive if one is present. There will be more about 'absolute sea level' when we talk about terrain textures in part two. All you need to know about it now is that it's any point where the altitude is zero.

Here's a view of the input curve with some extra scribbles on it to help me understand it enough to explain it. You won't see all these scribbles on a real curve editor and note that I erased the curve zoom handles in order to make a clear spot for these scribbles along the top and right edges of the graph area...

Input goes across horizontally. The green horizontal line across the top of the graph area is the axis along which input is measured. The min and max input parameters tell the curve graph what range of inputs the graph will affect. Remember that the input is coming from the Mountain Height parameter and that could have just about anything attached to it. If you've just done File->New, it'll be a constant 0 everywhere, which is the planet's absolute sea level. It's possible that the texture or function attached to mountain height generates nothing below 0 or maybe it only generates values below -10,000. We'll revisit that when we get to the next section on creating terrain textures.

That little 'Beyond Input' menu determines what happens if the value coming in is outside of the range one way or another. Leave it set to the default of 'Continue' for now. I'll mention in passing that for a gradient, 'Continue' or 'Clamp' end up meaning the same thing. In either case, a value larger than 0 will get the sand color, a value less than 10,000 will get the dark blue color. We'll revisit another 'Beyond Input' choice when we look at the blend between the second and third leaves of what will end up being a four-leaved texture.

The output axis is vertical. A key concept here is what does output mean in this case? For the input curve on _all_ color textures, the value of the output determines which point along the gradient is used. The left end of the gradient corresponds to 0 and the right end corresponds to 1.

The vertical green line considers an input of -5,000. The place where the red input curve crosses that line determines the output, indicated by that horizontal blue line. That in turn corresponds to a value between 0 and 1, which then goes through the gradient editor to result in a point along the gradient. For our example input of -5,000, the resulting color is medium blue.

An interesting thing about the curve editor is that for any vertical line you can draw through it, that line will cross the actual input curve line once and only once. That turns out to be a critical concept in understanding how curves work. Also note that for this texture leaf, we haven't changed the shape of the input curve at all - it simply provides a way to map one value (the altitude) onto another value (the color).

The second leaf - abovesea

Enable the second texture leaf. Open the kickstand. Name it 'abovesea'. Set it up just like the first leaf, with the coordinates set to 'Altitude' and the fractal set to 'None'. The big differences here are in the Input Curve and the Gradient.

For the gradient, I like to have my sand color match exactly, so I take a little detour through the library. Go back into the first leaf, open up the gradient editor, save the gradient to the library. Then, back in the second leaf, go into the gradient editor, load up that gradient from the first leaf and re-arrange the points so that the left-most end is the sand color. Re-color and add new points in to create a gradient like this:

The Input Curve is just a matter of specifying the min and max input values. The min is 0 by default and by definition, since we want this gradient to start at absolute sea level. The max gets set to 10,000 which is almost a kilometer taller than Mount Everest. This now works exactly the same way as the first texture leaf, but it applies to points whose altitudes are between 0 and 10,000.

The first blend - absolute sea level

By default, the blend between the leaves is 'Maximum'. Change this to 'Altitude'. It's not really necessary to go into the curve editor for the altitude blend, because the default min and max inputs are 0 and 1 which is close enough to the absolute sea level we're interested in. To make it really absolute, you can set the max input to 0.001 so that the blend between the two leaves happens sharply at an altitude of 0.

I will say a few brief words about what the output values mean in this case. They default to 0 and 1. An output of 0 tells the color to come from the 'belowsea' leaf and an output of 1 tells the color to come from the 'abovesea' leaf. Since the two leaves are the same color at the altitude corresponding to 0, there won't be a visible line between them.

The other digression here is that a just plain 'Altitude' blend does not have the concept of 'Use Sea Level?', so if you want to tie your coloring to the height of the ocean primitive, you'd need to make this blend of type 'Blend' and use a texture leaf that is itself driven with 'Altitude'. More on blend values when we get to the second blend.

The third leaf - 200m lines

This leaf is different from the others. The fractal gets set to 'None' like the others did, but the input coordinates aren't set to 'Altitude', they're set to 'Constant' instead. The input type of Constant has two parameters, one is the type of constant to output and the second is the value that constant should have. As it turns out, we don't care at all about what kind of constant we output or what value it is, so just accept the default type of 'real' and default value of '0'. The job we want from this leaf is, "output the color for the lines anywhere and everywhere." With a constant input, the mapping through the curve will always be the same. The output from the curve goes onto the gradient. So what we really need to do for this leaf is set the gradient to all one color. The easiest way to do that is to delete one of the end points of the gradient, then set the other end point to the desired color, in this case I've chosen red.

A side note - if all we want is for this leaf to output a constant red, why not set the type of input constant to 'Color' and set that color swatch to red? Well, what happens is the constant red color would go into the input curve and then would get mapped onto the default gradient, which goes from black at 0 to white at 1. So a constant input of red actually comes out grey...

The second blend - creating lines

A solid red is all well and good, but how does it get turned into contour lines? By using a texture as a mask. Change the default 'Maximum' blend to a blend of type 'Blend'. Name the blend texture leaf 'line blend'. Set it up like most of the other leaves we've done so far, with 'None' for the fractal and 'Altitude' for the input.

All the other leaves we've looked at so far have been color textures. That means they have not only an input curve, but also a gradient and an output curve. Since this texture leaf is being used for a blend, it's a value texture. It has only an input curve. What comes out is a value which in this case will determine the blend amount.

As we've done before, the input is the altitude. For our min and max input, we've got 0 and 200 because we want our contour lines to appear every 200 meters. Once the min and max input are set, the values that get shown in the Input field below the graph area of the will be shown in that range. There are four points on this curve. The first point is at min input and an output of 0. The second point is at an input of 195 and an output of 0. The third point is at an input of 196 and an output of 1. The fourth point is at max input and an output of 1.

The reason why I phrased the location of the first and last points as 'min input and an output of 0' and 'max input and an output of 1' is because those points cannot be moved off of their respective input axes. The first point of the curve will always be on the min input axis and the last point on the curve will always be on the max input axis.

The min and max output are left at the default of 0 and 1. Where the output is 0, the color comes from the upper leaf or leaves on the texture tree, in this case, the result of the blend between the abovesea and belowsea leaves. Where the output is 1, the color comes from the lower leaf or leaves on the tree, in this case, the solid red color of the contour line leaf.

The 'Beyond Input' menu is set to 'Repeat'. The min and max inputs could have been set to 1000 and 1200, with the second and third points coming around 1195. The point here is that the input curve defines a range of 200 meters which for the first 195 of them outputs a blend value of 0 and for the last 5 of them outputs a blend value of 1.

The fourth leaf - 1Km lines

Red lines every 200 meters. Red lines everywhere! But wait, there's a problem... The contour lines are only showing up above 0, there are no contours in the sea bed! There's an obvious edge between our 'sand blended with rich green from the abovesea leaf' and our 'sand blended with light blue from the belowsea leaf' colors, which happens at altitude 0, but there should be a contour line there, and at least one more visible in the bluish sea bed areas. The lower picture shows what it'll look like after we fix this and make the contour lines at every kilometer be yellow instead of red.

This is because the result of (A + B) * C is different than the result of A + (B * C). The order our leaves are being evaluated in is what's keeping the contour lines off the sea bed. Just like data in a texture leaf flowing up the kickstand, data in a texture tree comes from the lowest leaf first. So really we've got:

  • 'paint the planet all red' (leaf 3)
  • 'except for these spots' (blend 2)
  • 'where it should be abovesea color instead' (leaf 2)
  • 'but only above 1 m altitude, everywhere else should be...' (blend 1)
  • 'this belowsea color' (leaf 1).

There are two ways to fix this. One would be to re-order the leaves so that the '200m lines' leaf comes before the belowsea and abovesea leaves. The other way is to get ahold of some of them there parentheses. But MojoWorld doesn't give you parentheses 'til there are four leaves, even though there's clearly a use for them with only three ('just re-arrange them' isn't as easy as 'just poke the paretheses button!').

Up 'til now, the texture tree has looked like this:

The plan is to make it look like this instead:

Add the fourth leaf. As soon as the fourth leaf is there, that second magic 'parentheses' button appears on the left. That'll toggle the configuration of the texture tree between the 'straight 4' version to a '2-up / 2-down' version.

Name that last leaf '1k lines'. Set its input coordinates to 'Altitude' and the main fractal to 'None'. As with most of the leaves we've made here, the magic happens in the Output Controls. In the Input Curve, set the max input to 1000 and the 'Beyond Input' menu to 'Repeat.' Leave everything else as the default.

The tricky bit is in the Gradient this time. Here I've taken the two end points of the gradient and put them at 0.97 and 0.98'ths of the way along. The exact same results could be had by leaving the end points of the gradient the way they default and instead, draw a curve that looks a lot like the curve we have on the second blend texture with the sharp step in it.

The last blend

The last blend between the final two leaves defaults to 'Maximum' and that works for our purpose. The last leaf is putting out black everywhere, except for at altitudes of 980 to 1000 and 1980 to 2000 and 2980 to 3000, etc., where it's yellow instead. Red is 'bigger' than black and yellow is 'bigger' than red, so when we get to the next 'and output red everywhere' leaf, what was black becomes red and what is yellow stays yellow.

Well, that ended in a bit of an anti-climax. Ah well. On to terrains where having this contour line material handy will help you see what's going on with those.

Back
On to terrains