Home Technical Talk

A solution to Normal Maps with mirrored UV's in UDK.

polycounter lvl 11
Offline / Send Message
Fingus polycounter lvl 11
So I don't know if this is common knowledge or very obvious, but I decided to share since I didn't find this solution through google.

Last night I made a simple practice asset and ran into a snag when I imported it into UDK.

It ended up looking like this:

udk_seam.png

Ugh, awful.

My problem is that my normal map is mirrored, which means that half of the UV shells are flipped which cause problems with how the normals are calculated in the engine.

uv_bad.PNG

Look at all that red. That's a bad sign all right.

So after some research I came up with this solution.

First of all you need to fix your UV's. UDK hates mirrored UV's so I flipped the red shells so they are blue and nicely correspond to their geometry again. The problem of course is that they no longer line up with the texture any more, but there's a solution to it.

In UDK you can change the way that textures tile in the Texture Properties. The default is Wrap which is the mode we're all used to, but there's also Mirror and Clamp. Mirror is the one we're interested in because it does this:

texturesettings_mirror.PNG
texturesettings_result.png
Excellent! This means that if we lay out or UV’s this way they will match the mirroring:

uv_good.PNG

But it’s not that simple, because when you mirror the normal map horizontally you end up flipping the X axis (red channel) which causes mirrored lighting. But with a little bit of material editor magic we can fix that.
We can flip the red channel by multiplying the normal map with a float3 with the values -1,1,1, but we want that to only apply to the mirrored UV’s. This is also fairly simple. All we have to do is to lerp the two normal maps with a checker pattern with its UV tiling set to 0.5. This will make it match up to the alternating mirroring and mask out the x-flipped normals from where we don’t need them.

normal_flip_material.PNG

And the results?

udk_shot.png

Perfectly mirrored normals! No seams, huzzah! :D

Hope this is helpful to y’all.

Replies

  • pior
    Offline / Send Message
    pior grand marshal polycounter
    I love how the top screenshot looks like the regular UDK we all got used to, with that one specific artefact showing up so often ... and then your results make it look like a solid modern graphics engine from the future :D

    Cool stuff!
  • Fingus
    Offline / Send Message
    Fingus polycounter lvl 11
    I intentionally wiped out the lightmaps to make the example shot look even shittier. :p

    And I just realized I should have posted this in the UDK subsection. Oops!
  • monster
    Offline / Send Message
    monster polycounter
    This is a clever workaround. Kudos man!

    Just FYI, the issue is with the FBX file format not containing the tangents and binormals, it only export the normals. If you export to FBX ASCII you can look in the file and see they are not present. When you import the model, Unreal looks for the tangents and binormals but uses 0 when they are not found.

    Another way to fix it is to uncheck "Import Tangents" and check "Explicit Normals" But if you have custom/edited normals, they will be lost.

    The Epic guys gave us a code fix that always calculates tangents from imported normals, circumventing the FBX bug. Unfortunately, I can't share it. Hopefully it makes it into a release soon.

    I noticed a new UDK is out today. Have you tried that?
  • Minato
    Offline / Send Message
    Minato polycounter lvl 5
    Nice workaround Fingus, luv working around stuff, been actually thinking about this a few days ago, great job and thanks for sharing!

    @monster, very happy i read that last line, lol...
  • King Mango
    Offline / Send Message
    King Mango polycounter lvl 16
    Wow great find. And I use clamp all the time. Never even once questioned what mirror what do much less noticed it lol +rep
  • Fingus
    Offline / Send Message
    Fingus polycounter lvl 11
    Huh, really? I would have thought that flipped UV's would be screwy regardless of the state of the imported tangents. After all, if you bake normals with flipped UV shells the normal colors inverse.

    I haven't checked out the new version yet. We'll see if anything is different there.
  • Jerc
    Offline / Send Message
    Jerc interpolator
    Thanks a lot for the tip, I was raging over these normal/specular artefacts on my latest assets, now I'm happy again ! :)
  • Eric Chadwick
  • JamesWild
    Offline / Send Message
    JamesWild polycounter lvl 8
    I did suggest this a good while ago to someone having a problem with their Hylian shield on this very forum, they said it didn't work, odd.
  • Eric Chadwick
    Fingus wrote: »
    I would have thought that flipped UV's would be screwy regardless of the state of the imported tangents. After all, if you bake normals with flipped UV shells the normal colors inverse.

    I think the imported tangents should solve the mirror seam (if Unreal imported them properly!). When the tangents are created, as long as they correctly handle your UVs (rotated, mirrored, etc.) then this decides which direction each pixel-normal will be rotated. That's the point of the tangents.

    Baking flipped UVs is a different issue, if I understand you correctly. You should always move mirrored UVs out of the 0-1 UV rectangle before baking. Only the non-overlapping front-facing UVs should be baked, otherwise you get errors in the map. Moving the overlaps/mirrors 1 unit over is a good choice, and they can remain there after the bake.

    I think your shader trick should be discarded if Unreal imported tangents properly, since that would give you accurate results in more situations, and use less shader instructions. But it's still a cool trick nonetheless!
  • Fingus
    Offline / Send Message
    Fingus polycounter lvl 11
    Hmm, I'm confused. I thought that the tangent is the angle of the geometry, and the normal is the vector perpendicular to the tangent. In other words, tangent is XZ and normal is Y.

    So what is the relation of UV's to the tangents? Because my impression was that having a flipped UV shell would be at odds with the normal vector rather than the tangent because when you look at the lighting error it's only the vertical axis that is flipped.

    Besides, if you turn off the option to detect the UV Winding Order in Maya the same error appears, which suggests that it's not an issue with the import as much as an inherent problem with UVs and normal maps.

    maya_uvwinding.png

    Reversing the normals on the effected parts fixes the issue in Maya. But if I were to bring that into an engine I would need a double sided material.

    Also, when I import the model into Unity and make sure to import the tangents the same issue persists.

    unity_import_tangents.png
  • Eric Chadwick
    I'm not a graphics programmer, but my understanding is that the tangent basis is not based only on the geometry normals. It's basically deciding the "flow" of the UV space, so the per-pixel normals in the normal map can be converted into world space (or vice versa, the lighting converted into local space, depends on the shader).

    Yeah, IIRC the tangent basis is made up of three vectors... normal, tangent, and bi-tangent (aka bi-normal). The tb normal is not the same as the vertex normal.
  • cw
    Offline / Send Message
    cw polycounter lvl 17
    wierd, I dont get problems if I export with UV for mirrored areas offset by 1 unit, and making sure to export tangents in the fbx.

    Good trick if you need it though! :)
  • TrampledUnderFoot
    Offline / Send Message
    TrampledUnderFoot polycounter lvl 7
    Not sure this has been covered or not, but it's possible to mask off UV spaces with nodes in UDK instead of bringing in the additional texture sampler with the checker pattern.

    If you place your flipped UV's to the right of 0-1 space for example:

    http://i.imgur.com/JwPce5R.jpg

    For other UV layout situations one could consult UDN's page on material masks:

    http://udn.epicgames.com/Three/MaterialMasks.html
  • Froyok
    Offline / Send Message
    Froyok greentooth
    We talked a bit about this problem here :
    http://www.polycount.com/forum/showthread.php?t=108243
    monster wrote: »
    I noticed a new UDK is out today. Have you tried that?
    The Beta of February 2013 doesn't fix it, I already tried.
  • monster
    Offline / Send Message
    monster polycounter
    So, in 3ds Max, it seems that if you place an Unwrap UVW modifier or a Turn To Mesh modifier at the top of the stack the FBX plugin will export the Binormals and Tangents.

    If they are not at the top of the stack, even if you check Tangents and Binormals in the FBX Export window, they will not be exported.

    Any care to verify if Unreal or Unity imports them properly with this method?

    FBXBinormals.png
  • Minato
    Offline / Send Message
    Minato polycounter lvl 5
    ^Ok, this is odd... Just tried this and actually the only thing that seems to matter is the UnwrapUVW's presence on top of the stack, here's the different scenarios:

    1.No Unwrap mod, Tangents checked on export = Not working.
    2.Unwrap mod on top, Tangents checked on export = working.
    3.Unwrap mod on top, Tangents Unchecked on export = working!??

    And it doesn't matter at all if i check the tangent while importing in UDK or not, the only thing that seems to matter is the presence of the modifier on top...

    Nice find monster.

    Max 2013, UDK Nov-2012...
  • cman2k
    Offline / Send Message
    cman2k polycounter lvl 17
    I noticed that last week....confirmed issue for Max 2012 as well.

    It doesn't happen for me in max 2010 though.
  • JamesWild
    Offline / Send Message
    JamesWild polycounter lvl 8
    If it only happens in 2012 and above, that'd explain why I've never seen this issue myself as I've never bothered to upgrade beyond 2011.
  • cptSwing
    Offline / Send Message
    cptSwing polycounter lvl 11
    Weird, haven't noticed the need for an unwrap modifier here.. it just exports the tangents automatically, whether i tell fbx to or not ;)
  • Visceral
  • Froyok
    Offline / Send Message
    Froyok greentooth
    Well Maya export them at least, but it's not compatible with UDK :

    maya_fbx_ascii_binormals.jpg
  • Fingus
    Offline / Send Message
    Fingus polycounter lvl 11
    So i did some tests by messing around with the UVs and tangent space settings with display tangents turned on. I'm starting to understand how they're related now. I thought the tangent space settings were just viewport display options, but they seem to actually alter the tangents of the mesh. Interesting.

    I also experimented a bit with different import/export settings. Either UDK or the FBX plugin insists on flipping the binormal (blue) on the parts with mirrored UV's. The image on the left is with Import Tangents turned off, and the one on the right is with the setting turned on. Both meshes have overlapping UV's packed into 0-1 and a material where the normal map goes straight into it. No trace of my workaround.

    binormals.PNG

    So this seems to be an easier fix. But what do I lose by not importing the tangents? Leaving Explicit Normals on seems to import my hard/soft edges correctly so the normal map shades without error.
  • JamesWild
    Offline / Send Message
    JamesWild polycounter lvl 8
    Explicit normals -> imports the vertex lighting normals from the file instead of generating them from smoothing groups and face angles in the importer (which may differ from how Max/Maya generated them)

    Import tangents -> imports the tangents defining the red/green channels of the normal map as well. If false, UDK does this itself, which again may be different to how Max or Maya did it.

    Not importing tangents will be fine for most meshes, and you only need worry if you're doing some heavily distorted stuff with crazy UVs and unsplit edges. I've experimented with using this to bake normals on objects with no smoothing group splits at all, but in most sensible cases that will look much better due to less normal map bending letting UDK fill in those values is fine.
  • cptSwing
    Offline / Send Message
    cptSwing polycounter lvl 11
    pet gripe (and OT).. "reimport static mesh" will not reimport edited normals. argh.
  • monster
    Offline / Send Message
    monster polycounter
    "Reimport Static Mesh" will use the options from the last time the Import Dialog was used. Unless you haven't opened that session, then it will use the editor default.

    I wish it remember the last used settings for that particular asset. Maybe it's supposed to, but it doesn't.
  • cptSwing
    Offline / Send Message
    cptSwing polycounter lvl 11
    Well, that's a start.. maybe I'll just import a dummy mesh each session. Cheers!
  • Fingus
    Offline / Send Message
    Fingus polycounter lvl 11
    Will giving the new imported mesh the same name as the old one overwrite it, or count as a reimport? I'm not at my workstation so I can't test.
  • passerby
    Offline / Send Message
    passerby polycounter lvl 12
    giveing it the same name will overwrite it? for models i dont use the re-import function at all since i find it too buggy and always just manaully import with the same name and let it over write.
  • blankslatejoe
    Offline / Send Message
    blankslatejoe polycounter lvl 19
    yep--give it the same name and itll overwrite it and let you set new flags and such. Be sure you account for the group too--that's part of the 'name' in UDK.

    this thread is awesome, btw
  • cptSwing
    Offline / Send Message
    cptSwing polycounter lvl 11
    So basically reexport the same mesh with the same name, and instead of "reimport ...", just go through the regular import process for new meshes and it'll popup the dialog? will meshes keep their position and all that in a UDK scene?
  • m4dcow
    Offline / Send Message
    m4dcow interpolator
    cptSwing wrote: »
    So basically reexport the same mesh with the same name, and instead of "reimport ...", just go through the regular import process for new meshes and it'll popup the dialog? will meshes keep their position and all that in a UDK scene?

    Just do like you are importing something completely new, select your mesh and name it the same as the one you want replaced, and all instances will be updated. As mentioned above, make sure you have the same group name too.
  • blankslatejoe
    Offline / Send Message
    blankslatejoe polycounter lvl 19
    Regarding position/orientation--any mesh 'nodes' in the scene will keep their position/rotation as you've placed them, however the meshes themselves will update to reflect any changes in scale, rotation, or placement you've made in maya/max. So, say you turn a model 90 degrees and reexport--everything will rotate in your scene, but the meshes will still be there.

    Oh, youll have to rebuild lighting/paths/etc and all that jazz, of course.
  • SimonT
    Offline / Send Message
    SimonT interpolator
    Awesome workaround. A shame that a workaround is needed for such a basic thing. Are we in 2013? Is UDK also in 2013?
  • cptSwing
    Offline / Send Message
    cptSwing polycounter lvl 11
    It works well enough and thankfully is a lot less clicks than deleting the mesh from the package and reimporting / repositioning. So thanks guys!
  • Accipiter
    Offline / Send Message
    Accipiter triangle
    Not to throw a monkey wrench into this whole thing, but it would seem turning "Explicit Normals" to true isn't an option if the object is a Skeletal Mesh.
    I think I might need to preform Fingus' workaround to make this work for Skeletal Meshes.
  • AlecMoody
    Offline / Send Message
    AlecMoody ngon master
    this doesn't happen with handplane..

    -slowly backs out of the thread
  • LaurentiuN
    Offline / Send Message
    LaurentiuN polycounter
    Hello, i`m trying this technique with mirrored uvs but is not wrk for me, when i select address X - mirror, the mirrored part is empty, without texture...

    I try`d to invert the mirrored UVS or normal UVS and nothing, the mirrored uv in max is outside 1-0 uvspace..
  • luthyn
    Offline / Send Message
    luthyn polycounter lvl 8
    Thanks for starting this thread Fingus, it's been really helpful!
  • kurt_hectic
  • sayoend
    Offline / Send Message
    sayoend polycounter lvl 4
    i tried 40+ different normal maps  for one model, all export import combinations.  at the and, i managed to get normal map work without seam, but i dont now what i did hahahah...
    all maps were 2k but the one that was working was about 600kb, while others were 7-8mb... can someone tell me what i did i do? :-) WHAAAAAT
    EDIT: it worked without any nodes, just texture applied
Sign In or Register to comment.