Normal Map Baking with Geometry Nodes

Introduction

From time to time I like to do an exercise in geometry nodes to understand them a little bit better and to see what’s possible. This is such an excercise, it serves no real purpose, though who knows, with developments in geonodes I might go back to it some day.

In this blog post I will share with you an explanation of parts of the geonodes setup and how I achieved the final result.

Goal

We want to capture normals of high poly object (that’s easy) and translate those captured normals into tangent space so we can use them in the shader.

Steps we need to take:

  • capture high poly normals using raycast node
  • capture bitangent of each vertex of low poly mesh
  • rotate captured high poly normals using bitangent vector, thus translating object space normals into tangent space normals.

Capture high poly normals

To better illustrate the process I will be using the baking setup from Sphere collection.

With a raycast setup I’m capturing object space normals from high poly object that is plugged into target socket of raycast node.

Tangent Space

So now the question is: „How do we get from object space to tangent space?”

I will try to explain it in as simplistic way as I can.

Shader needs to know what is the difference between low poly normal and captured high poly normal.

For normals to be comparable they need to be in the same space, otherwise there’s no point of reference.

For low poly normals we will rotate them so they will be all facing upwards in Z-axis and we will also align bitangent to Y-axis so the space is precisely oriented and isn’t rotated randomly in Z-axis. In such a way we get the characteristic blueish/pinkish color, which is neutral for normals.

Next we will apply exactly the same rotation to the captured high poly normals. In such way we translate object space normals into tangent space.

Finally we also multiply all normals by 0.5 and add 0.5 to squeeze their values into range 0-1 so they can be represented by colors in the final texture.

Calculating Bitangent

Allright, but as you can see in the geonodes setup above we need Bitangent to align Y rotation. So here is a bit of schematic explanation.

Tangent is a direction in X-axis in UV space, that is translated into 3D space.

Bitangent is vector perpendicular to normal and tangent: in math terms it’s cross product of these two vectors.

So how do we find tangent using geometry nodes?

Well first we need to translate our low poly object to UV space.

Below is the setup for finding UV seams. It selects edges where information about UVs is different between points and faces corners .

Now that we are in the UV space we will create a tangent vector.

We can store vector per vertex by subtracting position of the nearest connected vertex from current vertex position.

Next we need to find the angle by which we need to rotate it by Z-axis (normal) so it becomes tangent in UV space.

Once we have stored the angle that will change vector created by subtracting nearest vertices positions into tangent, we can translate our low poly from UV space to 3D space. 

Now we will once again subtract nearest vertices positions, this time in 3D space, and we can rotate this vector by the stored angle turning this vector into tangent* in 3D space.

*well an approximation of tangent, we’d need a bit more of math to make sure it’s perpendicular to normal, that’s why we’ll use cross product and bitangent to make geonodes setup simpler.

So finally result of cross product of normal and tangent translated into 3D will be our bitangent

Once again you can see below where bitangent comes into use to rotate captured high poly normals into tangent space.

Finally we need to store those tangent space normals as attribute in geometry nodes so we can use it in our shader setup.

Final result

DISCLAIMER

Two important footnotes:

I am not a mathematics professor, most of the stuff I do, is done intuitively using my knowledge of 3D rather than in depth understanding of math, so you should trust me like 90%.

Other important note, if you dig such content and perhaps would like to get some of my tools for educational purposes, I need to warn you, that they’re made with final working product in mind. The geonode setups running them aren’t ordered or named or described for educational purposes, so I wouldn’t like to dissapoint you like that. I might do a special course on how to make such tools, but for now they’re straight up for artists use.