If you take a look at the code:
template<typename T, qualifier Q>
GLM_FUNC_QUALIFIER mat<4, 4, T, Q> lookAtLH(vec<3, T, Q> const& eye, vec<3, T, Q> const& center, vec<3, T, Q> const& up)
{
vec<3, T, Q> const f(normalize(center - eye));
vec<3, T, Q> const s(normalize(cross(up, f)));
vec<3, T, Q> const u(cross(f, s));
mat<4, 4, T, Q> Result(1);
Result[0][0] = s.x;
Result[1][0] = s.y;
Result[2][0] = s.z;
Result[0][1] = u.x;
Result[1][1] = u.y;
Result[2][1] = u.z;
Result[0][2] = f.x;
Result[1][2] = f.y;
Result[2][2] = f.z;
Result[3][0] = -dot(s, eye);
Result[3][1] = -dot(u, eye);
Result[3][2] = -dot(f, eye);
return Result;
}
glm calculates the direction vector f by subtracting the eye (for example camera position) from something that is called the center.
So if for example, you have a camera with camPos and camFront (camera position and direction) then you call glm::lookat like this:
glm::lookat(camPos, camPos - camFront, worldUp)
and then glm calculates the f direction like this:
f = center-eye = camPos - camFront - camPos = -camFront
So it basically ends up looking at the camFront (negated). But why does it have to do this calculation? Why can't just take the camFront directly instead of that center? It does an unnecessary calculation…