The highpoly object in modo 401
Part I: The theory - Overview
Part II: The theory - A closer look
Part IV: The lowpoly object in modo 401
Scene management
I have a separate file for both the highpoly and the lowpoly scenes. It’s a must when two artists are working together on different stages, but it has benefits even when a single person creates everything: the item list and shader tree will be less bloated. It becomes easier to debug things and to focus on the task at hand without wondering off.
The item list
Let’s start with the overview of the item list.
The first item is the high def mesh itself. Then comes the Workbench group where I keep all temporarily used things: extra mesh layers, backdrop items, additional lights, texture locators, etc.
Then there is the group called “General Render Additions". This contains items which should be only visible when doing “General Renders".
This is a common prefix throughout the the scene. It marks not just mesh items, but any entity which should be enabled when doing “general renders” and disabled when rendering for any other purpose (like baking). We’ll see more of this name later on.
The spotlights come next, and finally a camera called “General Render (CAM)". It should be used when rendering final reference images, along with every other item, group and shader tree layer with the same prefix.
Before modo had animation capabilities I used to have a “temp” camera as well for test renders. Nowadays however I just use keyframes for different camera positions: every keyframe beyond 0 is for test shots. Less cameras make a tidier scene, and I don’t have to keep switching the actual camera in the render settings.
The shader tree
The shader tree is a bit more complex:
I divided the tree into several sections for clarity and made sure that every group is properly named. I’m also using the prefixes mentioned earlier to indicate the functions of different layers.
At the top there are two groups of outputs: the “General Render (OUT)", the function of which is probably clear by now, and “HighPoly AO Bake". The latter group contains outputs used only when baking an ambient occlusion texture.
The shader layers are used in similar fashion. The difference between them is that in the AO Bake shader has indirect illumination and shadows disabled, as they wouldn’t affect the AO texture at all.
The last section in the tree is for all the layers which actually affect the surface of the mesh.
The top most layer, called “HighPoly AO Bake - Set UV” is never actually enabled, it’s just there for convenience: if I select it, modo automatically selects its UV set, so I don’t have to fiddle around in the UV list to select which UV I want to use when baking to outputs.
The similarly named material bellow it is there to nullify the complex texturing bellow, which is irrelevant when baking AO. The high resolution textures and procedurals would slow down the render unneccesarily.
The next layer, member of the “General Render” family, is there for cosmetic purposes: it dims (multiplies by 0.1) the luminous values, so they don’t render as pure white on the reference renders.
When it comes to baking the mesh to its lowpoly counterpart, this layer is disabled, so emissive polys are clearly indicated on the baked texture. That information will be used by the in-game shader to mask out the flashing light effect on the object. Additionally, due to GI, the emissive material illuminates surrounding polygons.
Then comes a group called “Instanced elements", which store commonly used, multi layer groups. The always disabled “originals” are stored here, only their instances are used in materials bellow.
A typical example for this is the “Bolts” texture set. It consists of five texture layers:
A bolts ambient occlusion layer darkening whatever diffuse color is already present and the same map toning down specular and reflection amounts. A displacement map creates the actual geometry of the bolt and rivets. and there is a simple mask to slightly brighten up the rivets, thus separating them visually from the rest of the surface.
The reason for this group is to keep these often used snippets in one place, so any adjustments to them have to be done only once, here, and the changes automatically propagate to every single instance.
Well, almost.
Unfortunately adding a new layer goes unnoticed, so after extending a group, the big instance hunt begins to replace the old instances with new ones. I usually rename the group to something like “!!!!Groupname” so its easier to see where the instances are (they inherit the name change).
The “Utility” group stores layers showing the UVGuide texture mentioned earlier on different UV sets and any other layers, which I want to see realtime on the model. By placing this group above “normal” materials, we can override the complex material setups with simple layers. As a result, the OpenGL view will not get confused which texture and which UV set to use, and will display what we want. Naturally this group must be disabled before baking or rendering.
And we finally arrived at the “HighPoly (MAT)” group which is a container for all the materials used on the object.
For the sake of clarity, this time let’s start from the bottom and work our way up to see how the different effects are layered.
The “Matr: HD_Painted” is the blue painted metal material.
The material layer at the bottom defines the base values for specular and reflection amount, as well as displacement distance.
The first texture is for diffuse color: “Image: Metal01_diff". It uses the “HP_Common” UV set which has all the polygons unwrapped. (More on UV creation a bit later.)
The next layer is an instance: “HP AO - High contrast". It’s original is stored in the “Instanced Elements” group above.
It uses a baked ambient occlusion image, adjusts it for higher contrast and blends it with the “Color Burn” blending mode to simulate accumulated greasy grime in crevices.
The “Image: Metal01_spec” layer is the specular texture for the diffuse image of similar name. Its blending mode is set to multiply, so it adjusts the values set in the bottom most material layer.
It has an instance just above it, which does the same but to the reflection amount.
Then comes another instanced group from the “Instanced Elements” gang: “HP Bolts 1″. As said earlier, a displacement map generates actual geometry for the rivets and bolts, a precomputed texture adds AO and a third texture controls a slight color change.
All textures here use the UV set called “HP_Bolts", which only contains polys which should have these details.
The “HP Scratches 03 Disp” instance handles the displacement of deep scratches. The reason it’s separated from the “HP Scratches 03 Rest” (which manages color/specular/reflection changes) is that the area they should affect differs for a small degree. The mask for the displacement is slightly fatter than the one used in the other group. It isn’t a big deal, often all aspects of the scratches can be done in one group.
Here is the UV related to the textures used for this effect:
Again, only those polys are present which should have scrapes on them.
And finally the “Image: Metal01_bump” layer adds fine bumps to the surface, using the “Add” blending mode.
That concludes the “HD_Painted” material group. This is a typical material setup I used throughout the scene. The others might use different textures or have different values, but have a similar structure. Often several layers can be omitted: for example I know that I will never want nuts and bolts on the “Grill” material, so I don’t place the related group instances there.
Now let’s move on and see what lies above the “HD_Painted” group.
The “Color variations” group has four subgroups, each one affecting a certain set of polygons. The polygons are marked by “Part” kind of polygon tags: there are polys with the “ColorVariation1″ part name, others have “ColorVariation2″ and so on.
Each subgroup contains a single “Process” layer which adjust the saturation and lightness of the surface, to make it a bit more interesting.
Next is the “Stripes” group, which just adds the black-yellow stripes to the surface, using it’s own UV set.
“HD_Painted2″ is for the green painted surfaces. Its structure is similar to “HD_Painted", but it has no bolt related instance layers.
“HD_Painted3″ is even simpler, as it has no displacement at all, only two kinds of scrapes.
The “HD_Light” defines the surface properties of the warning light part of the object. It uses several textures for displacement, luminous-, specular- and reflection amount.
The grill on the air intake holes are generated by “Grid” type of procedural. A few textures are also used to add dirt and scratches.
The buttons use a very simple material setup, where the only interesting thing is two subgroups colorizing the buttons. They work similar to the “Color variations” for the base metal surface: parts are used to mark polygons and then a simple constant diffuse color overwrites the default color.
The data plate is also made in a rather simple way: a diffuse texture drives diffuse color, specular- and reflection amount, while a separate texture does the displacement.
The last three layer adds surface independent details. They should affect everything, that’s why these layers located at the top of the stack: they will be added last, on top of all the other materials.
“Dust” is for a dust deposit, accumulating on areas facing upward. Masking out such areas is quite simple using a gradient driven by the “Slope” parameter: at 0 degree (up) the gradient is white (show dust) while at 45 degrees and bellow its black (no dust). Then it can be combined with noise procedurals and the baked AO texture.
“Leak” creates rusty leaks on polygons present on the “HP_Leak” UV. A photo based mask is used to mask out the effect of a noise procedural on the diffuse, specular and reflection channels.
And at the top is an AO texture providing a subtle darkening effect on hard to reach areas, separating parts of the machine from each other.
So this is how the shader tree was set up. Before moving on to the UV creation discussion, here are a few hacks and workarounds for common shader tree problems:
Shader tree workarounds
- Use groups, instances and name everything properly. The shader tree is very unforgiving when it comes to layer management, so lousy shader setups make debugging a nightmare.
- If several layers are always used together, try to make a group of them.
- If something is used in more then one place, use instances. Keep the original in an easy to find place so if you want to modify it, you don’t have to dig through the whole tree.
Instances can be modified in place, so small tweaks to them are no problem.
- Due to the limitation of the tree based shader system, a group of layers (or the instance of that group) can not act as a group mask of another group. (Btw, Can you can a can as a canner can can a can?)
For example let’s say I want to use a combination of 3 procedurals as group mask like this:
I also want to use them at several places in the shader tree.
To keep things tidy, I’d make a group for them, so I only need to instance this one entity, the group, and not every single layer.
I would set the group effect to “Group mask” to use it as one, but that won’t work. So instead I set it to “Driver A” (or B, C, D, whichever is free).
Then I use it along with a linear gradient as a “Group mask", driven by “Driver A".
Make sure that different effects don’t use the same “driver” channel.
- When baking tangent space normal maps ("Bake from object to texture"), only the geometry of the highpoly mesh is processed, bump and normal maps on it are discarded. Only displacement textures affect the baked normal maps, since micropoly displacement generates actual geometry while rendering.
Displacements are not just slowing down rendering but also consume huge amounts of memory. This can be a problem on 32 bit systems, with the 2Gb memory per application limit.
Interestingly if a small “limited region” is active while baking normal maps, micropoly displacement needs significantly less memory, while the baking still generates the whole texture.
If that’s still not enough, then the next step is to finetune the displacement settings. I baked the top left corner of the final, 2048x2048 normalmap several times to see which is the longest “Minimum Edge Length” where there are still pixel sharp details. I kept all the test renders and compared them: when the latest result seemed blurrier then the previous step then I knew that I reached the threshold.
UV creation
I’ve already covered the basic principles of UV creation in part two, so here I just show my preferred way to do it in modo.
When the highpoly model is done, my first step is the unwrapping parts. The only thing I care about at this point is having the seams at reasonable places.
Unwrapping the polygons.
The unwrapping is done, so it’s time for “UV pack". It arranges and scales the poly islands, so the texture density is consistent throughout the mesh: if a polygon is twice as big in 3D than another one, then “UV pack” will make sure that their relative scale is similar on the UV as well.
After that, the UV is ready to use with a base texture. When seams are very apparent, a bit of manual massage helps.
For the lightmap/AO baked onto the highpoly mesh, the plain packed UV is fine. It’s suboptimal, but with the higy definition object, we care more about work speed than texture efficiency.
Arranging the UVs.
Finally let’s see how I put the scratches up there. New UV set, select polygons involved, “Unwrap” or “Project from view", then drag to tweak the shape of the scrapes.
UV creation for the high poly object
And this is pretty much it for the highpoly mesh. The final part of the article is about the lowpoly object and texture baking.
Part I: The theory - Overview
Part II: The theory - A closer look
Part III: The highpoly object in modo 401
Part IV: The lowpoly object in modo 401