Normal Map format X-Y-Z+?

Started by Treidge, February 16, 2021, 08:18:42 AM

Previous topic - Next topic

0 Members and 3 Guests are viewing this topic.



I wonder why the documentation for the Keyshot is lacking a hint on what Normal Map format the software is using. I've tried to assemble a simple scene and noticed that all my Normal Maps are rendered wrong.

Keyshot isn't using OpenGL or DirectX-like normal maps as they come by default? Both formats were rendered wrong in my experiments. Normal maps generated by the software such as Substance Painter/Substance Designer will be rendering incorrectly inside the Keyshot. So will textures from websites hosting texture libraries - unless they were specifically tailored to the Keyshot beforehand.

My experiments demonstrated that the correct Normal Map format for the Keyshot (at least on Windows) is X- Y- Z+. To OpenGL-like format, it's a red and green channel of the texture flipped (inverted).

Unfortunately, there are no options inside the app to flip (invert) colour channels of the Normal Map texture. Having only OpenGL or DirectX-like Normal Maps, to render them correctly, one needs to process them manually inside some image editing software such as Photoshop.

My question is: is this the case? X- Y- Z+ is the correct Normal Map format? Not a bug?

My suggestion is: it would be nice to have an option to flip channels (at least red and green) of the Normal Maps inside the Keyshot. It would increase app compatibility because most Normal Maps out there come in OpenGL format.


Can you show a visual example of a normal map rendering incorrectly for you? (and also, show one that is rendering correctly) I've never had any issue with any normal maps and your post is the first time I've heard someone make this complaint here. Curious as to what you're seeing that makes you think its wrong.


Sure. It's actually quite easy to demonstrate and anyone could quickly assemble a test scene to check things out.

Let's take a UV-mapped plane to act as a test surface and a plane with half of a sphere to be baked down to a normal map. See the first image for a visual clue.

Place both objects into the Keyshot scene and locate them side by side for a visual reference. Make a lighting environment with a single light source located at the top (around 45-60 degrees above the horizon), so it will cast a highlight on the top-left corner of the high-poly sphere.

Bake down three normal maps. One as X+ Y+ Z+ (OpenGL, the most common one), one as X+ Y- Z+ (DirectX, less common), the last one as X- Y- Z+ (uncommon). Apply them to the test surface and check results. With a correct normal map, highlights and shades locations on the test surface should match the source mesh (plane with half of the sphere). Only the last normal map (X- Y- Z+) produce such a result.

This means that Keyshot is using an uncommon normal map format. If that's the case, it means that the vast majority of Keyshot users were (most likely) rendering their normal maps incorrectly.

I've made a quick check and it seems that normal maps bundled with the Keyshot are actually using the correct format, so this concerns primarily normal maps originating elsewhere.


Ooph, this has bitten me in the past, many times. Your observations are spot on, and the best I've been able to resolve this in KeyShot (without inverting channels) is to use the OpenGL format but to use negative values for the height value.

I created this exact same scene many years ago, and was blown away that the default normal maps in the KS library are not correct when applied with the default (positive) values. I chatted with Dries about this a while ago who confirmed the mismatch.

Some sort of toggle or fix for this would be great, and way overdue. It's knowledge that I've had to share many times since it's not explicitly addressed in the software or manual :/


Quoteuse the OpenGL format but to use negative values for the height value

This is brilliant. Thank you very much for the tip. It's gonna save me a lot of time.  :)

I do hope that this information will find its way into the user manual, at the very least. It would be best to actually ask the support staff or devs directly to take another look at this.


I was actually hoping that Dries might see this post and chime in.