WebGL Camera Transformation
Related Topics: OpenGL Camera
- Overview
- Camera LookAt
- Camera Rotation: Pitch, Yaw and Roll
- Camera Translation: Shift and Forward
- Example: Camera Interface
Overview
Please note the camera object in WebGL is virtual (does not exist). Instead, we inversely transform the whole vertex data in the scene from the world space to the eye space using the view matrix, where the virtual camera is positioned at (0, 0, 0) and always facing to -Z axis in the eye space. For example, rotating the camera left is equivalent to rotating the whole scene to right, and shifing the camera left is same as shifting the scene to right.
Camera LookAt
With lookAt() function, you can rotate the camera to the given target point from the camera position. It is used for an orbital camera interface which is always facing to the target object. The view matrix of lookAt() consists of 2 transformation parts; translation matrix MT and rotation matrix MR.
Function | Description |
---|---|
lookAt(px,py,pz, tx,ty,tz) | Position the camera at (px, py, pz) and rotate to (tx, ty, tz) |
Please see how to construct the lookAt matrix for details. A typical usage of lookAt() follows;
// global var
let gl = {};
...
// create camera object with position (0,0,5) and looking to target (0,0,0)
gl.camera = new OrbitCamera(0,0,5, 0,0,0);
// lookat from position (1,2,3) to target (0,0,0)
gl.camera.lookAt(1,2,3, 0,0,0);
...
// pass view matrix to shader
gl.uniformMatrix4fv(gl.program.uniform.matrixView, false, gl.camera.matrix.m);
...
Camera Rotation (Pitch, Yaw, Roll)

Pitch is rotating the camera along the camera's local X-axis, Yaw is rotating it along Y-axis and Roll is rotating it along Z-axis. These rotations are used for first-person shooter style games. Visit OpenGL Camera Rotation page to learn more about how to construct the camera rotation matrix.
Please note that matrix muliplication is not cummutative. If you combine pitch, yaw and roll together, the different order of multiple rotations produces a different result. A common sequence of rotations is Roll → Yaw → Pitch.
OrbitCamera class provides rotateTo() to rotate it to the given angles (degrees) or quaternion. It also allows gradual animation for the given duration (ms). If the duration is not specified, the camera will snap to the target angles immediately.
Function | Description |
---|---|
rotateTo(to, duration) | Rotate to the target angles or quaternion (If duration is given, rotate this gradually.) |
// global var
let gl = {};
...
// create camera object with position (0,0,5) and target (0,0,0)
gl.camera = new OrbitCamera(0,0,5, 0,0,0);
// rotate camera with pitch=30, yaw=40, duration=1000ms
let angle = new Vector3(30, 40, 0); // degree angles
gl.camera.rotateTo(angle); // snap to the angle immediately
gl.camera.rotateTo(angle, 1000); // rotate gradually for 1 sec
...
// rotate camera with quaternion for 2000ms
let q = Quaternion.toQuaternionFromAngles(1, 2, 0); // radian angles to q
gl.camera.rotateTo(q); // snap to the quaternion immediately
gl.camera.rotateTo(q, 2000); // gradually rotate for 2 sec
...
Camera Translation (Shift and Forward)

In the camera interface for first-person shooter games, you want to move left/right or forward/backward in the 3D scene. These translations require shifting a delta movement along the camera's local axis; Left (X-axis), Up (Y-axis) and Forward (Z-axis) vectors.
You can acquire these local axis directly from its view matrix;
Please see how to derive the camera's local axis for details. Common interfaces for the camera translations are;
Function | Description |
---|---|
shift(delta, duration) | Move left/right and up/down by the delta amount (deltax, deltay) (If duration is given, move this gradually.) |
moveForward(delta, duration) | Move forward/backward by the delta amount, deltaz (If duration is given, move this gradually.) |
moveTo(to, duration) | Move this position to the target position (tox, toy, toz) (If duration is given, move this gradually.) |
startShift(dir, accel) | Start to shift to the given direction and acceleration |
stopShift() | Stop shifting |
startForward(speed, accel) | Start to move forward/backward to the given speed and acceleration (If the speed is positive, it moves forward.) |
stopForward() | Stop forwarding |
// global var
let gl = {};
...
// create camera object with position (0,0,5) and target (0,0,0)
gl.camera = new OrbitCamera(0,0,5, 0,0,0);
// shift camera left and up by (10, 20), duration=1000ms
let delta = new Vector2(10, 20);
gl.camera.shift(delta); // shift by delta immediately
gl.camera.shift(delta, 1000); // shift gradually for 1 sec
...
// forward camera by 5, duration=1000ms
gl.camera.moveForward(5); // forward immediately
gl.camera.moveForward(5, 1000); // forward gradually for 1 sec
...
// move camera position to (10, 20, 30), duration=2000ms
let to = new Vector3(10, 20, 30);
gl.camera.moveTo(to); // move immediately
gl.camera.moveTo(to, 2000); // move gradually for 2 sec
...
Example: Camera Interface
This example demonstrates how to implement the camera interface with JavaScript pointer event API (mouse + touch + stylus). It also binds the keyboard events. You can use the arrow keys to shift the camera and +/- key to move forward/backward.
Fullscreen Demo: test_cameraOrbit.html
GitHub Repo: test_cameraOrbit.html