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.

enter image description here

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

| improve this answer | |
  • \$\begingroup\$ 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. \$\endgroup\$ – dotminic Jul 12 '19 at 9:19
  • \$\begingroup\$ @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 \$\endgroup\$ – Bálint Jul 12 '19 at 11:06
  • \$\begingroup\$ 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 \$\endgroup\$ – Bálint Jul 12 '19 at 11:08
  • \$\begingroup\$ 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. \$\endgroup\$ – dotminic Jul 12 '19 at 11:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.