How to Set WebGL Viewport Dimensions Manually

This article explains how to manually set the viewport dimensions in WebGL using the gl.viewport() method. You will learn the syntax of this function, what each parameter represents, how WebGL maps coordinates to screen space, and how to properly handle viewport updates when resizing the HTML5 canvas to prevent visual distortion.

The method used to manually set the WebGL viewport dimensions is gl.viewport(). This function specifies the affine transformation of \(x\) and \(y\) from normalized device coordinates (which range from -1 to 1) to window coordinates (pixel space on the canvas).

Syntax and Parameters

gl.viewport(x, y, width, height);
  • x: A GLint specifying the horizontal coordinate for the lower-left corner of the viewport origin. The default is 0.
  • y: A GLint specifying the vertical coordinate for the lower-left corner of the viewport origin. The default is 0.
  • width: A GLsizei specifying the width of the viewport in pixels.
  • height: A GLsizei specifying the height of the viewport in pixels.

In WebGL, the origin (0, 0) is located at the bottom-left corner of the canvas, unlike standard CSS or 2D canvas contexts where the origin is at the top-left.

Basic Implementation

When initializing your WebGL context, you typically match the viewport to the internal resolution of the canvas:

const canvas = document.getElementById("glcanvas");
const gl = canvas.getContext("webgl");

// Set the viewport to cover the entire canvas drawing buffer
gl.viewport(0, 0, canvas.width, canvas.height);

Handling Window and Canvas Resizing

Setting the viewport once during initialization is insufficient if the canvas changes size dynamically. If the drawing buffer changes and gl.viewport() is not called again, the rendered image will appear stretched, squashed, or clipped.

To handle dynamic sizing, synchronize the canvas drawing buffer with its display size and update the viewport prior to rendering:

function resizeCanvasToDisplaySize(canvas) {
  const displayWidth = canvas.clientWidth;
  const displayHeight = canvas.clientHeight;

  const needResize = canvas.width !== displayWidth || canvas.height !== displayHeight;

  if (needResize) {
    canvas.width = displayWidth;
    canvas.height = displayHeight;
  }

  return needResize;
}

function render() {
  if (resizeCanvasToDisplaySize(gl.canvas)) {
    gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
  }

  // Draw scene...
  requestAnimationFrame(render);
}

requestAnimationFrame(render);

Viewport vs. Canvas Size

The viewport does not alter the size of the canvas element itself; it only dictates where WebGL draws inside the canvas drawing buffer. Setting the viewport smaller than the canvas dimensions will cause rendering to occupy only a sub-region of the canvas, which can be useful for split-screen rendering or UI overlays.