Tillbaka till Bloggen
Handledningar

Normal Map-konventioner: OpenGL vs DirectX förklarat

Varför din normal map ser inverterad ut i Unreal men fungerar fint i Unity — en enkel förklaring av tangent-space Y-axelkonventioner, med konkreta lösningar.

Admin23 april 20263 min läsning11

Du lägger en normal map i Unreal och ytan lyser upp som om solen skulle komma från under. Du lägger samma fil i Unity eller Blender — ser bra ut. Meshen är identisk. Texturen är identisk. Vad händer här?

Två industrier, en axel som inte är överens

Normal maps lagrar en ytorientering i sina RGB-kanaler. Röd = X, grön = Y, blå = Z. Varje PBR-motor dekoderar dem på samma sätt med ett undantag: tecknet på Y.

OpenGL-konvention (Y+): en ljusare grön kanal betyder att ytan pekar upp. Används av Unity, Godot, Blender (Cycles och Eevee), Substance Painters standardexport och alla WebGL-baserade motorer.

DirectX-konvention (Y−): ljusare grön betyder att ytan pekar ned. Används av Unreal Engine, det äldre Direct3D-verktygsketet och vissa CryEngine/Xbox-eraresurser.

Samma byte i PNG-filen. Motsatt fysisk betydelse.

Hur du kan se det på en gång

Titta på en halvsfärisk bump (som en knapp eller kupol) i din normal map. I OpenGL-konvention kommer botten av bumpen att vara mörkare grön eftersom ytan roterar mot Y−, bort från ljuset. I DirectX-konvention är botten ljusare grön.

Om din belysning känns bakvänd i motorn — höjdpunkter där skuggor borde vara — har du en konventionskollision.

Fixet tar 5 sekunder

I Unreal finns en Flip Green Channel-kryssruta i texturs importdialog. Aktivera den så inverterar motorn G-kanalen vid samplingstillfället. Du behöver inte exportera om din källa.

I Unity ställer du in texturtypen till Normal map och importeraren hanterar allt — Unity förväntar sig OpenGL, men det varnar dig om filen ser fel ut. I Blender använder du en Separate Color → Invert G → Combine Color-nodkedja, eller välj helt enkelt DirectX-formaterad inmatning direkt i Normal Map-noden.

Varför två standarder från början?

På 1990-talet definierade OpenGL och DirectX motsatta texturkoordinatutrymmen — OpenGL hade Y ökning uppåt, DirectX hade Y ökning nedåt. När normal maps blev vanliga i mitten av 2000-talet bäddade varje verktygkedja sitt utrymme in i sina utgångar. Avvikelsen fastnade eftersom det är dyrt att vända på en etablerad pipeline.

Generera normal maps utan förvirring

aukimi Normal Map Generator låter dig välja konventionen explicit när du exporterar. Den kör en Sobel-gradient på höjdmappens luminans och packar sedan (−dx·s, −dy·s, 1) i RGB — med Y vänd när du väljer DirectX. Du kan växla konvention efter generering och ladda ned igen utan att ladda upp något nytt.

Formeln är identisk internt. Den enda skillnaden är tecknet vi använder på Y-komponenten innan vi skriver den gröna kanalen. Med vetskapen om det kan du konvertera en fil mellan konventioner med vilken bildeditor som helst: öppna PNG-filen, välj den gröna kanalen, invertera den, spara. Det är allt "Flip Green Channel" gör i Unreal.

Snabbreferens

  • Unity, Godot, Blender, Substance Painter (standard): OpenGL (Y+).
  • Unreal Engine, äldre Direct3D: DirectX (Y−).
  • Ser fel ut i Unreal? Aktivera Flip Green Channel i importinställningarna.
  • Ser fel ut i Unity? Du exporterade förmodligen från ett DirectX-konventionsverktyg — invertera den gröna kanalen eller exportera igen.

När du väl har internaliserat konventionen är fixet trivial. Det svåraste är att känna igen det första gången.

#normal-map#3d#pbr#shaders#opengl#directx

Gillade du den här artikeln?

ShareHN