0
\$\begingroup\$

While rendering a cube to the gbuffer (diffuse, normal, depth) I noticed something odd when applying rotations. I build a world matrix for the cube as follows:

Yaw = Yaw % MathUtil.PI2;
Pitch = Pitch % MathUtil.PI2;
Roll = Roll % MathUtil.PI2;

Matrix4 s = Matrix4.Scale(Scale);
Matrix4 t = Matrix4.CreateTranslation(Position);

Matrix4 rotY = Matrix4.CreateRotationY(Yaw);
Matrix4 rotX = Matrix4.CreateRotationX(Pitch);
Matrix4 rotZ = Matrix4.CreateRotationZ(Roll);

return s * rotY * rotX * rotZ * t;

If I render the cube with scale 1, position 0,0,0 and no rotations my normals are rendered properly. Applying scale/position does not change this fact.

Normals with no transformation

However, when I apply rotations the normals screw up in some cases.

Nothing wrong in these settings:

  • Yaw = Pi/2
  • Yaw = Pi
  • Pitch = Pi/2
  • Pitch = Pi
  • Yaw = Pi && Pitch = Pi

But when I apply these rotations:

  • Yaw = Pi/2 && Pitch = Pi/2

This happens:

Normals with transformation Yaw = Pi/2 && Pitch = Pi/2

For some reason the normals aren't rotated correctly. I rotate them like this in the vertex shader using the world matrix described above:

mat3 WorldMatrix3x3 = mat3(WorldMatrix);
normalWS = vertexNormal_modelspace * WorldMatrix3x3;

And store them in the fragment shader:

rtt_normal.xyz = normalWS * 0.5 + 0.5;

I display the normal buffer on the screen like this:

color = vec4(abs(texture(gbufferTexture, UV).rgb * 2.0 - 1.0), 1);

What am I missing here?

\$\endgroup\$
1
\$\begingroup\$

PI/2 is the magic number that causes gimbal lock. A Euler rotation of that value will disrupt subsequent rotations about another axis, because they have overlain each other. You need to replace

Matrix4 rotY = Matrix4.CreateRotationY(Yaw);
Matrix4 rotX = Matrix4.CreateRotationX(Pitch);
Matrix4 rotZ = Matrix4.CreateRotationZ(Roll);
return s * rotY * rotX * rotZ * t;

With something that doesn't suffer from the same problem.

Matrix4 rot = Matrix4.CreateFromAxisAngle(axis, angle)
return s * rot * t;
\$\endgroup\$

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.