基本剪裁

在这个示例中,我们将看到如何使用 WebGL 剪裁操作绘制简单的矩形和正方形。剪裁会建立一个剪裁区域,在该区域之外不会进行绘制。

应用剪裁时清除绘制缓冲区

这是一个使用 scissor() 进行渲染的简单演示。

虽然 clear() 绘制命令将清除颜色(由 clearColor() 设置)写入绘制缓冲区中的所有像素,但 scissor() 定义了一个遮罩,只允许在指定矩形区域内的像素更新。

这是一个很好的机会来谈论像素和片段之间的区别。像素是指屏幕上的一个图片元素(实际上是一个点),或者是指绘制缓冲区中的一个元素,该缓冲区是存储像素数据的内存区域(例如 RGB 颜色分量)。片段是指在 WebGL 管道处理过程中所指的像素。

这样区分的原因是,片段颜色(以及其他片段值,例如深度)在图形操作过程中可能被多次操作和更改,最后才写入屏幕。我们已经看到在图形操作过程中片段颜色如何改变,例如通过应用 颜色遮罩。在其他情况下,片段可能完全被丢弃(因此像素值不会更新),或者它可能与已经存在的像素值进行交互(例如,在对场景中非不透明元素进行颜色混合时)。

这里我们看到了片段和像素之间区别的另一个示例。剪裁是 WebGL/OpenGL 图形管道中的一个独特阶段(它发生在颜色清除之后,但在颜色遮罩之前)。在实际更新像素之前,片段必须通过剪裁测试。如果片段通过剪裁测试,它们将继续沿着图形管道向下传递,并且相应的像素将在屏幕上更新。如果它们未通过测试,它们将立即被丢弃,不会进行任何进一步的处理,并且像素不会更新。由于只有指定矩形区域内的片段才能成功通过剪裁测试,因此只有该区域内的像素才会更新,并且我们在屏幕上会得到一个矩形。

管道中的剪裁阶段默认情况下是禁用的。我们在这里使用 enable() 方法启用它(您还将使用 enable() 激活 WebGL 的许多其他功能;因此,在这种情况下,使用 SCISSOR_TEST 常量作为参数)。这再次说明了 WebGL 中命令的典型顺序。我们首先调整 WebGL 状态。在这种情况下,启用剪裁测试并建立一个矩形遮罩。只有在 WebGL 状态得到满意调整后,我们才会执行绘制命令(在本例中为 clear()),该命令会启动片段沿着图形管道向下传递的处理过程。

html
<p>Result of scissoring.</p>
<canvas>Your browser does not seem to support HTML canvas.</canvas>
css
body {
  text-align: center;
}
canvas {
  display: block;
  width: 280px;
  height: 210px;
  margin: auto;
  padding: 0;
  border: none;
  background-color: black;
}
js
window.addEventListener(
  "load",
  function setupWebGL(evt) {
    "use strict";
    window.removeEventListener(evt.type, setupWebGL, false);
    const paragraph = document.querySelector("p");
    const canvas = document.querySelector("canvas");

    // The following two lines set the size (in CSS pixels) of
    // the drawing buffer to be identical to the size of the
    // canvas HTML element, as determined by CSS.
    canvas.width = canvas.clientWidth;
    canvas.height = canvas.clientHeight;

    const gl =
      canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
    if (!gl) {
      paragraph.textContent =
        "Failed to get WebGL context. Your browser or device may not support WebGL.";
      return;
    }
    gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);

    // Enable scissoring operation and define the position and
    // size of the scissoring area.
    gl.enable(gl.SCISSOR_TEST);
    gl.scissor(40, 20, 60, 130);

    // Clear the drawing buffer solid yellow.
    gl.clearColor(1.0, 1.0, 0.0, 1.0);
    gl.clear(gl.COLOR_BUFFER_BIT);
  },
  false,
);

本示例的源代码也已发布在 GitHub 上。