ZBrushCentral

How does ZBrush calculate normal maps in tangent space?

In more detail, the questions I have are:

  1. How is the normal vector calculated at each vertex? For example, does it use the angle of neighboring polygon faces to weight their normals, or does it just use an unweighted average?
  2. How are the tangent and binormal vectors calculated? For example, is the binormal perpendicular to the other two, and the tangent in the direction of horizontal texture change? In particular, how is this calculated when neighboring triangles at a vertex don’t have identical texture directions?
  3. How is the tangent space basis interpolated across a triangle? Is it a simple bilinear interpolation of the tangent space basis at the triangle’s vertices? Does it have renormalization? Are only the tangent and normal interpolated with the binormal recalculated per sample?

The exact basis used doesn’t matter so much, but it is vital that I can reproduce it exactly in the code I’m writing for the game engine. If I cannot do this, then there will be “faceting” artifacts in the game engine from a discontinuity in normal direction between neighboring polygons. It is particularly important to know how they handle vertices where the normal and tangent / binormal vectors of the adjacent faces are different.

I am not familiar with all the details, but will try to get more info for you. Here’s what I do know:

Question 1) ZBrush is using an unweighted average.

Question 3) The tangent space is interpreted bilinearly.

Thanks much for the feedback Matthew, I look forward to any other information you can track down on this for me. Question #2 is probably the more important of the 3, but the information you have provided me here is still useful.

Looking forward to hearing more!

Just bumping to see if you had found out any additional information on this Matthew. Thanks again for all your help.

Bumping the thread back to reality… plus another question:

  1. Suppose I create a displacement map relative to my base mesh (i.e. lowest LOD selected, switched back to stored MT, CAGE button not used).

If I now subdivide the base mesh without smoothing (in ZBrush) + apply the displacement map, it doesn’t quite work (the displacement map doesn’t seem to be relative to the base mesh, but rather relative to the smoothly-subdivided mesh).

bump

That is correct. The displacement map is created based upon a smoothed mesh. It assumes that your model will be smoothed via some form of subdivision (such as HyperNURBS) before the displacement map is applied.

Thanks, aurick!

Is there a way to export displacement relative to the non-smoothed base mesh? If not, do you believe it is feasible to write such a plugin with ZScript, or would it require effort from Pixologic?

bump