# Tangent spaced Normal Map seam visible in uv border area

## Recommended Posts

Drongle McMahon wrote:

With no map, there is no seam. With the blank map, there is a seam. So it's something happening with any UV map. The effect of the blank map can't have anything to do with tangent basis etc. Since there is no seam with no normal map, it's not to do with the basic rendering in ALM. So it must be happening in the code that applies the normal  map. My blank is <128,128,255>. It might be interesting to try slightly different colours.

As far as I know, a blank map would be <127,127,255>. Any other color will bend the normal relative to the current tangent basis.

##### Share on other sites

That's the way to counterfight missmatching tangent spaces. Hard edges/supporting edgeloops. With a synced bake the shading of a smoothed cube will look perfectly fine, even with the large gradients on the flat surfaces. And it won't increase the vertex count, by making all these edges hard.

Anyhow, since not everybody in SL has ALM on, an entirely smooth shaded hard surface object will look like a piece of garbage without it's normal map. So it's best to make these egdes hard anyway.

##### Share on other sites

Masami Kuramoto wrote:

As far as I know, a blank map would be <127,127,255>. Any other color will bend the normal relative to the current tangent basis.

Normal map neutral color is kind of a tricky thing. Actually the correct answer would be <127.5 127.5 255> but as we know this number cannot be expressed easily in 24 bit space.

This comes more obvious if we think the baking process. The normal map consists of 3 vectors. Each vector can have a value between -1 and 1 so the range is [-1,1]. Way to think it practically: For example blue channel contains the normal vector. Face normal can point to any direction from totally backface to totally frontface..so it can make 180 degree turn from back to front. So, this vector has a value between -1 and 1 in vector math.

(Just for fun: Sometimes take one of your normal maps in photoshop, select blue channel, press ctrl-I, save file and render it inworld. You will get a spooky ghost like effect. If you set your environment so that the sun is behind your object...the front side of the object is lit )

Well, 24 bit RGB file does not have negative values. To get things work the baker software pushes -1...1 ranged values into 0...1 range. This 0...1 range can be expressed using 8 bit number between 0...255. During this process some data is lost. As you can see -1...1 range has twice as much space as 0...1 range.

An example: Original vector is [-0.2, 0.5, 0.1] ==> Packing into RGB would be this:

([-0.2, 0.5, 0.1] / 2 + [0.5, 0.5, 0.5]) * 255 = [102, 191.25, 140.25]. The stuff behind decimal point do not work => the baker rounds the number into 102, 191, 140

Neutral vector is [0,0,1]. After above math it looks like 127.5, 127.5, 255 => Rounded up to 128, 128, 255

Now lets look at this neutral 128,128,255 number in the shader point of view. The shader unpacks it from the file into more suitable -1...1 vector space. The math would look like this:

2 * ( [128,128,255]/255 ) - 1 ==> [0,004, 0.004, 1]. Yep, it is wrong but close enough to correct 0,0,1.

How about 127, 127, 255 value:

2 * ( [127,127,255]/255 ) - 1 ==> [-0.004, -0,004, 1] Yep, as much wrong as the previous value.

If we take the absolute correct 127.5, 127.5, 255 we get the correct vector [0,0,1]

So, in principle there is no difference if you use 127,127,255 or 128,128,255. Both are wrong but close enough and both of them should render looking about same.

Sidenote for picky people: The example vector [-0.2, 0,5, 0.1] above is not a correct normal map vector, because it is not normalized. I just didnt have time right now to go into normalizing vectors. Forgive me that - someone else can do it here if needed : ). The un-normalized vector does not affect the math itself.

• 1

##### Share on other sites

"It's also a result of baking to the wrong kind of geometry..."

I disagree. I deliberately chose this extreme case because the purpose was to obtain the maximum effect from the tangent basis mismatch, and thus the maximum improvement from changing it, because that ishat I was discussing. In real cases, the effects are much more subtle. It is true that a nicer result can often be obtained by using hard edges in the low poly (albeit at the cost of extra vertices because they get split). That is really beside the point here though.

##### Share on other sites

"As far as I know, a blank map would be <127,127,255>"

Ah. That seems to be right. I was assuming that my 128,128,255 was correct because it gives the identical result to LL's Blank normal map, but from the picture below, I think me and LL got it wrong. Interestingly, it appears that Blender uses <127,127,254>. At least that's what I get when baking a flat surface onto itself. So I added that as well.  The 127,127 ones are obviously much better, although you can still see a seam if you turn environmental reflection right up. (I think I'll have to delete my comment from the jira.)

##### Share on other sites

I was real hesitant to say it's a bug given all the hard work the Linden Lab programmers put into implementing Materials code, but after considering everything I've seen sofar it kinda seems like it is.

This kind of bug is madness inducing. LOL Foreal. :smileyvery-happy:

##### Share on other sites

Jake Koronikov wrote:

(Just for fun: Sometimes take one of your normal maps in photoshop, select blue channel, press ctrl-I, save file and render it inworld. You will get a spooky ghost like effect. If you set your environment so that the sun is behind your object...the front side of the object is lit
)

____________________________________________________________________________________________

That's interesting info. I heard that some renderers do not use blue channel at all. I wonder if we can exploit it to fake subsurface scattering.

##### Share on other sites

DerpWolf wrote:

Jake Koronikov wrote:

(Just for fun: Sometimes take one of your normal maps in photoshop, select blue channel, press ctrl-I, save file and render it inworld. You will get a spooky ghost like effect. If you set your environment so that the sun is behind your object...the front side of the object is lit
)

____________________________________________________________________________________________

That's interesting info. I heard that some renderers do not use blue channel at all. I wonder if we can exploit it to fake subsurface scattering.

Well yes, it is actually a sort of a subsurface scattering. I have never been thinking it that way, but you are right.

Tho I think the effect is quite strong, so I am not sure if it can be used that way. Another thing is that when I tested that blue channel flipping sometimes in SL, it caused black artifacts here and there - but I didnt test or tweak it any further. Was just a quick experiment.

(ETA: I just tested your subsurface scattering idea inworld. It looks like the black artifacts can be avoided by stabilizing the blue channel flip with some actions in red and green channel. But gotta play with it more, I didnt yet figure out the principle how SL handles that turned around face normal. Anyway, purely flipping the blue will cause some artifacts)

Yup, and some shaders do not use blue channel directly. They calculate the blue channel vector using the values from the green and the red. If the normal map is correctly baked so that resulting vector lenght is always 1, the third channel can be calculated using only two values.

##### Share on other sites

I also ran some tests today. In "standalone" mode the effect indeed won't be very convincing, I think. But if it is restricted by the local thickness map baked for particular mesh, it gets better.

In my test, I used two-layer mesh. The base layer is just a diffuse texture. The second layer is the same texture, but with thickness map used as opacity mask, plus inverted normal map (flat 128.128.0 square in my case). The screenshot shows the object with different lighting angles. Under front light the "scattered" areas look unnaturally dark, but I think it still can be used to simulate materials like ice or crystals.

##### Share on other sites

Jake Koronikov wrote:

Jira is now filed:

Regarding this old thread, and a Jira above:

Geenz Spad (from Exodus viewer project) wrote an interesting comment for this jira. I think it might be a good idea to share his knowledge here too - this explains what is happening inside SL (warning: the embedded link below containts mathematics, and may cause serious health issues for living organisms :matte-motes-silly:) :

"

What I suspect is happening here is how the viewer generates a special set of coordinates called tangents.

Tangents are required for normal mapping to function properly. What you're seeing here looks to me like the tangents your normal map was baked with aren't lining up with what the viewer is generating. This isn't surprising, as most 3D modeling packages have their own, often times proprietary, way of calculating tangents on a surface. The method that the viewer uses (or at least, what the viewer's implementation is based off of) can be found here: http://www.terathon.com/code/tangent.html

What this can result in is edge discontinuities like you're experiencing in SL. As for other applications like Toolbag, those applications actually import the tangents that were generated by the 3D package you exported from to ensure that normal maps all look correct when viewed within those applications.

Second Life does not do this for the sake of file size, and instead generates them on the fly for meshes and most other geometry.

You likely won't be seeing a fix for this any time soon, as it basically requires that the SL mesh format support tangents which it currently does not."