Tuesday, March 23, 2010

Mean Curvature, Cavity Map, ZBrush and nice tricks for enhancing surface shading

There are many many techniques for enhancing the look of a surface by mean of smart shaders. Without touching Non photo-realistic rendering techniques there are many tricks that can helps the perception of the features and the fine details of the surface of an object. ZBrush has popularized one of these techniques with the name of cavity mapping. The main idea is that you detect 'pits' on the surface and you make them of a different color and, very important, very dull. In practice it simulates in a rough way all those materials where in low accessibility regions dust/rust/oxide accumulates while in the most exposed parts the use make them shiny. You can do such effects in MeshLab and they can be very useful for making quick nice renderings of scanned objects; let make a
a practical example using a 3D scanned model of ancient statuette of the Assyrian demon Pazuzu (courtesy of Denis Pitzalis C2RMF/Louvre). The plain model (shown on the right) is rather dull and not very readable and at a first glance you cannot appreciate the scale of the scanned details.



You can improve it a bit by adding a bit of ambient occlusion. In MeshLab you can do it in a couple of ways, either computing an actual ambient occlusion term (e.g. a steradian denoting the portion of sky that you can see from a given point) for each vertex (Filter->Color->Vertex ambient occlusion) or just resort to a quick and dirty Screen Space Ambient Occlusion (SSAO) approximation (render->Screen Space Ambient Occlusion).In the first case as a bonus you are able to tweak the computed value as you want (by playing with the quality mapping tools), in the second you have just an approximation, but the nice fact is that it is a decoration e.g. it is blended over the current frame buffer and therefore it mix up with whatever rendering you have. In the two pictures  per vertex AO vs SSAO.

Not enough. Lets try to find out and enhance the pits. Mean Curvature is what you need, you can think it as the divergence of the normals over the surface and it captures well the concept of characterizing local variation of the surface. There is a vast literature on computing curvatures on discrete triangulated surface and MeshLab exposed a few different methods (and it has also a couple of methods for computing them on Point Clouds). The fastest one (a bit resilient on the quality of the mesh) is filter->color->Discrete Curvature. On the right you can see the result of such filter mapped into a red-green-blu colormap.
if you want expmeriment you can try the various options under filter->normal->compute curvature principal direction (be careful some of these filters can be VERY SLOW).




Now the final step is just to use this value for the shading. Just start the shader called ZBrush and play a bit with the parameters and then, hopefully, you can get the desired result. Some notes. It happens that curvature has some outliers so clamping the quality values before starting the filter can be a good idea (filter->quality->clamp). Similarly the range can be very large so playing with the "transition_speed" parameter of the shader can be a quite useful. To vary the amount of "pits" use the "transition center" slider.