Rotate mesh to normal

I have some instanced geometry (basic tube meshes) laid out in a grid, and I have a noise texture (normal map) that I want to use to rotate my instances with. So head pixel in my texture is a normal and I want to rotate each instance with the corresponding normal in a shader. How can I achieve that in a shader only? Unless I am mistaking, there should only be a rotation around the X and Z axes.

You can get a rotation matrix from a a direction ($$\\vec d\$$) and an up vector ($$\\vec u\$$) (direction is the normal here).

First you need to get 2 perpendicular vectors, one pointing to the right ($$\\vec r\$$) and one pointing up ($$\\vec t\$$) when looking in the direction of the normal vector.

You can get $$\\vec r\$$ by getting the cross product of $$\\vec d\$$ and $$\\vec u\$$:

$$\vec r = \vec d \times \vec u$$

Then you can get $$\\vec t\$$ by doing the same to $$\\vec r\$$ and $$\\vec d\$$:

$$\vec t = \vec r \times \vec d$$

The rotation matrix can be defined by these three vectors in the following way:

$$\begin{bmatrix} \vec r_x & \vec r_y & \vec r_z & 0 \\ \vec t_x & \vec t_y & \vec t_z & 0 \\ \vec d_x & \vec d_y & \vec d_z & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}$$

Use it as a model matrix

• Works perfectly, thanks! Could you provide a bit more of an explanation if you have time, it would be nice to understand how and why this works. – dotminic Jul 12 at 9:19
• @dotminic The three vectors define a coordinate system. If you take 3d rotation matrices for pitch (rotation around x) and yaw (rotation around y) and you multiply them together, the different parts of the matrix will be equal to the coordinates of those three vectors, e.g. the top-left value of the matrix will equal the x coordinate of the right vector. The up vector is needed, since the direction vector doesn't define a roll (rotation around z), so you can't really tell which direction "right" is – Bálint Jul 12 at 11:06
• This also means, that if you need a direction vector from a rotation matrix, you can just use the third row, which is pretty useful – Bálint Jul 12 at 11:08
• Ok now I get it, I had figured out that the first step was to build a basis but the matrix was a bit of a blur to me. Thanks for clearing that up. – dotminic Jul 12 at 11:34