The theory - A closer look
Part III: The highpoly object in modo 401
Part IV: The lowpoly object in modo 401
High poly object modeling.
Use as many polygons as deemed necessary. Instances, replicators, particles, metaballs, any technique goes. Only quality matters.
Using subdivision surfaces makes it easier to create smooth, rounded edges and corners, which can be captured in a normal map nicely.
High poly object texturing.
Same thing as above: use whatever tool, method or technique necessary to reach maximum quality. Use a dozen 8K textures along with procedurals, doesn’t matter, only quality does.
At first it might look like a difficult job, but fortunately advanced tools make the work much easier: we have UV unwrappers, we can paint 4K textures right on a 1M poly model and make practically any kind of surface in shader editors.
Rapid preview capability (like FPrime for Lightwave or modo’s preview viewport) is essential to this step as it provides a quick feedback thus really speeds up the creation process.
There is often confusion about the place of Photoshop in this workflow, but it’s very simple really. There are two important things to remember:
1.: “Do the 3D work in the 3D application”
2.: “Do the 2D work in a 2D application”
For example you need a metal box with the paint scratched off here and there.
Making the painted metal texture, the underlying rusty metal texture and the mask for the shapes of the scrapes is a 2D task.
Placing said texture maps onto the surface is a job for a 3D software.
In a 2D package it is kind of difficult to consider the shape of a 3D mesh, it was not built for that. (And the 3D paint toolset was not made for photo retouching for example.)
So use each application to the type of work it is for:
- Define material qualities in 2D: create very high resolution, tiling textures without unique, object specific features. This makes possible to reuse each texture on several objects with little or no adjustment. (See more on re-usability bellow.)
- Create masks in 2D or 3D: Photo based scratches make great masks to blend between different materials. Alternatively you can quickly paint onto a 3D mesh to define where you want to see dirt, rust, etc.
- Place the 2D assets on the 3D mesh in a 3D package.
It is just like working in Photoshop (especially with layer based shader editors), only the canvas is the surface of an object. Placing textures on top of each other, changing blending modes, using alpha masks, all work the same as in PS.
Here is an example of the different layers on a highpoly object:
The raw metal is the most common material quality on this machine part. A baked ambient occlusion map is there to separate the bits and pieces of the machine. The reflection and specular amounts were toned down a bit. After that a set of textures are used to displace rivets and crevices, colorize and add precomputed AO to them. Then scratches are placed at edges and corners.
An oil leak layer is added, along some simple color adjustment which slightly alters the base metal’s color on different assembly parts. Then the rest of the materials are defined, and finally the stripes are added.
To place textures on the 3D surface, one or more UV maps are needed. Creating a UV map for a high poly model might seem to be a daunting task, but it’s not as bad as it looks. By using UV unwrapper and “relax” tools, distortion free poly islands can be quickly created, while “pack UV” functions arrange them in an efficient way. Actual polycount matters much less than before, when most of the UV work was manual poly massage.
If possible, have the UV seems on material borders or where the topology suddenly changes: at sharp corners and edges texture discontinuity is expected. In other words, keep together in the UV polygons which somewhat belong together in 3D.
Something like this:
While sometimes certain polygon UVs might need some manual adjustments, properly made and over sized textures usually take care of seams: they only become visible at extremely close ranges.
If the seams are located at sharp edges or material borders, then they will look fine, since discontinuity is present at those places in real life.
Also, the interaction with other textures (grime, wear and tear, etc) and the bilinear filtering on the baked texture will make these artifacts less apparent.
Usually only one all encompassing UV is required. All other UV set contains only a handful of polys.
- Reusability and presets.
Making several, very high resolution textures for a single surface (diffuse, specular, bump and other maps) can take some time, but by creating texture and material libraries we can save a considerable amount of time and effort on the long run.
(On the left it’s the online material library for modo.)
Again, the textures are there to define material qualities and should not contain object specific features: their arrangement on the 3D object and combination with other textures will make up the unique result.
They are general, so a preset library can be created, reused and extended by other artists. The more work at the beginning will start to pay off when whole material rigs can be dragged and dropped onto objects.
Small adjustments (hue shift, saturation tweaks, etc) are usually needed to get the best look, but the important thing is that the tedious, repeating setup work is done only once.
This step, texturing the high poly object, requires the most attention. It can be done reasonably fast with top quality, but there is one thing to look out for: Don’t get carried away with unnecessary details.
Often check the object from the distance it will be seen most of the time in-game. Know how it will be used eventually, and cut corners whenever you can: don’t waste too much time on polygons only seen when the player is lying on the floor dead. Slap on a material which makes sense there but there is no need to add extra layers and effects there.
It will take some practice to get the quality/speed ratio just right, but I think it’s worth the effort.
Freezing design, releasing asset.
The design is considered final when the lead artist accepts the look of the high poly object. From then on the frozen asset is the reference when tweaking the ingame asset.
The mesh is locked down so the high poly artist can move on and people taking over the task can be sure that this asset will not change significantly later.
Having said that, adjusting surface properties and replacing textures later on is not a big problem. Since the low poly geometry, UV is not affected, only the baking process and the texture import/export should be repeated.
This also makes possible to make and try out several texture variations on an asset relatively quickly.
Low poly object modeling.
Same job as before. Taking advantage of the re-topology tools can really speed up the process.
In modo the most important feature is the background constraint: it limits the tools to the surface of another object. This makes it easy to create a low poly geometry by drawing quads onto the high poly mesh.
Making UVs.
The goal is to create a UV which covers the most of the texture.
I usually create a quick, automated UV map while I’m refining the low poly model or testing baking distances.
When the low poly mesh is considered final, then I do the final, efficient UV.
Make sure that the UV islands at least 3 pixels away from each other. This will prevent polygons from sharing pixels and reduce color bleeding due to the bilinear filtering.
The following images illustrate the problem:
A blue/green pyramid on a red quad. The colors change abruptly at polygon edges.
When the UV islands are too close together, a pixel’s color can be affected by more than one polygon. Also, due to the bilinear filtering, pixels at the edges of the texture get tainted by pixels from the other side.
In this example the polygon edges are at least one pixel apart, so each polygon has its own set of pixels. There are no artifacts at the edges.
However this one pixel gap is only enough for this resolution. If mip mapping kicks in and lower resolutions of the texture are displayed, then unwanted colors will creep back in. By keeping a 3-4 pixel gap, we can prevent the issue on the first one or two mip levels. Later on it will happen, but by then the object is usually so far away that the problem is hardly visible.
(Make sure that the renderer extends the baked data around the UV islands!)
To make this work easier, I used this guide texture as the UV view’s background in the examples above:
On the full sized image (which is quite big, 1024x1024 and around 1Mb in size) you can see several rectangle outlines. These represent different texture resolutions: 512x512, 256x256, 128x128, 64x64 and 32x32.
So let’s say I know that the final, highest texture resolution for my object will be 512x512. In that case I’ll start to arrange the polygons in the respective area defined in this guide texture.
The individual pixels can be identified on the guide texture, so its obvious how to place the polygons.
When I’m done filling up the 512x512 pixel square, I scale up the UV by 2 so its in the normal 0-1 UV space. (For a 256x256 the multiplier would be 4x, for 128 it’s 8x and so on.)
When I deal with 2048 textures, I just use the same 1K UV guide, but since one pixel there will be 2x2 pixels on the final textures, I keep polys 1-2 pixels apart.
This whole procedure is very similar to creating a UV for lightmaps, after all storing the lighting conditions in an image is texture baking as well.
When you want parts of the lowpoly object mirrored or repeated then you have to hide the reused parts while baking. (Baking onto overlapping polys will produce ugly artifacts.)
There is a neat trick which can easily be done with baking: UV weighing. You can freely adjust the texture density and give more pixels to more important parts. The baking process will keep the seam visibility to an absolute minimum.
Stretched UVs are also fine: the texture density can be different on horizontal and vertical axis, the distortion will be compensated by the renderer.
The first image shows a common UV with the same texture density on both dimensions.
The assigned texture resolution was halved on the horizontal axis in second example. When the texture is applied, the looks more blurry than before, but the circle remains a circle.
The last one is an extremely distorted UV. It still delivers the look and feel, in spite of the weird blurring.
Baking everything.
If you have a UV (final or not) to bake to, then the baking can be set up. The actual process depends on the software you use.
Best case is that you have a bake cage which defines where the baking rays will start. Those cages usually can be adjusted to work around tricky areas like very sharp inner corners.
Less advanced bakers might ask for a constant ray distance, which is far less flexible when it comes to complex topology. However it is possible to tweak the low poly object just for baking by using morph maps.
First, make one which will be enabled when baking. Then see where the constant ray distance causes artifacts, hits unwanted surfaces or misses them all together. With the bake morph map active, adjust those polygons: move them closer or further away from the high poly surface, until it the baked result is reasonable.
Keep in mind that these tweaks make the normalmap on the affected polys less precise: the baker will take the tweaked polys as a reference when computing the difference between the high and low poly geometries. This means that the generated normalmap will fit perfectly to the morphed low poly object, but less so to the original. This will result in odd shading, but often these small hacks aren’t apparent.
Avoid manual post processing of the baked results. Fix problems at the source rather than cover up artifacts by hand in PS.
While collecting the render buffers in one “.PSD” is a good idea, don’t do anything there which can not be redone exactly the same way by an intern at 3 in the morning 2 days before gold submission.
Adjustment layers are useful, groups and layer copies with proper naming make it easy to quickly regenerate texture data after a fresh bake.
Here is an example:
Upon receiving a new batch of baked textures, I just copy the new version of each layer above the existing ones and merge them down. Then I enable the appropriate layer group and export the texture.
Freezing technical aspects, releasing asset.
When the lowpoly object is roughly modeled, it is recommended to transfer the mesh into the game right away: create a quick, automated UV (Atlas mapping for example), bake 256x256 textures with coarse settings and create the related PSD files. Scale up the textures to their intended resolution and export both the textures and the object.
Name everything to their final, proper names, and pass the data to the next (technical-) artist who manages the import and ingame shader setups.
The reason for this early export is performance testing: even with ugly textures and unoptimized geometry, the asset is in the game, which is a very important step. Level designers can start using it, which means that the performance assessment can be done more precisely. You can get feedback on your asset earlier, which means less wasted time and effort if changes need to be made.
As days go by, you will deliver an optimized mesh with tighter UV’s and sharper textures, but no one depends on you after the first export cycle.
When polycount, texture resolutions, collisions data, LOD levels and other technical aspects of the asset are accepted by the lead technical artist, then this sub-task is done.
Transferring the asset to the engine.
Nothing tricky here, get the assets to the engine/content management system, and prepare it so it can be used in game (set up compression, LOD parameters, etc).
It is important to have final asset names, even if the actual assets are “work in progress” versions.
Tweaking the shaders in game.
The actual procedures depend on the engine you use. In UnrealEngine it mostly involves creating and adjusting material instances, based on the appropriate shaders.
The ingame visuals can be brought reasonably close to the original highpoly renders. However, the more important thing is that the asset should match its environment, the context of the game. The player won’t compare it to the high definition mesh, but will experience it as a part of a bigger picture.
The next part is about the practical implementation of these ideas in modo 401.
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