Proper way to export displacement & normal maps from Zbrush for user in Poser?

  • What are the rules for making a displacement map in Zbrush for use with Poser?

    What are the rules for making a normal map in Zbrush for use with Poser?

    • Is it better to use Xnormal? If so, do you know what the X,Y,Z requirements are? Some programs want a normal map with the X+, or Y-, or Z-, something like that.

  • Crap, I need to edit my post, but can only edit it 2 minutes 30 seconds after making it.

    Here is my re-phrased questions:

    What are the rules for exporting a displacement map in Zbrush for use with Poser?

    What are the rules for exporting a normal map in Zbrush for use with Poser?

    • Is it better to use Xnormal? If so, do you know what the X,Y,Z requirements are? Some programs want a normal map with the X+, or Y-, or Z-, something like that.

  • @zazop

    For displacement maps, grayscale images. Typically 50% gray is "no displacement", black is indented, white is raised. Another alternative is to use something like Knald or Substance Designer/Painter to generate your displacement maps from the normal map.

    Poser uses OpenGL normal maps (not directx). They are always blue (base color is 128 Red, 128 Green, 255 Blue). If, after you apply your normal map in Poser the things that are supposed to poke out are instead poking in, you can use Photoshop or another image editor that lets you change RGB channels to invert the Green (Y) channel.

    What I usually do is bring the normal mesh resolution mesh into ZBrush, subdivide it no more than 6 times (I find ZBrush flakes out and stops responding if you try to export a high res mesh higher than that). Then I sculpt in my wrinkles and folds and other high resolution details on the subdivided mesh. After all the detail is added, you dial back down to the base level, and ZBrush's normal map baking feature bakes all the high resolution detail down into a normal map.

    I believe you also need both a low and high resolution version of the model to bake normals in XNormal as well. It's been a long time since I've used it, though, so I'm not 100% sure.

  • Let me clarify, sometimes there are other colors than blue in a normal map, depending on the height of the detail. Just that the base color is 128-128-255. And they are usually TANGENT SPACE, not WORLD SPACE normal maps.

    I need to have other ZBrush users jump in, though, on what you have to do to create normal maps from objects that use multiple tiles.

  • Poser Ambassadors

    Depends on the app.

    Some apps use 128,128,128 (middle grey) as no Bump or no Displacement.

    Poser uses true BLACK as no Bump and no Displacement.
    (You can use a Math_Fuctions substract node at 0.5 to go from middle grey to Black for no Bump or displacement, so you do not have to change /adapt the texture.)

    FireFly can do displacement on a map pixel level and SuperFly can do displacement on vertex level.

    Normal maps have a flipped green channel in FireFly comapred to SuperFly.

  • @vilters is that right? I always worked on mid-grey as zero bump and black as zero displacement, hence subtracting 0.5 to convert bump maps for displacement use. I must have been doing it wrong all these years! Maybe that's just an impression I got from all the vendors using mid-grey as zero bump and they were wrong too. Huh.

  • Poser Ambassadors

    Long discussion with examples here.
    Link to BB discussion on Displacement maps

    Quote from his first post on the linked page :
    In Poser, displacement is based on the numerical value of the displacement source (image or math nodes.) Black = 0 = no displacement. White = 1 = 100% displacement. Mid gray = .5 = half displacement!
    Many applications other than Poser use a convention that the displacement map is offset by 50%, so that mid gray is intended to mean no displacement (.5 - .5 = 0), black is negative half inward displacement (0 - .5 = -.5) and white is half outward displacement (1 - .5 = .5).

  • Poser Ambassadors

    Bump mapping is actually normal mapping with a built-in conversion of an input height map into normals. Different renderers implement this differently.

    When we appeal to a notion of "neutral" value, I prefer to define it as "having no discernible effect". Keep that in mind as you read on.

    Poser's FireFly can be demonstrated as doing something mathematically not neutral when given a supposedly "neutral gray" bump map (say to yourself height map every time you read bump map and you will begin to grasp what is going on).

    FireFly seems to pretend to move (displace) the surface, then calculate the resulting normal and use that normal in its calculation of normal map modulation. Where surfaces would cross over each other (e.g. lips, eyelid, nose crease, ears), the resulting normal is inverted and results in black instead of the expected diffuse color.


    Clearly, midgray is not "neutral" as I easily discern a difference in the outcome.

    My "midgray" png file is all 128. The numerical value of 128 is 128/255 which is approximately .5, but more precisely it is .50196. If instead of using the map directly, I subtract .50196 so that the effective bump map is close to 0, the artifacts go away.


    SuperFly is a different renderer with a different implementation of bump mapping, which is still conversion from height map to normal map but happens at a different stage. The map itself is evaluated for differences, and directly creates a normal map (internally) BEFORE applying it to the 3D geometry. The upshot of this is that ANY uniform black/gray/white map is a neutral BUMP map. This is obvious from the fact that the derived normal map from ANY uniform height map is nothing but completely flat.

    FireFly doesn't build its normal map that way from the bump map, so we get a different outcome.


    In FireFly, the numerical value 0 (or if you prefer a color, then black) is the only neutral value for Bump (and for Displacement)

    In SuperFly, any numerical value, as long as it is constant, is a neutral value for Bump.

  • @bagginsbill

    Good info there, Ted, thanks!

    Given that info, allow me to add that ZBrush does consider the mid-range colors as producing "no displacement" ...

    From the manual:

    "The Apply Displacement Map button deforms the mesh by displacing polygons as mapped by the current displacement map. When displacing, ZBrush interprets grayscale data as follows: areas at 50% gray are unchanged; lighter areas (greater than 50%) are displaced outward; darker areas (less than 50%) are displaced inward. This button reads the value of the Displacement menu Intensity slider and is disabled if the slider is set to zero."

    There is a "Mode" setting in ZBrush that serves the following function, depending on whether you want to create a bump map or a full displacement map:

    "The Displacement Mode button selects one of two types of displacement effects for display in ZBrush. If un-pressed the effect is Bump Only mode. In this mode, the outline of the object is unchanged, and displacement effects are only visible on portions of the object facing you. If pressed, the effect is Full Displacement mode. In this mode, all displacement effects are created by deforming the object’s shape."

    There is also a setting in ZBrush where you can specify the "mid point" setting. By default, it's set at .5 (middle gray). I'm assuming that adjusting that setting to 0 would make black the "mid point" setting. However, being that you can't achieve a "blacker than black" color in the map to produce indentations in the displacement, it seems to me that leaving the map at default mid-gray as "no displacement" in ZBrush is the way to go, and then using math nodes in Poser to produce negative displacement where needed.

  • Poser Ambassadors

    Best results in Firefly will come from exporting a 32 bit EXR from Zbrush & using it as displacement. Visually the texture map will make no sense but that doesn't matter - import it, plug it into a Math node set to Multiply & then play with Value 2 until the result matches the high-res mesh in Zbrush. The amount of detail that can be achieved is huge.

    I found a comparison I did years ago. This is the scene with mesh & UV's -

    0_1529344693357_T2 - FullScene.jpg

    The map was a single 4k tile. Close-up of the circled area using 16 bit height as displacement shows noticeable pixellation -

    0_1529344778589_T2 - 16bitDisp 34s.jpg

    Close up using 32 bit -

    0_1529344803226_T2 - 32bitDisp 33s.jpg

    So more detail & no difference in render time.

    Superfly is very different though. I would export 16 bit height maps (AFAIK Superfly will not read 32 bit EXR's when used as height but haven't tried for a while) & use as bump. I also use higher res meshes in Superfly with 1 level of subD to compensate for lack of micro-poly displacement & terminator artefacts. I do also use baked normal maps (though not from Zbrush) but they are potentially a lot more complex than height maps - I view them as code, not textures. The tangent basis (nothing to do with tangent space) is different between Firefly, Preview & Superfly so results can vary. Both Firefly & Superfly can use either OpenGL or DirectX maps though.

    0_1529345080752_render results.jpg

    I have found that Firefly & Superfly need different strategies both in modelling & texturing to get the best results, at least for the stuff I make.

    I did make a video demo on baking normals a year ago, I'll see if I can post the link ...

  • Poser Ambassadors

    Link to video

    (can't seem to embed it). [edit: it embedded itself, cool!]

    Covers making a cage in Zbrush; exporting low poly, high poly & cage; baking in XNormal & Knald; set up & simple texturing in Substance Painter; import mesh & textures to Poser; render in Superfly & Firefly; basic processing to go from raw render to finished image.

    Note on using baked tangent space normal maps - the tangent basis used by Superfly is MikkT or mikktspace. It is essential that the normals are baked using MikkT so that the encode & decode are speaking the same language. Firefly uses its own tangent basis, Preview uses something different again which is why normal maps can be problematic between the different engines.

    MikkT has emerged over the last few years as the closest thing to a default tangent basis as the guy who wrote it gave it away freely. XNormal, Knald, Substance & Superfly all use it as default setting as do many other apps.

  • @caisson

    Yeah I use Knald and Substance Designer/Painter to generate maps. Good stuff.

  • @bagginsbill this is excellent information in regard to how the bump maps are processed internally. It truly confirms the redundancy of performing any kind of normalisation on bump maps (apart from scaling deviations from the mean/mode) which attempts to move the "zero-point" grey level. It also re-affirms the necessity of offsetting the zero point of maps designed for bump map use with mid-grey = zero, before they are applied as displacements.

    @caisson the differences you refer to regarding tangent space normal maps would presumably have had no impact or visible discrepancy for macOS Poser users, since DirectX plays no part in their video pipeline (unless running Poser within a Windows emulation), or are there other visible differences (I notice the encoding schemes you mention in your subsequent post)?

  • Poser Ambassadors

    @anomalaus - tangent basis is "a surface-relative coordinate system for the per-pixel normals stored in the normal map, so lighting can be applied to the normal-mapped surface" - more detailed info on the Polycount Wiki here.

    Tangent space means that the normal info determined by the tangent basis is stored relative to the underlying surface; in an object space map the normal info is stored relative to the object's orientation (& tangent basis is therefore irrelevant).

    DirectX & OpenGL are both types of tangent space map but where the "required native direction" of the stored information is different - OpenGL is right-handed, DirectX is left-handed - again, the Polycount link gives more info under Swizzle Co-ordinates.

    Poser has several renders - Superfly uses MikkT as the tangent basis but Firefly & Preview each use their own different tangent basis.

    All that means that if a tangent space normal map is made using some random tangent basis it could result in lighting errors in all 3 of Poser's renderers.

    If a tangent space map is made using MikkT as the tangent basis then Superfly will be fine but there could be lighting errors in Firefly & Preview.

    Whether the tangent space map is OpenGL or DirectX only affects the direction & Poser can use either as the render in my previous post demonstrates.

    The only thing I'm not sure of is if a map created as DirectX format on a Windows system would render with the correct directionality in macOS ;)

    Now tell me, aren't normal maps fun!?!