I am currently creating a 3D first-person shooter game in the browser using WebGL. How would I implement mouselook/free look for such a game?

  • \$\begingroup\$ Look at THREE.js's implementation of FirstPersonControls class. You might also need to lock the pointer in order to freely look around the player. Try this: Pointer Lock. Unfortunately it's not implemented in Opera and IE but WebGL isn't implement in those browsers either. \$\endgroup\$ Commented Oct 24, 2012 at 19:14

3 Answers 3


Mouselook is now supported in Chrome and Firefox via the W3C Pointer Lock specification. Essentially:

document.onmousemove = function (e) {
  document.body.innerHTML = "<div>dx: " + 
    (e.movementX || e.mozMovementX || e.webkitMovementX || 0);

document.body.onclick = document.body.requestPointerLock ||
                        document.body.mozRequestPointerLock ||

A good tutorial article is Pointer Lock and First Person Shooter Controls on HTML5Rocks.

  • \$\begingroup\$ The bug must be fixed, because this demo works in firefox now: mdn.github.io/pointer-lock-demo If you update your comment, I'll give you an 'up' \$\endgroup\$
    – xaxxon
    Commented May 14, 2015 at 11:18

Capture mousemove Events and use the screenX and screenY properties of the event object to update camera position (use the delta to the last screenX and screenY position to get the amount of movement).

If you have some sort of scenegraph, you could build a node-setup like the following:

CameraNode (Scene Node)
 +- YawNode (Scene Node)
     +- PitchNode (Scene Node)
         +- Camera (actual Camera Object)

Movement in the X-Axis rotates the YawNode and movement in the Y-Axis rotates the PitchNode. The CameraNode will be moved when the player moves.


It's quite simple, and just takes two things.

  1. An event handler for the mouse move event.
  2. A camera object representing your basic model-view transformation

Sample event code

Here's some sample source code for doing the event handling. The system module (which handles all game <--> browser interaction) keeps track of two variables: lastMousePosition and lastMouseDelta.

To track the camera with the mouse, you just need lastMouseDelta which is how you will know how many degrees to rotate frame-to-frame.

  var canvas = /* WebGL rendering context */
  canvas.onmousedown = function (event) { me.handleMouseDown(event); };
  canvas.onmouseup   = function (event) { me.handleMouseUp(event);   };
  canvas.onmousemove = function (event) { me.handleMouseMove(event); };

  // snip

  engine.SystemModule.prototype.handleMouseMove = function(event) {
    this.lastMouseDelta = [event.clientX - this.lastMousePosition[0],
                           event.clientY - this.lastMousePosition[1]];
    this.lastMousePosition = [event.clientX, event.clientY];

Same camera movement code

Here's some sample code for handling the camera rotation. Given the number of pixels the mouse has moved in the X or Y direction, rotate the camera by that many degrees.

   * degrees/pixel
   * @const
  var cameraMouseRotation = 0.5;

  // Mouse movement for camera angle.
  if (sys.isMouseDown()) {
    var positionChange = sys.getLastMousePositionDelta();
    camera.rotateYDegs(cameraMouseRotation * positionChange[0]);
    camera.rotateXDegs(-cameraMouseRotation * positionChange[1]);

Later, when you actually go on to render your world, simply generate a model-view matrix from your camera. (Converting the camera's position, yaw, pitch, and roll into vectors you can pass to gluLookAt.) And you should be good to go.


You must log in to answer this question.

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