How to blend World Space Normals

Started by
6 comments, last by fire67 8 years ago
Hey everyone,
I am trying to blend two world space normals inside a shader. One comes from a tangent space normal map converted into world space using a classic TBN matrix and the other one is a mesh normal map in world space.
I found some interesting resources here :
But those blending technics seem to be only available for tangent space normals, especially the Reoriented Normal Mapping (RNM).
I tried to apply the RNM technic with unpack already done.

n1 += vec3(0, 0, 1);
n2 *= vec3(-1, -1, 1);

return n1*dot(n1, n2)/n1.z - n2;

But this doesn't give expected results and I don't get why. Is there a way to apply the RNM blending on world space normals ?

Thanks a lot !
Advertisement
As long as both normals are in the same coordinate space, you should be able to use any blending technique. Do you have any screenshots for what is going wrong?
My current game project Platform RPG

Here are the outputs which are obtain using this, expect when outputing only the normals.


float3 nv = dot(normal, viewDir);
color.rgb = nv;

[attachment=31554:total.jpg]

Here is the RNM function I am using :


n1 += float3(0.0, 0.0, 1.0);
n2 *= float3(-1.0, -1.0, 1.0);

return n1 * dot(n1, n2) / n1.z - n2;

As you can see in the bottom screenshot, I would like like some kind of blending between both normal map and I don't really know what's happing but the A normals should be disturbed by the B normals or it seems to give another result.

From what i remember at least some of those blending functions assume Z to point upwards, means they work in tangentspace. So they blend normalmaps, not normals.

Also i don't get why you want to blend the mesh normal with a normalmap converted to worldspace via TBN since the TBN orients tangentspace-normalmaps to your mesh.
To me it looks like you get kind of double oriented normals.

I used the partial derivate function to add some additional detail, but i blended it in tangentspace and then converted the resulting normal to worldspace via TBN.

The sample implementation of RNM on that blog post assumes that the "s" vector is a unit z vector, which is the case for tangent-space normal maps. This is represented in equations 5/6/7. If you want to work in world-space, then you need to implement equation 4 as a function that takes s as an additional parameter:

float3 ReorientNormal(in float3 u, in float3 t, in float3 s)
{
    // Build the shortest-arc quaternion
    float4 q = float4(cross(s, t), dot(s, t) + 1) / sqrt(2 * (dot(s, t) + 1));
 
    // Rotate the normal
    return u * (q.w * q.w - dot(q.xyz, q.xyz)) + 2 * q.xyz * dot(q.xyz, u) + 2 * q.w * cross(q.xyz, u);
}

If you pass float3(0, 0, 1) as the "s" parameter, then you will get the same result as the pre-optimized version. However the compiler may not be able to optimize it as well as the hand-optimized code provided in the blog.

From what i remember at least some of those blending functions assume Z to point upwards, means they work in tangentspace. So they blend normalmaps, not normals.

Also i don't get why you want to blend the mesh normal with a normalmap converted to worldspace via TBN since the TBN orients tangentspace-normalmaps to your mesh.
To me it looks like you get kind of double oriented normals.

I used the partial derivate function to add some additional detail, but i blended it in tangentspace and then converted the resulting normal to worldspace via TBN.

Thanks for your answer @Ryokeen. In the original paper, they are baking the bent world normal into the vertex color.

Then they are using those bent vertex normals to calculate the TBN and calculate a bent version of the world normals using the normal map. Unfortunately, I am not able to use the vertex color that's why I am using a bent world normal texture to re-orientate the normals. :(

Thank you for the code @MJP !

I Understand what you mean concerning the z vector unit. But I think that I am missing something because I don't know which other vector should I use for this unit vector.

Another thing that I don't get is why (especially visible on the cheek) the normals are so much perturbed.

When outputting only world normals A and B (see previous screenshots) the value seems to be close to (x, y, 1) and when blending, no matter the classic RNM technic or yours (see screenshot below) the combined normals become black and closer to (0, 0, 0).

Why the values are changing so much ?

[attachment=31563:normal.jpg]

You'll want to use the vertex normal vector, since this is what determines the Z basis in your tangent frame.

Thank you very much @MJP this makes sens now !

This topic is closed to new replies.

Advertisement