I have been struggling to create a first person camera in OpenGL ES 2.0 without using gluLookAt(). I grab the camera's orientation vectors (the way it's looking) from the current modelview matrix, and use that to calculate the new forward/backward (Z) translation value. I then calculate the strafe (X) value from the dot product of Z and Y (which is always 1.0). So, I have all the information I need to create a view matrix, but how do I do that without using gluLookAt? Almost all the examples I've seen use gluLookAt, but no such function exists in OpenGL ES 2.0. Besides, one of the moderators on cprogramming.com mentioned that gluLookAt is not appropriate for FPS cameras:


I am really confused by all the conflicting information I'm getting. I just want to create a first person camera that goes forward (W,S keys), side-to-side (A,D keys) and rotates around its center (Y axis only), Wolfenstein style.

Here's more-or-less my existing code:

vec4 cur_look,dir_move,dir_strafe,cam_pos;
mat4 mat_modelview,mat_rot,mat_temp;
float lr; //left/right keypress increment value
float ud; //up/down keypress increment value

//grab current camera orientation (look at) from the modelview matrix
cur_look[0] = mat_modelview[8];
cur_look[1] = mat_modelview[9];
cur_look[2] = mat_modelview[10];
cur_look[3] = mat_modelview[11];

//rotate the direction vector using the rotation matrix
mat4_rotate_Y(mat_rot,mat_temp,lr); //create rotation matrix

//multiply the current direction vector by the rotation
//matrix and place the result in dir_move
mat4_mul_vec4(dir_move, mat_rot, cur_look);

//normalize the fwd/back direction vector

//calculate strafe vector using cross product of Z and Y

//normalize strafe vector

//detect key input

if(key_pressed == 'w'){
    cam_pos[2] += (dir_move[2] * -INPUT_SENS_Z); //z
if(key_pressed == 's'){
    cam_pos[2] += (dir_move[2] * INPUT_SENS_Z); //z

if(key_pressed == LEFT_ARROW){
    lr += INPUT_SENS_ROT;
if(key_pressed == RIGHT_ARROW){
    lr +=  -INPUT_SENS_ROT;

//build new modelview matrix

//multiply modelview matrix by rotation matrix

//create translation matrix
mat4_translate(mat_tran,-cam_pos[0], 0.0, -cam_pos[2]);
//multiple modelview matrix by translation matrix

//update uniforms and draw scene using glDrawArrays()
glUniformMatrix4fv(loc_modelview, 1, GL_FALSE, mat_modelview);

Any help on this would be much appreciated!


2 Answers 2


It seems like you are trying to do things backwards. Here is my preferred way of creating an FPS camera:

Store the position and orientation in client code (Euler Angles)

Define the position and orientations along the x, y, and z axis in the client code. This would would something like this in C++:

float camera_x = 0.0f;
float camera_y = 0.0f;
float camera_z = 0.0f;
float pitch = 0.0f; // The rotation along the x axis
float yaw = 0.0f; // The rotation along the y axis
float roll = 0.0f; // The rotation along the z axis

Then apply these variables before you render your objects in 3D space by writing:

glRotatef(pitch, 1.0f, 0.0f, 0.0f);
glRotatef(yaw, 0.0f, 1.0f, 0.0f);
glRotatef(roll, 0.0f, 0.0f, 1.0f);
glTranslatef(-x, -y, -z);

In the input handling code I make sure that the angles are never higher than 360 degrees or lower than 0 degrees to prevent precision loss, but this is up to you.

This method is unfortunately prone to the gimbal lock issue. I myself have never experienced this problem with FPS cameras, but you should be wary of it nonetheless. If you wish to avoid this problem, try quaternions. Be warned - they are notoriously difficult to understand.

  • \$\begingroup\$ This works except that the translation always goes in the same direction and is not affected by rotation. In other words, when I rotate the view 90 degrees to the left, the "forward" key actually goes "right." If I return the view to 0 degrees, "forward" goes "forward" as expected. \$\endgroup\$
    – Synthetix
    Commented Jul 10, 2012 at 9:32
  • \$\begingroup\$ This requires a basic knowledge of trigonometry. Check out khanacademy for some tutorials on that. \$\endgroup\$
    – Oskar
    Commented Jul 10, 2012 at 9:38
  • \$\begingroup\$ Should I be multiplying the translation vector (the -x,-y,-z in your example) by the same rotation matrix I used to derive the yaw value (I only ever rotate around the Y axis)? \$\endgroup\$
    – Synthetix
    Commented Jul 10, 2012 at 9:43
  • \$\begingroup\$ I haven't tried that myself, so I honestly don't know. I divided the yaw angles into four quadrants, each having separate input handling code. Then, using trigonometry, I calculated the new xy position for the camera. Repeat the same steps for the x axis if you want to move in the direction you're looking vertically too. \$\endgroup\$
    – Oskar
    Commented Jul 10, 2012 at 9:47
  • \$\begingroup\$ I added a code example, if that helps. \$\endgroup\$
    – Synthetix
    Commented Jul 10, 2012 at 9:59

I figured out the problem. It had to do with this line:

if(key_pressed == 'w'){
    cam_pos[2] += (dir_move[2] * -INPUT_SENS_Z); //z

I was only adding to an individual element in the vector array. I should have been adding to the entire array as a unit:

if(key_pressed == 'w'){
    vec4_add(cam_pos,cam_pos,dir_move); //add dir_move to cam_pos

I still need to include the INPUT_SENS_Z value in the example to throttle the speed, but you get the idea. Thank goodness that's solved!


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .