Home Technical Talk

3dsmax favors local-space normal maps?

polycounter lvl 19
Offline / Send Message
Joshua Stubbles polycounter lvl 19
After doing some tests the past few days, it seems that 3dsmax prefers to properly display local space normal maps over tangent space normal maps.
These two objects here have the exact same DirectX FX shader and grey diffuse texture. Notice how the local-space looks how it should.

error3es.jpg


Has anyone else here experienced the same issues? And if so, is there any way around it?

Replies

  • Kevin Albers
    Offline / Send Message
    Kevin Albers polycounter lvl 18
    My guess is that the smoothing groups on the lopoly model are flawed. The local space normal map probably bypasses the existing smoothing, so it looks better than the tangent space one. Are the smoothing groups on the model the same as when you baked out the normal map? I'm pretty sure they should be, to give correct results.
  • Joshua Stubbles
    Offline / Send Message
    Joshua Stubbles polycounter lvl 19
    The entire mesh had a single smoothing group both during and after the bake. I think that's pretty shitty if the local space is bypassing the smoothing, and giving me false visuals.
  • MoP
    Offline / Send Message
    MoP polycounter lvl 18
    IMHO the local space one is displaying the normals as the tangent-space one should... surely the viewport display should be purely based on the normal map, if the low-res mesh is all one smoothing group?
    It's just max being assy... if you generated/rendered in Doom3, it'd be fine. Just for some reason Max's tangent-space display likes to kinda overlay the lowpoly smoothing onto the normal-map smoothing, so it looks crap.
  • Eric Chadwick
    Looks to me like max isn't calculating nor using the tangents and bitangents, which are required for proper lighting with tangent space maps.

    The tangents and bitangents need to be calculated per-vertex from the UV coordinates of the model. Once they're created, they can be stored in an unused UV channel. Then the light vector can be transformed from world space into tangent space, and the surface will be lit correctly (most of the time... there are exceptions like the poles of a sphere, so I'm told).

    Here's some code if someone wants to whip up a proper Max plugin or script...
    http://www.terathon.com/code/tangent.html
    ...though you'd also have to have a viewport shader that'd be able to use the resulting vectors.
  • Joshua Stubbles
    Offline / Send Message
    Joshua Stubbles polycounter lvl 19
    Awesome. Thanks for looking into this, everyone. I knew I wasn't crazy! smile.gif
    Hopefully someone here is crafty with code/maxscript, and is willing to take this up.
  • Joshua Stubbles
    Offline / Send Message
    Joshua Stubbles polycounter lvl 19
    On a side note, the FX shader I used was "RTTNormalMap.fx".
    I'm clueless on this code stuff, though. If someone could make it support 3 lights, transparency, and specular, I'll have your baby laugh.giflaugh.gif
  • MoP
    Offline / Send Message
    MoP polycounter lvl 18
    Vassago, have you tried Ben Cloward's 3-light specular normal-map shader? I usually get a lot better results with that than Max's own shaders.
  • Joshua Stubbles
    Offline / Send Message
    Joshua Stubbles polycounter lvl 19
    Yea I have, but they don't seem to properly support world/local-space normal maps.
    And using his scripts, I still get f'd up shading like the above pic.
  • Ben Cloward
    Offline / Send Message
    Ben Cloward polycounter lvl 18
    I'm pretty sure I've found a work around to this issue. All of my shaders put the light vector and eye vector in tangent space in the vertex shader before passing them to the pixel shader. That should work, but for some reason Max doesn't like it and you end up with weird lighting artifacts. Recently I've done some tests with putting the vectors in world space instead and things work much better. The normal map is still a tangent space normal map, but the way the shader is handling it is different. Give me a couple of days and I'll post updates to all my shaders using this new method.

    On a related note - did you guys notice that they fixed the issue with Normal map seams at UV borders in Max 8? Yeah! Also, you can now mirror your UVs and the lighting is correct. Some nice normal mapping improvements in this version.
  • MoP
    Offline / Send Message
    MoP polycounter lvl 18
    Awesome, Ben. Can't wait for that shader - finally an *accurate* preview of normals!

    Am I right in thinking that Max's RTT renders the normal-maps perfectly correctly, just the display is screwy? Or is it linked in some way?

    Yeah, the Max8 fixes are good, seams and mirrored UV's are now handled very well, however those artifacts on objects with 90-degree angles (like Vassago's example here) still display nastily using the standard shaders.

    Great work, man, I really appreciate it, and I'm sure hundreds of other people do too! smile.gif
  • Joshua Stubbles
    Offline / Send Message
    Joshua Stubbles polycounter lvl 19
    That's great, Ben. Your scripts are extremely helpful to the community. I'm glad you're taking the time to fix these up for everyone.

    MoP - I think that Max does in fact render the maps correctly. I had a freind look at tangent normal map above in his engine, and it looked perfect. I figured that Discreet would have resolved this issue by now, but I guess no one has spoken to them about it :P

    Can't wait for those scripts, Ben! laugh.gif
  • Ben Cloward
    Offline / Send Message
    Ben Cloward polycounter lvl 18
    Don't get your hopes up too high yet, guys. I'm not sure if the changes I'm making will fix these issues or not. It's possible that the issues I was seeing (that will be fixed in my new versions) are different from the issues that Vassago is getting. I'll post up a quick test shader for you to take a look at and test in a couple of hours.
  • Ben Cloward
    Offline / Send Message
    Ben Cloward polycounter lvl 18
    Ok, try this normal map shader and see if it does any better. I'd be interested to see a side by side comparison like the one you've got at the top. I hope it works better. :0)

    http://www.monitorstudios.com/bcloward/test.fx
  • MoP
    Offline / Send Message
    MoP polycounter lvl 18
    Zing! Nice work, Ben. That seems to have done the trick.

    normal-fix.jpg

    As you can see, the Max default shader doesn't even load a texture larger than 512x512, resulting in horrible blurring. Also, the normals along sharp angle changes are screwed with the vertex shading.

    Your older shader works a whole lot better, but there are a few areas where it's noticeable that the vertex shading is darkening areas inappropriately.

    The new test shader seems to work perfectly! Nice one! smile.gif
  • Joshua Stubbles
    Offline / Send Message
    Joshua Stubbles polycounter lvl 19
    I'll post a comparison in a minute, but this didn't fix my issues at all frown.gif
  • MoP
    Offline / Send Message
    MoP polycounter lvl 18
    Hmm, I just tried it on some other objects (sorry, no screenshots, NDA!), and the smoothing, although mostly better, is still a bit screwed due to vertex shading in some places, mostly where there are long triangles bordering 90-degree turns in the low-poly mesh.

    It does seem to be an improvement, though, as shown on my screenshot before, a few obvious vertex shading artifacts were removed completely, and nothing got noticeably worse, only better.

    Also, if you keep developing this, is there any chance to have a checkbox or drop-down menu to choose which way the X- and Y-axis shading is being calculated? Your old shader and your new shader require the Y-axis (green channel) to be flipped between them. An option to choose that would be hugely beneficial (since there are also game engines which use different methods, and not having to manually invert a channel in Photoshop would save time).

    Thanks again, great work! Hope you get something resolved...
  • Joshua Stubbles
    Offline / Send Message
    Joshua Stubbles polycounter lvl 19
    Here's my comparison shot. Although there is some improvement, there's still a lot of shading issues going on.

    max6sm.jpg
  • Ben Cloward
    Offline / Send Message
    Ben Cloward polycounter lvl 18
    Thanks for the comparison images, guys. That's really helpful - and cool looking models too!

    Adding a check box to choose which way the channels should go is very easy. Yes, I will add that to all my shaders. It's a handy feature - especially for a shader that's being used by several different companies.

    Solving the sharp angle & long edge issue is going to be a lot harder. The reason that the local space normal map looks so much nicer is that that type of map doesn't use the vertex normals from the low poly model at all. It only uses the data in the map. The problem with a tangent space normal map is that the data in the map is recorded as an offset from the low poly normal instead of a normal that can stand on its own. Generally just using an offset is ok, but in extreme cases like sharp angles, the vertex normals of the low poly model are going out diagonally from the surface and don't match what the actual surface normals should be at all. That means that the tangant space normal map is really fighting against the screwy normals of the model to bring them back into an orientation that's more reasonable. Somewhere along the line - either when the normal map was generated, or when the lighting is calculated, something is not being done quite right. I don't know what it is.

    I know that in the case of this particular model, you can get better results by making seperate smoothing groups for the polygons on the back side of the fountain and also the bottom. That might help. You could also add one more edge loop around the middle that cuts the shading problems in half. This would give you some vertex normals that were a little less extreme. Re-generate the normal map once you've made these changes and see if that helps.

    You might also try generating your normal map in ATi's NormalMapper or with ORB to see if you get any better results from those.

    The real strength of a tangant space map is that it is deformable - so you can use it on a skinned character. You can't do that with a local space map. In the case of this fountain, maybe you're just better off using a local space map since it will never deform? :0)
  • Joshua Stubbles
    Offline / Send Message
    Joshua Stubbles polycounter lvl 19
    This is confusing smile.gif
    I don't see why tangent space normal maps work that way, then. The whole purpose of a normal map is a have the lighting of the high res mesh. How can this happen when it's calulating the low res smoothing on top of it? I thought that it should be behaving just like the localspace map is, in max. grr...

    As far as the smoothing goes, that's not a solution. It's going to break the smooth edges of the mesh corners, which completely negates the benefits of the normal map. I don't want hard creases on the edges of the mesh...

    I'll have to try hacking the mesh up and re-baking the normals. If I do in fact have to use local-space normal maps, do the same principles apply when overlaying detail in photoshop? I mean, they're completely differant in color, so I don't know if it's the same process or not.

    Any help would be great..

    **edit
    I forgot to say, that I sent this in to a freind, and they tested it in their engine. This is the same tangent space normal map that I used in the above viewport shader tests:

    sexi4gq.jpg


    The problem still seems directly linked to Max's inability to properly display tangent-space normal maps in the viewport.
  • Eric Chadwick
    [ QUOTE ]
    How can this happen when it's calulating the low res smoothing on top of it? I thought that it should be behaving just like the localspace map is, in max.

    [/ QUOTE ]
    The different methods work differently. smile.gif

    World-space and local-space (or object-space, same thing) use the same style of normal map, normals are encoded with world-space values.

    World-space: The shader takes the vector of the incoming light and compares that with the per-pixel normals from the map, then lights the surface. Mesh cannot be rotated differently than the original normal-map-baking orientation, or the lighting breaks down. But world- is the cheapest method, shader-instruction wise.

    Local-space: Same as world, except the mesh object can be rotated away from the original bake orientation. This rotation is simply added into the shader's duties, transforming the light vector into the local orientation of the mesh. A little more processing that world- but not by much.

    Tangent-space uses a different style, as Ben said the normals are encoded in reference to the vertex normals of the mesh. So now the mesh can not only be rotated but also deformed (skinned characters). The shader has to do a bit more work with tangent maps than either world- or local-, because it has to transform the light vectors from world space into the tangent space for each vertex, and henceforth onto each texel (pixel on the mesh).

    [ QUOTE ]
    If I do in fact have to use local-space normal maps, do the same principles apply when overlaying detail in photoshop?

    [/ QUOTE ]The "standard" overlay method works for tangent-space maps, but not really for world- or local- maps (world- and local- use same map). World-space maps need an overlay that's actually colored in world-space itself, not an easy task. There are ways however, like using a special lighting setup to bake a grayscale bump map into world-space, which you could then overlay (or somehow) add to your existing map. Never tried this myself.

    [ QUOTE ]
    I sent this in to a freind, and they tested it in their engine. This is the same tangent space normal map that I used in the above viewport shader tests:

    [/ QUOTE ]Looks good! The game exporter is generating the proper tangents and bitangents, so the lighting rocks.


    It took me a bit to learn all this, from Ben and others, so I might as well share. Good luck Vassago, I know it can be confusing. It certainly was for me.
  • MoP
    Offline / Send Message
    MoP polycounter lvl 18
    Thanks for the info Eric and Ben.
    Vassago: I'm wondering if the engine your friend tested that in, is an OpenGL or DirectX graphics engine? Do you know?
    If it's DirectX, then what could it be that's causing Max's hardware renderer to screw up the display, if it's possible to have a perfectly working tangent-space normal map in a different hardware renderer using the same SDK?

    Could it be that it's an inherent Max fault, and that no amount of HLSL shader coding will be able to get around it?

    I hope that's not the case, but if it is, then... well, damn!
  • Joshua Stubbles
    Offline / Send Message
    Joshua Stubbles polycounter lvl 19
    MoP - he just told me it's DirectX based.
    It's got to be a problem with 3dsmax itself. Like Eric said, the tangents and bit tangents needs to be recalulated upon export/viewing.

    It's very unfortuneate though, since I now have no way to accurately look at my work. It's probably going to be quite some time still, until our new engine supports normal mapping.
  • Eric Chadwick
    Doesn't matter whether it's Direct3D or OpenGL, it's an issue of Max not creating the tangents and bitangents, or even if it does (which I doubt) then it isn't using them in the shader.

    It wouldn't be hard for someone to write a little utility that calculated those, then stored them in a modifier or somesuch, then write a shader that would take advantage of that data. Coders do it all the time for game engines, and Max's viewport is essentially a mini game engine.

    But I'm not a coder... smile.gif
  • MoP
    Offline / Send Message
    MoP polycounter lvl 18
    Calling all coders! smile.gif
  • Joshua Stubbles
    Offline / Send Message
    Joshua Stubbles polycounter lvl 19
    I agree - it would be a monumental aid to the entire community, if someone would do this. Seeing as how Autodesk seems too lazy to fix it, this seems like the only solution.
  • Eric Chadwick
    I wouldn't go so far as to say they're lazy. I think that's just frsutration doing the talking.

    It's probably a simple matter of priorities. They are on a cyclical dev cycle after all, and features must be prioritized.
  • Joshua Stubbles
    Offline / Send Message
    Joshua Stubbles polycounter lvl 19
    Well, seeing as how it's taken them around 6-7 years to add a UVbitmap exporter, I don't think 'lazy' is a harsh term.
    Though frustration is certainly exaggerating my anger smile.gif
    With the whole normal mapping thing taking over, I just would have thought that by now, there would be a standard set of tools out there for people to use. Not to mention function properly.
  • Eric Chadwick
    Texporter is free and has been around for a long time, plus there's Grant Adam's fine PSDPathExporter. I'm not a marketing guy for Autodesk, but third-party devs have been a major part of the appeal of 3ds since the DOS days. Savvy way to get more tools, if you ask me. If functionality isn't up to par, Autodesk attempts to merge/update the tool into the shipping app. Not always successfully, but works for the most part.

    Sure some tools have been late in coming, or not at all, but that's true of every 3d package out there. When you're on the cutting edge, it hurts some times. wink.gif Don't get me started on the DVR I just bought, whew what a pain in the ass.
  • Ben Cloward
    Offline / Send Message
    Ben Cloward polycounter lvl 18
    Vassago, it looks like you've got a pretty good case here to submit as a bug. The guys at Autodesk are pretty good at fixing things that people complain about. Normal Mapping seems and mirrored UVs are a good example of this. If you don't tell them there is a problem, it's much less likely that they'll fix it. Here are some suggestions of what to include in the bug that you submit:

    - Side-by-side comparisons of what your model looks like using lots of different normal map display methods - as many as you can think of - kinda like the image that MoP made above. You might also include what the model looks like when you render it. Be sure to mark the spots on the image where the lighting problems are so it's very obvious.

    - Include your max file with all of the maps required so that they can reproduce the bug.

    - In the material editor of the file set up several materials, each with a different method of displaying the normal map and include instructions on how to recreate the problem and view the model with each different material/shader.

    - Be as clear as you can and especially emphasize the fact that the model looks perfect in an external game engine and also in Max's scanline renderer.

    - Include a link in your bug submission to this forum thread so they can come and get more details if they need them.

    I'd really like to hear a reply from Autodesk on this one! If they do fix it (they really need to) then you can feel all cool since you helped make the software better!
  • Joshua Stubbles
    Offline / Send Message
    Joshua Stubbles polycounter lvl 19
    Autodesk refuses to return my emails, it seems. I've sent them multiple emails via the 'customer feedback' section, but I've yet to recieve any replies. Unfortuneatly, they don't have a tech support email, and this is impossible to explain over the phone.

    I've gotten onto their tech support forum, but they have an attachment size limit of 200kb.....
  • Eric Chadwick
    They don't return emails immediately, AFAIK. In fact they may not respond to a bug report at all, unless they need more details. I think that's their modus operandi.

    I've had no response before. I've just accepted that the message was probably passed on to the suitable folks, or stuck into the queue.

    If attachment size is an issue, why not host the files yourself? If you don't have a site, free upload services abound.

    But it is all worth it, IMO. Good software depends on user feedback.
  • Michaelson Britt
    Offline / Send Message
    Michaelson Britt polycounter lvl 17
    Hello,
    We're aware of the issue but still seeking the file in question. We need both the low and high-res objects in .max files, and we also need the generated normal map to verify the problem. Information about your graphics card and driver can be helpful too.

    For general suport issues, please use http://support.discreet.com/webboard/wbpx.dll/%7E3dsmax
    To log individual bugs, don't be shy, please use http://usa.autodesk.com/adsk/servlet/item?siteID=123112&id=5600504&linkID=5573345

    I'd like reiterate everything Ben Cloward said in his previous post about bug logging. We do take this seriously and I cannot overstate the importance of logging a clear, methodical, comprehensive bug report. Although an issue may seem of paramount importance to an individual user, we do a lot of prioritizing since we guggle several market segments.

    Regarding the tangents and binormals; yes of course Max calculates these for both rendering and viewport display. If the viewport used some kind of technique that did not rely on tangents/binormals, it would be mathematically nonsense and would look much much worse to the user. The tangents/binormals are not stored in a mapping channel, and after all they would change every frame if the object is deforming. So they're stored only in the vertex buffer. The problem with tangents is that there are many ways to calculate them, and problems often arise when maps are encoded and decoded with techniques that don't match. In Max 7, the RTTNormalMap.fx probably had an issue here, but I'm thinking it's fixed in Max8. Which version are you using?

    Also, I fully agree that you should always use Local Space maps for objects that are not deforming. However, touching these up in Photoshop can be almost impossible, so you might stick with Tangent if Photoshop'ing is a must.

    Cheers,
    Michaelson Britt
    Software Developer
    Autodesk Media & Entertainment
  • Joshua Stubbles
    Offline / Send Message
    Joshua Stubbles polycounter lvl 19
    I sent the file off a while ago, but I think our mail server is slow right now.
    I'm using the Max8 Demo, for all of the above tests. This includes modeling, baking, viewing and rendering.
    About the tangents - since everyone here is having the same issues, would it be safe to say that Max is handling them wrong? I know there are multiple ways to calculate them, but if they show up correct in nearly every game engine, why couldn't they show up correct in the viewport?

    Thanks again for the reply, and for posting the information here for the community. smile.gif
  • darkshadow
    Offline / Send Message
    darkshadow polycounter lvl 18
    this question might be a bit of topic, but what kind of lighting do you guys use when baking normal maps, using max7
  • Joshua Stubbles
    Offline / Send Message
    Joshua Stubbles polycounter lvl 19
    There shouldn't be any lights in the scene when baking normal maps. At least, I've never put any there. To be honest though, I don't think they affect the normal map render anyways. They'll certainly change things if you're baking a lighting/complete map, stuff like that.
  • darkshadow
    Offline / Send Message
    darkshadow polycounter lvl 18
    aight man thx alot, so i just should set the viewport on default lighting and 1 light?
  • MoP
    Offline / Send Message
    MoP polycounter lvl 18
    It doesn't matter what your lighting is set to if you're just rendering a single normal-map.

    The lighting will only matter if you're rendering a complete map including diffuse and shadows and stuff... just the RGB normal map is not affected by any lighting.

    I'd use a Skylight with advanced lighting turned on to get good ambient lighting from a high-poly object if I was baking all the textures. However, if you're not rendering out lighting, don't use the Skylight because it will slow down the render-to-texture process needlessly.

    That maybe made sense...?
  • darkshadow
    Offline / Send Message
    darkshadow polycounter lvl 18
    yeah ty alot man
  • Eric Chadwick
    Nice to get feedback directly from the developers themselves, thanks Michaelson for your time.

    Does RTT store the tangent/bitangent data when it creates a normal map? I can't find any options to turn it on, at least in Max 7. It seems to me both the scanline dlm and viewport fx shaders would need to access that data for it to be useful.

    I think it would also be helpful if the RTT data was easily exportable via an SDK pointer, so it could go out with the rest of the game data. Might help to make it a part of the helpful Game Export Interface example code.

    Thanks again.
  • DDS
    Offline / Send Message
    DDS polycounter lvl 17
    EDIT: It was the inverted green channel, :P

    I wonder if it's related to this topic. Look at this. Same model, 1 smoothing group both models, Max Render to texture Vs Melody. May I be doing something wrong with max normalmapper? I don't see any button that says "create beautiful normal map"

    Thanks all.

    http://membres.lycos.fr/dreamdesigner/coses/maxmelody.JPG
  • pior
    Offline / Send Message
    pior grand marshal polycounter
    Hmmm looks like an inverted green channel issue... ain't it?
  • MoP
    Offline / Send Message
    MoP polycounter lvl 18
    DDS: Are those both shown in the Max viewport, or is the right-hand one a screengrab from Melody?
  • DDS
    Offline / Send Message
    DDS polycounter lvl 17
    OOops, yes pior u're right, it was the inverted green channel. So weird. Thanks smile.gif

    (Mop, it was 3dsmax viewport smile.gif)
  • MoP
    Offline / Send Message
    MoP polycounter lvl 18
    Ahh, right. Yeah, it would have been the flipped Green channel then. I was just wondering how different the results would seem if you used a 3dsmax-rendered normalmap to display in Melody, or if you used a Melody-rendered normalmap to display in Max.
    But since those were both displayed in Max, it doesn't matter, and I guess you've fixed it now anyway smile.gif
Sign In or Register to comment.