DEV Community

cutie
cutie

Posted on

You don't need look-at matrices for an FPS camera

If you have ever written an FPS camera, you have probably seen something like this:

vec3 forward = get_forward_vector(yaw, pitch);
vec3 target = position + forward;

mat4 view = look_at(position, target, world_up);
Enter fullscreen mode Exit fullscreen mode

It works, but it's really redundant and there's a way simpler way of doing an FPS camera properly.

Constructing a target just to pass it to look_at is unnecessary. The camera is already defined by its position and orientation, so constructing the basis vectors directly is just simpler.

look_at is actually for cases where you actually have a target. Maybe you're orbitting a planet, or tracking an object, whatever, THIS is what actually makes sense:

view = look_at(camera_position, player_position, world_up);
Enter fullscreen mode Exit fullscreen mode

Now you might ask, oh, Cutie, what's the proper way of doing an FPS camera?
First you want the forward direction

vec3 forward;
forward.x = cos(pitch) * cos(yaw);
forward.y = sin(pitch);
forward.z = cos(pitch) * sin(yaw);

forward = normalize(forward);
Enter fullscreen mode Exit fullscreen mode

Then, you want the camera basis:

vec3 right = normalize(cross(forward, world_up));
vec3 up = normalize(cross(right, forward));
Enter fullscreen mode Exit fullscreen mode

And now you have the directions to move and orient the camera:

position += forward * movement_forward;
position += right * movement_sideways;
Enter fullscreen mode Exit fullscreen mode

Then you can construct a view matrix from these axes, or construct a camera transform and invert it.

That's it. I hope it was useful.

Top comments (0)