Sign in to follow this  
Jake Koronikov

Tangent spaced Normal Map seam visible in uv border area

Recommended Posts

I have been fighting with this normal map issue for a long time. The problem is visible seam or discontinuity in UV island border. This issue is not visible when normal map is standard (+x +y +z) but when dealing with
SL normal maps (+x -y +z, green channel flipped) this comes visible.

I have been trying normal map bake (+x -y +z) in XNormal, ZBrush and Blender, all of those produce the same problem. Blender generates only standard normal maps but after flipping the green channel in Photoshop the seams come visible.

To make normal map work correct in SL, the green channel has to be flipped. Otherwise lights from up or down will reflect wrong.

[ ETA: "Just marked red some of my totally wrong opinions, SL uses x+ y+ z+ normal map. Do not follow my advice above:) ]

The question: What is this all about and is there a way to bake correctly -y swizzled normal map for SL?

The mesh is
- smooth shaded low poly
- normal map (+x, -y, +z) baked from smooth shaded high poly
- uv map has no overlapping verteces
- mesh has no double verteces or split edges
- edge padding (bake margin in Blender terminology) is 6 pixels


Some images make it more clear. This is a side view from a human shaped character upper leg:

 

Normal Map viewed as diffuse texture:

1.png

 

 Mesh in Blender viewport with normal map used as tangent spaced normal map (seam comes actually visible):

 

2.PNG

 

Normal Map itself, arrows point to UV border:

 

3.PNG

 

And the visible seam inworld SL, no diffuse texture, just white object with normal map applied to the material:

 

4.PNG¨¨

 

 

Am I the only one who has had this issue ;D ?

Share this post


Link to post
Share on other sites

I have been fighting with this normal map issue for a long time. The problem is visible seam or discontinuity in UV island border. This issue is not visible when normal map is standard (+x +y +z) but when dealing with
SL normal maps (+x -y +z, green channel flipped) this comes visible.

I have been trying normal map bake (+x -y +z) in XNormal, ZBrush and Blender, all of those produce the same problem. Blender generates only standard normal maps but after flipping the green channel in Photoshop the seams come visible.

To make normal map work correct in SL, the green channel has to be flipped. Otherwise lights from up or down will reflect wrong.

[ ETA: "Just marked red some of my totally wrong opinions, SL uses x+ y+ z+ normal map. Do not follow my advice above:) ]

The question: What is this all about and is there a way to bake correctly -y swizzled normal map for SL?

The mesh is
- smooth shaded low poly
- normal map (+x, -y, +z) baked from smooth shaded high poly
- uv map has no overlapping verteces
- mesh has no double verteces or split edges
- edge padding (bake margin in Blender terminology) is 6 pixels


Some images make it more clear. This is a side view from a human shaped character upper leg:

 

Normal Map viewed as diffuse texture:

1.png

 

 Mesh in Blender viewport with normal map used as tangent spaced normal map (seam comes actually visible):

 

2.PNG

 

Normal Map itself, arrows point to UV border:

 

3.PNG

 

And the visible seam inworld SL, no diffuse texture, just white object with normal map applied to the material:

 

4.PNG¨¨

 

 

Am I the only one who has had this issue ;D ?

Share this post


Link to post
Share on other sites

I can think of as a funky-solution for this problem:
1. Making selection around the edge of the UV-end
2. Filled the border selected with a neutral color high

blender.jpg

Share this post


Link to post
Share on other sites

Canobu's idea actually works as a funky, very fun and quick solution :P

Yeah, if I understood right you fix the seam area from both sides using neutral normal map color. About like blending neutral color gradually stronger when closing the border line.

I tried to do some more research on this swizzle -y normal bake, and I think there really is no way to bake these maps correctly. There has to be made some manual adjustment as Canobu suggests. Problems might arise if there is strong normal mapped geometry across the uv seams....

Share this post


Link to post
Share on other sites

"Second Life uses +x +y tangent space normal maps."

Yes. I second that. I just did a whole lot of experiments to re-convince myself. It's the same as Blender (2.6+), so that no channel inversion should be necessary. On the other hand, I have to invert the green in normal maps made with the GIMP normalmap pluigin; so I suppose that uses +x-y by default. I also noticed that rotating the normal map inworld messes the normals up completely, but rotating the UV map in the model, after baking, doesn't seem to. I have to try to get my head round that now.

Share this post


Link to post
Share on other sites

You are both absolutely right! The correct is x+ y+ z+, as you both said. It was my mistake, sorry!

And now I am getting closer to get rid of seams too.

 

Thanks guys :)

 

 

 

Share this post


Link to post
Share on other sites


Drongle McMahon wrote:

"Second Life uses +x +y tangent space normal maps."

Yes. I second that. I just did a whole lot of experiments to re-convince myself. It's the same as Blender (2.6+), so that no channel inversion should be necessary. On the other hand, I have to invert the green in normal maps made with the GIMP normalmap pluigin; so I suppose that uses +x-y by default. I also noticed that rotating the normal map inworld messes the normals up completely, but rotating the UV map in the model, after baking, doesn't seem to. I have to try to get my head round that now.

Well, then I feel stupid, because I've been telling people '-y' this whole time. Drongle, would you mind posting a pic of the normal map you used to test? I know that the normal maps I've brought into SL are in the correct tangent space, but by the sounds of it, Xnormal has been lying to me and they've been opposite what I thought.

 

Share this post


Link to post
Share on other sites

Certainly no more stupid than me. I wasn't at all sure till I retested it. Here's the (simplest) experiment. Bottom left is the Blender 3D view with the "high poly" mesh in edit mode, and the low poly (one quad) beneath it, looking from above in Y direction.  Above that is the normal map baked from the high to low poly (UV map project from view (bounds) from directly above). Top right is the view of the two meshes rendered in Blender, from a similar view, with a single light above left of the camera. Bottom right is the low poly mesh with that map applied in SL, midnight, single local light in the visible sphere. This is all with no channel inversions or rotating anything. So I think that comfirms SL and Blender are the same.

All the googled references I found said that Blender is (now) x+y+z+. So if that's right, I think that means SL is x+y+z+ too. I think I saw something saying that Blender object-space maps were x+y-z+, and there were suggestions that it should be changed to the same as the tangent space maps. So maybe that difference may be the source of some confusion. I don't find all this easy, so I just try to remember that it has to look like red light from the right and green light from the top. I assume that is x+y+, but I am ready to be corrected if it's wrong.

testuv3.png

 ETA: This is something thar seriously needs to be put in the wiki if and when we are certain.

Share this post


Link to post
Share on other sites

Yes, its +Y, I can confirm that. Also how and why I was wrong:

I do all my baking with xNormal, and usually one particular rendering method because its the fastest: The openRL map renderer. What I've discovered in the course of testing is that this renderer defaults to +Y, and ignores the coordinates I set in the options - which has been set to -y. With the default renderer, +Y is correct.

So basically, I was doing it right, just thought the coordinates I was using were reversed, so thanks for correcting me on that.

 

All that aside, of course, its got nothing to do with seams. Everything else I said was accurate :)


Edited because I went and tested it and have proved myself wrong again in the process. Shameface! Although I did learn a lesson about edge padding, so that's something :)

Share this post


Link to post
Share on other sites


Drongle McMahon wrote:

 ETA: This is something thar seriously needs to be put in the wiki if and when we are certain.

Well, it's in the wiki for quite some time. I'll quote the importend bit:

"Keep in mind these are OpenGL style normal maps, where bright green is up and bright red is right."

http://wiki.secondlife.com/wiki/Material_Data

 

Share this post


Link to post
Share on other sites


IvanBenjammin wrote:

All that aside, of course, its got nothing to do with seams. Everything else I said was accurate
:)

Well, actually you'll make it even worse making these edges hard, on such a shape. You only need UV splits where you have hard edges, but you don't need hard edges on UV splits.

Share this post


Link to post
Share on other sites

Oh yes, but an additional explicit "x+y+z+" would make it easier to relate that with the notation generally used elsewhere, I think. That's what I was looking for.

Share this post


Link to post
Share on other sites


arton Rotaru wrote:


IvanBenjammin wrote:

All that aside, of course, its got nothing to do with seams. Everything else I said was accurate
:)

Well, actually you'll make it even worse making these edges hard, on such a shape. You only need UV splits where you have hard edges, but you don't need hard edges on UV splits.

You're totally right. I was all set to prove you wrong, and proved myself wrong in the process! I edited my original posts so as not to pass on bad information - and replying to you so it doesn't look like I'm trying to cover it up and make myself look better :D

Share this post


Link to post
Share on other sites

IvanBenjammin wrote:

 I was all set to prove you wrong,

I expected that. :matte-motes-sunglasses-3: That's why I hadn't mentioned it at first. But as you came back to it another time, I couldn't resist. :matte-motes-wink-tongue:

However, thanks for your honest reply, much appreciated. :matte-motes-smile:

Share this post


Link to post
Share on other sites

Actually I made some more tests, and the results are even more confusing.... Let's mimic a model that represents smooth shaded organic object in SL. The hi poly is complex and low-poly is not a simple cylinder but more like..yeah..low-poly representation of original mesh. UV unwrap contains some small non-uniform sections. Some polygons are a bit too small, some a bit too large, and there are angles all around. That is probably the way complex organic UV maps are, almost perfect but still some little issues here and there, too small to be seen in final render engine tho. Here is a photo of hi-poly and low-poly in Blender:

1.png

 

As you can see there is a seam in LowPoly model. (Well of course, it is not well placed, in the middle of important geometry, but as an example here). Also the edge flow is not straight, there is some angles in LP edges. Would be just normal in real model too.


Here is a nice uv layout with Normal map:

 

4.png

There is a noticable stretch in UV map. On that angle area the polygons on both side of the seam are too large. This kind of error in uvmap is not good, but smaller stretches are just okey in big organic model.



The same uv map packed a bit different way, whitch is also okey when there is a lot of islands everywhere and you pack them to avoid empty areas in the final texture file.

3.png

 

But the result of these two uv-islands in SL is totally different. The nicely 90 degree angled uv islands look perfect. The rotated uv islands look horrible.

6.png

 

The weird thing is that according to my knowledge the uv island rotation should have no effect on tangent space UV map in the actual real-time shader. I tested this using XNormal 3d View, Blender GLSL shading, Maya...they all rendered this well. But SL does not.

 

Example of Blender and XNormal viewport with the rotated uv island normal map applied. No seams, looks perfect.

5.png

44.PNG

 

Has anyone got further knowledge about this?

 

Share this post


Link to post
Share on other sites

I am actually answering the previous post myself. I found out interesting issues regarding uv-seams, normal maps and shader engine.

Quote:

"

Tangent space normal maps use a special kind of vertex data called the tangent basis. This is similar to UV coordinates except it provides directionality across the surface, it forms a surface-relative coordinate system for the per-pixel normals stored in the normal map.

Light rays are in world space, but the normals stored in the normal map are in tangent space. When a normal-mapped model is being rendered, the light rays must be converted from world space into tangent space, using the tangent basis to get there. At that point the incoming light rays are compared against the directions of the normals in the normal map, and this determines how much each pixel of the mesh is going to be lit. Alternatively, instead of converting the light rays some shaders will convert the normals in the normal map from tangent space into world space. Then those world-space normals are compared against the light rays, and the model is lit appropriately. The method depends on who wrote the shader, but the end result is the same.

The UVs and the vertex normals on the low-res mesh directly influence the coloring of a tangent-space normal map when it is baked. Each tangent basis vertex is a combination of three things: the mesh vertex's normal (influenced by smoothing), the vertex's tangent (usually derived from the V texture coordinate), and the vertex's bitangent (derived in code, also called the binormal). These three vectors create an axis for each vertex, giving it a specific orientation in the tangent space. These axes are used to properly transform the incoming lighting from world space into tangent space, so your normal-mapped model will be lit correctly.

When you look at a tangent-space normal map for a character, you typically see different colors along the UV seams. This is because the UV shells are often oriented at different angles on the mesh, a necessary evil when translating the 3D mesh into 2D textures. The body might be mapped with a vertical shell, and the arm mapped with a horizontal one. This requires the normals in the normal map to be twisted for the different orientations of those UV shells. The UVs are twisted, so the normals must be twisted in order to compensate. The tangent basis helps reorient (twist) the lighting as it comes into the surface's local space, so the lighting will then look uniform across the normal mapped mesh.

When an artist tiles a tangent-space normal map across an arbitrary mesh, like a landscape, this tends to shade correctly because the mesh has a uniform direction in tangent space. If the mesh has discontinuous UV coordinates (UV seams), or the normal map has large directional gradients across it, the tangent space won't be uniform anymore so the surface will probably have shading seams."


Conclution after several tests:

To get baked normal map (at least baked by x-normal,blender or zbrush) work correctly across UV seams -> UV seams has to be aligned left-to-right and up-down, eg along the uv-axeses. This means about like tiling the uv-seams, as mentioned above in the last paragraph.

This kind of aligning ruins the whole UV map of more organic model. The only workaround I found was to make a temporary UV map with all seams aligned to the axeses and baking normal map to those uv islands.

Then I took the resulting normal map as a "diffuse texture" and baked it to the final uv-map. (In Blender you could think this as 'bake with bake mode textures', original normal map as texture, and coordinates UV mapped according to temporary UV)

ETA: Afterwards I noticed the final uv-islands require some additional flipping. Seems to be they have to be 90 degree angle compared to original ones, and mirrored...:D so ..umh...looks like not a suitable for everyday thingies...:)

 

 

 

Share this post


Link to post
Share on other sites


canobu Almodovar wrote:

I can think of as a funky-solution for this problem:

1. Making selection around the edge of the UV-end

2. Filled the border selected with a neutral color high

 

blender.jpg

The solution to UV seams is to use "Edge Padding". The color that was used to bleed out the UV Island colors in the above images is the base color that is supposed to fill the empty areas around UV Islands. Black or White, or other colors shouldn't be used as your background color. Baked out Normal Maps usually are baked out with Black in some cases but it needs to be changed to its correct background color.

The appropriate backround color for a Normal map is: 128, 128, 255 / #8080ff

This background color represents zero or no height.

The technique used to in these images would of been more effective if the Solidify filter by the Flaming Pear plugin for Photoshop was used. I don't recommend creating "Edge Padding" this way.

Baking edge padding from your Normal Map baking program does a more sophisticated and correct solution to edge padding.

Edge Padding needs to be bled out pixel by pixel not by a uniform color, hence why the above technique is not a solution.

 

 

Share this post


Link to post
Share on other sites


Drongle McMahon wrote:

Certainly no more stupid than me. I wasn't at all sure till I retested it. Here's the (simplest) experiment. Bottom left is the Blender 3D view with the "high poly" mesh in edit mode, and the low poly (one quad) beneath it, looking from above in Y direction.  Above that is the normal map baked from the high to low poly (UV map project from view (bounds) from directly above). Top right is the view of the two meshes rendered in Blender, from a similar view, with a single light above left of the camera. Bottom right is the low poly mesh with that map applied in SL, midnight, single local light in the visible sphere. This is all with no channel inversions or rotating anything. So I think that comfirms SL and Blender are the same.

All the googled references I found said that Blender is (now) x+y+z+. So if that's right, I think that means SL is x+y+z+ too. I think I saw something saying that Blender object-space maps were x+y-z+, and there were suggestions that it should be changed to the same as the tangent space maps. So maybe that difference may be the source of some confusion. I don't find all this easy, so I just try to remember that it has to look like red light from the right and green light from the top. I assume that is x+y+, but I am ready to be corrected if it's wrong.

testuv3.png

 ETA: This is something thar seriously needs to be put in the wiki if and when we are certain.

In this image Dronge is correct, it can be confusing thinking about x, y, z. As Drongle said here a good way to spot if your Normal Map is baked out correctly is red form the right and green form the top.

Share this post


Link to post
Share on other sites


Jake Koronikov wrote:

I am actually answering the previous post myself. I found out interesting issues regarding uv-seams, normal maps and shader engine.

Quote:

Conclution after several tests:

To get baked normal map (at least baked by x-normal,blender or zbrush) work correctly across UV seams -> UV seams has to be aligned left-to-right and up-down, eg along the uv-axeses. This means about like tiling the uv-seams, as mentioned above in the last paragraph.

This kind of aligning ruins the whole UV map of more organic model. The only workaround I found was to make a temporary UV map with all seams aligned to the axeses and baking normal map to those uv islands.

Then I took the resulting normal map as a "diffuse texture" and baked it to the final uv-map. (In Blender you could think this as 'bake with bake mode textures', original normal map as texture, and coordinates UV mapped according to temporary UV)

ETA: Afterwards I noticed the final uv-islands require some additional flipping. Seems to be they have to be 90 degree angle compared to original ones, and mirrored...
:D
so ..umh...looks like not a suitable for everyday thingies...
:)

 

 

 

Their is some misinformation in this conclusion.

UV Islands are not restricted to 90 degree angles in order to bake out a properly working Normal Map, if this where true Normal Maps would not have been widely accepted as they are now. Some models are gonna have irregular UV Islands with no real sense of what is 90 degrees or any other angle for that matter.

Baking a Normal Map as a "diffuse texture" to a different UV Layout is a messy hack that will never produce properly baked out Normal Maps. A Normal Map is unique to the UV Layout it was baked to, if you change your UV Layout you need to rebake you Normal Map.

Normal Maps are suitable for any kind of model, especially low-poly models.

Linden Lab went through a great deal of trouble to implement Normal Maps into Second Lifes rendering engine because they new the benefits of their use would give people the option of not having to resort to using extreme triangle numbers in daily uploaded geometry.The solution of Normal Maps was created over a decade ago and professional Artists and Game development houses haven't looked back since.

And finally their will not be a situation where the use of more triangles over the use of Normal Maps will be favored. CPU and Memory resources will always have better things to do than being used on an unnecessary amount of triangles.

Real time: Ambient OcclusionGlobal IlluminationSubsurface ScatteringLiquids, Cloth, Physics, Particle Effects,  Spatial 3d Audio, Post Prossecing Effects, Dynamic Lights and Shadows, AI, Ragdoll, Procedural Terrain Texture Generation (the list goes on and on) are all better suited for CPU and Memory resources than rendering more triangles. I still haven't researched the performance hit that comes from using the Oculs Rift but I imagine their is some, which is another example for better suited CPU and Memory.

Of course alot of these effects arent availible in Second Life but the Oculs Rift is, and dedicating CPU and Memory for the Oculs Rift and real time tracking, and tracking devices is alot better suited.

 

Share this post


Link to post
Share on other sites


Their is some misinformation in this conclusion.

UV Islands are not restricted to 90 degree angles in order to bake out a properly working Normal Map, if this where true Normal Maps would not have been widely accepted as they are now. 
Some models are gonna have irregular UV Islands with no real sense of what is 90 degrees of any other angle for that matter.

Baking a Normal Map as a "diffuse texture" to a different UV Layout is a messy hack that will never produce properly baked out Normal Maps. A Normal Map is unique to the UV Layout it was baked to, if you change your UV Layout you need to rebake you Normal Map.

Normal Maps are suitable for any kind of model, especially low-poly models.

That is true, there is some misinformation, because UV islands *should not be restricted to 90 angles*. However, in SL engine one cannot make Normal Maps work properly if the island borders are in some other angle than left-right or up-down....

As an example: If you have a human body uv map where upper body is unwrapped naturally up-down direction (neck up, waistline down) and lower body is for some reason unwrapped left-right direction (toes right side of uvmap and waistline on the left side of map)-> result is a bad seam between upper body and lower body when rendered in SL.

And this is the whole point. Why in other shaders the UV seams can be in any angle but not in SL shader engine.

This baking one uv into another uv is of course a bad hack. But it was the only way I could get rid of most of the ugly seams. And you are right, normal maps are uv layout specific. The map has to be baked and used with same uv layout. Otherwise the tangent space is broken.

I have been studying a lot about this UV island issue on other forums, and they admit that in some shaders there is issues (or bugs) that cause false rendering. But can this be interpreted as bug or as a feature in SL?

Share this post


Link to post
Share on other sites


Jake Koronikov wrote:


That is true, there is some misinformation, because UV islands *should not be restricted to 90 angles*. However, in SL engine one cannot make Normal Maps work properly if the island borders are in some other angle than left-right or up-down....

As an example: If you have a human body uv map where upper body is unwrapped naturally up-down direction (neck up, waistline down) and lower body is for some reason unwrapped left-right direction (toes right side of uvmap and waistline on the left side of map)-> result is a bad seam between upper body and lower body when rendered in SL.

And this is the whole point. Why in other shaders the UV seams can be in any angle but not in SL shader engine.

This baking one uv into another uv is of course a bad hack. But it was the only way I could get rid of most of the ugly seams. And you are right, normal maps are uv layout specific. The map has to be baked and used with same uv layout. Otherwise the tangent space is broken.

I have been studying a lot about this UV island issue on other forums, and they admit that in some shaders there is issues (or bugs) that cause false rendering. But can this be interpreted as bug or as a feature in SL?

I read alot of those same threads and posts giving me the sense that the Normal Maps I would bake would not work correctly. I have baked flawlessly working Normal Maps just recently. As long as the viewer code dosen't change, they should continue to keep working ok.

As I stated before Normal Maps are not dependent on UV Island shape or angle, UV seams are fixed by adding "Edge Padding" around the bake of your UV Islands. The tangent basis of Second Life and baking software is not significantly different because I have them working just right.

When you bake a diffuse texture to another UV Layout in Blender you also have the option of adding "Edge Padding". If you fixed you seam issue's this way its likely edge padding was added in the diffuse texture baking process doing the exact same thing baking out your Normal Map with edge padding would of done. Baking a Normal Map to another UV Layout using diffuse texture baking is like making a copy of a VHS tape losing fine detail.

Share this post


Link to post
Share on other sites

I will give you here a practical example.

- Mesh is low poly

- normal map baked from hi-poly,

- edge padding 8 px,

- normal map type OpenGL (x+ y+ z+),

- normal map file as 24 bit targa to avoid lossing of data. I made the normal map background black just to make it more visible up here in the forum.


First uv layout render in SL:

test2.png

UV layout and normal map of the model above:

test1.png

It looks like the angle between uv edges (separated by this uv border) affects the normal map seam in render.

 

Same model with different uv-layout. Note that normal maps are baked using this layout (not using the hack I described in earlier post)

Snapshot_004.png

In this render, the seam has disappeared totally.

 

And the uv-layout is now so, that the uv-border edges are aligned to same direction as uv-axeses. And also aligned to the same angle compared to eachother:

test3.png

 

So..what is happening here and why?

Share this post


Link to post
Share on other sites

It seems like all you need is to add some more edge padding. 

Here is one of my normal maps, I didn't worry about UV Island shape or angle. I added a good amount of edge padding, add a good clearly definable amount of padding. There are no UV seam issues with this Normal Map at all it works perfect. From my experience edge padding seems to stop when it meets itself so it dosen't seem to bleed onto the UV Islands themselves.

 

RVD_Padding.png

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
Sign in to follow this