twirl

OpenGL vs DirectX normals (and roughness vs smoothness)

September 1, 2026·twirl

If your PBR material looks inside-out in Unreal or too shiny in Unity, it is probably the green channel or an inverted roughness map.

Two conversions eat more time than the actual texturing: normal Y-up vs Y-down, and roughness vs smoothness. They look like broken maps. They are the other engine’s convention.

twirl writes OpenGL-style normals and roughness, same as Blender. That is the default. Unreal and Unity want a flip.

Normals

A normal map stores surface direction as color. OpenGL and DirectX disagree on the green channel (Y). Blender, Godot, and most GL pipelines want OpenGL, so leave it. Unreal, Unity, and DirectX want the green channel flipped.

If lighting looks like the bricks are dents, invert green. Do not regenerate. Do not “fix” it in the albedo.

In Blender, Separate Color, invert G, Combine Color, into the Normal Map node. Or a dedicated invert node on Y.

Roughness vs smoothness

Same data, inverted. Roughness 0 is a mirror and 1 is chalk, which is what Blender wants, and what Unreal wants as the R in ORM after packing. Smoothness is 1 minus that, which is what Unity puts in the Mask Map alpha on URP/HDRP.

Invert in any image editor or a one-line shader. Packing later: Unreal ORM is occlusion / roughness / metallic in RGB. Unity Mask Map is metallic / AO / detail / smoothness.

A short checklist

Albedo in sRGB, everything else Non-Color or Linear. In Blender, leave the normals and the roughness. In Unreal, flip green, pack ORM, and use DirectX normals. In Unity, flip green, invert roughness to smoothness, and pack the Mask Map.

Grab a set from twirl and run it through that list before you blame the prompt.