With traditional 2d art (like sprites and background paintings) the artists had a much more direct control over the final look. The result was tweaked interactively to a certain look and no matter where an object was placed in the level, it looked the same. The content was independent from the surrounding lighting conditions. Nowadays, the viewer perceives the art assets influenced by the lighting model of some rendering engine and the artists can only indirectly control the visual result by light, material and texture setup. It is much harder to achieve the desired look in dynamic situations. This is why understanding the technical properties of an engine can help artists to get the best out of the technology.
Ideally there would be no need for normal maps which are a GPU friendly implementation of bump maps. Even the smallest details could be modeled as geometry. However, performance, memory and quality of detailed triangle meshes are still a big concern. Normal maps cannot modify the surface, they only affect the shading, so on silhouettes and in combination with shadows the illusion can vanish. Normal maps can store surface perturbations at various feature levels (e.g. 10 cm .. 0.1 mm) but it works best when the details are much smaller than the 3d model features. Normal maps are mip-mapped like most other textures. This is not correct as surface details can vanish when averaged like colors.
For example, one normal map pixel that points upwards and an adjacent one that points downwards become a single flat pixel in the next lower mip-map. Good art can reduce this effect by avoiding details that are too high-frequent. Having details at various scales also helps to improve the look. Having some details like noise or grain in the texture also helps to hide compression artifacts and often the compressor can compress the result with better quality. Normalmap artifacts are mostly noticeable in the specular highlights or in reflections, as minor differences in the normals become amplified.
Poor normal map (left), good grayscale height map (middle) and resulting normal map (right).
Unwrapping and Mip-Mapping
When unwrapping a model, it is not enough to have the UV mapping solely work well for the top mip-map. The unwrapping should also work well for lower mips. The following example shows a black border that introduces wrong normals in the smaller mips. The simple fix is to set a more average background color which is easy for tangent space normal maps. The most correct solution would be to give the unwrapping some texel border and use the border expand feature (SRF to TIF conversion in Polybump) or at least fix the issues in Photoshop. In the example pictures the first mip is ok but the second mip already results in bad shading.
The following textures are useful to test if the tangent space of a mesh is good (art and code wise). They can be found in
UV.dds (left) and what it looks like when texture is applied to a mesh as diffuse map (right).
The texture helps to reveal where mirroring is applied and shows extreme rotations in texture space.
TangentReference_ddn.dds (left) and what it looks like when texture is applied to a mesh as bump map (right).
The normal map data of the tangent reference represents a truncated pyramid with 45 degree sides and another smaller truncated pyramid of the same type on top of it. This texture can be assigned to the bump map channel of some object. With tiling (use the diffuse map tiling) it is easier to check for problems.
The tangent reference can be used to check if the normal map is lit correctly on all sides. For this test it makes sense to reduce the overall lighting (for example by selecting night in the time of day settings) and to put a point light close to the geometry. All sides of the pyramid should be lit consistently.
Good unwrapping tries to minimize the shearing of the texture. Shearing means that the angle between U and V vector is not 90 degrees. However, even with very good art setup the problem of seams cannot be fully avoided and it is recommended to place seams in hidden or not important areas of the mesh. This can be controlled by the artists when doing the unwrapping.
Extracting Normal Maps from High-Poly Objects
This information might help if you have problems with seams:
Texture mirroring with seam (left) and mirroring without seam (right).
- Take a look at your high poly object:
- Does it have the same problem?
- Have you calculated the normal map only from one side? Smoothing is not the same without merging both sides!
- Take a look at your low poly object:
- Have you calculated the normal-map for the same low poly object? Smoothing is not the same without merging both sides!
- Are the low poly and high poly objects really corresponding? For example, if they are slightly displaced this could create a seam.
Tweaking the Right Value
To control the final pixel color, you need to think where in the pipeline you want to affect it. There might be multiple possibilities to tweak one scene and the choice can affect how other scenes look like (view direction, time of day, eye adaptation level). This is different from a movie production where the final image can be checked. Let's say we want to change some gray concrete to be a bit more desaturated since it's slight yellowish. The material can be tweaked very quickly to make it less yellowish but the material might be used in other places and there someone might have tweaked the light sources already to get the gray result. A good artist would check the texture first. The idea is to have textures dry which means they should not be affected by lighting. Furthermore, it is recommended that all textures have a similar brightness so that when a texture is switched for a material, the material doesn't need to be readjusted.
On the other hand, it is best for texture compression quality to have bright textures and dark materials as this results in more accurate internal color computations. The brightness is also affected by the tone mapper (only in HDR) and the eye adaption (currently HDR only but that can change). However, those should be tweaked with care and only by programmers that understand all implications. Finally, the post-processing (e.g. color grading) can change the look again. For tweaking it is best to switch off post-processing and tweak materials in some known lighting conditions like night, daylight or foggy ambient.
Natural Outdoor Lighting
A common sunny daylight condition can be created with a bright yellowish sun color, a bright blueish sky (=ambient) color and some angled sun direction to get nice shadows. When using the time of day feature, it is recommended to not have the sun perfectly at the highest position. This can be avoided by specifying some angle in the Terrain Lighting dialog (north pole, equator, south pole). It is also good to have some rotation there so that the shadows are not aligned with the world direction. This is all to make man made buildings look better as they are often world aligned and built straight up.
Shadows From the Moon
The time of day features change the sun position and other properties dynamically depending on the day time. In the night the moon might be the only major light source and the shadow system automatically uses the moon position when the sun is below the horizon. The system automatically fades from one state to the other but if the viewer pays special attention, he might notice the lack of shadows for a short while. This is because we want to avoid computing shadows from the sun and moon to fade out both. This is rarely and barely visible and can be hidden to some degree by smart game design.
Global Illumination Look
Indirect lighting is light that gets bounced from some object and becomes colored by the surface it bounces from, taking over parts of the texture and material color. Darker surfaces reflect less light. A good surface color is some bright beige. The effect of color bleeding is perceived the best with vibrant colors. High frequency texturing should be avoided as it is hard for the human eye to see the subtle effects of global illumination.
Output Device Colors
Different display technology (CRT, TFT, TV, beamer, ...) reproduce the same input signal in different ways. There are differences in sharpness, resolution (scaling quality), latency, color and the range of values that can be represented . More variety can originate from the used connections, cables, the graphics card (X360, PS3, PC) and the driver settings. Furthermore, the viewing environment where the display is located (reflections from windows, day or night) can affect the way how colors are perceived.
The best for limiting those problems is a defined setup in a room with fixed lighting conditions (no windows, one switch for the lights). A display of each type allows to check the same scene quickly. Configurations shouldn't be altered and some person should be made responsible to verify the setup regularly.
There are certain good practices and even some requirements for developing on TVs. Dark colors should be avoided if the content there is important as on some displays those dark colors all look the same. For example, most TFT's cut values <12/255 and worse TFT's even values <24/255. By adding grain (animated noise) to the image and de-saturating it, the image is perceived as darker but might give a better visibility.
Importance of Features
Many features can be tweaked to have little effect on the result (dark lights, dark ambient color). This is often bad as performance is always a problem and expensive features should contribute to a good degree. Instead it should be considered if the feature can be switched off as that might free up resources for other features. If scalability of the product and consistent look is a concern, it might make sense to reduce the effect of some feature that only exists in some spec settings. If features are tweaked down to hide some artifacts, this can lead to more problems as the need for fixing them could be delayed and more time is wasted.