# Normals not rotated correctly

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. 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: 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?

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;