How to Use Three.js setScissor and setScissorTest

In Three.js, rendering can be restricted to a specific rectangular region of the canvas using the setScissor and setScissorTest methods of the WebGLRenderer. This article provides a straightforward guide on how to enable scissor testing, define a custom rendering viewport, and use these tools to render multiple scenes or views on a single canvas.

Understanding the Scissor Test

By default, Three.js renders to the entire WebGL canvas. When you enable the scissor test, you tell the WebGL context to discard any pixels that fall outside of a specified rectangular mask. This is highly useful for creating split-screen effects, minimaps, or rendering multiple independent views in a single canvas performance-efficiently.

Step-by-Step Implementation

To restrict rendering to a specific rectangle, you must configure the renderer using three main steps: enabling the scissor test, defining the scissor box, and updating the viewport.

1. Enable the Scissor Test

Before specifying the boundaries, you must explicitly enable scissor testing on the renderer.

renderer.setScissorTest(true);

2. Define the Scissor Rectangle

Use the setScissor method to define the boundaries of the rendering region. The parameters are (x, y, width, height).

Note: In WebGL, the coordinate system starts at the bottom-left corner of the canvas (0,0 is bottom-left).

const x = 100;       // Pixels from the left
const y = 50;        // Pixels from the bottom
const width = 400;   // Width of the rectangle
const height = 300;  // Height of the rectangle

renderer.setScissor(x, y, width, height);

3. Update the Viewport

To ensure that your camera’s projection scales correctly to the new rectangle (rather than squishing the full-canvas render into the smaller box), you should update the viewport to match the scissor dimensions.

renderer.setViewport(x, y, width, height);

4. Render the Scene

Once the scissor and viewport are configured, trigger the standard render call. Only the defined rectangular area will be drawn on.

renderer.render(scene, camera);

Complete Code Example

Below is a complete implementation showing how to render a scene inside a specific \(300 \times 200\) pixel box in the bottom-left corner of the canvas.

// Setup renderer
const renderer = new THREE.WebGLRenderer({ canvas: myCanvas });
renderer.setSize(window.innerWidth, window.innerHeight);

// Define the rendering region
const width = 300;
const height = 200;
const x = 0;
const y = 0; // Bottom-left corner

// 1. Enable scissor testing
renderer.setScissorTest(true);

// 2. Constrain the rendering area
renderer.setScissor(x, y, width, height);
renderer.setViewport(x, y, width, height);

// 3. Render the scene
renderer.render(scene, camera);

// 4. Disable scissor test (optional)
// Disable this if you need to perform full-screen rendering passes afterward
renderer.setScissorTest(false);

Rendering Multiple Views

If you are rendering multiple views (like a split-screen game or a CAD editor with top, side, and front views), repeat this process for each view inside your animation loop:

  1. Enable setScissorTest(true).
  2. Define the boundaries for View A using setScissor and setViewport.
  3. Render View A.
  4. Define the boundaries for View B using setScissor and setViewport.
  5. Render View B.
  6. Disable setScissorTest(false) if you need to render full-screen UI overlays.