webgl2 方法解析: SCISSOR_TEST

在 WebGL 中,gl.SCISSOR_TEST 是一个重要的功能,用于限制渲染操作的区域,从而提高渲染效率或实现特定的视觉效果。

1. 什么是 gl.SCISSOR_TEST?

gl.SCISSOR_TEST 是 WebGL 中的一个功能标志,用于启用或禁用剪切测试(Scissor Test)。剪切测试允许开发者指定一个矩形区域(剪切框),只有在这个区域内的像素才会被渲染,区域外的像素将被丢弃。

2. 如何启用和禁用剪切测试?

  • 启用剪切测试:

    ini 复制代码
    gl.enable(gl.SCISSOR_TEST);
  • 禁用剪切测试:

    ini 复制代码
    gl.disable(gl.SCISSOR_TEST);

    默认情况下,剪切测试是禁用的。

3. 如何设置剪切区域?

使用 gl.scissor() 方法可以设置剪切区域。该方法的参数包括剪切框的左下角坐标 (x, y) 以及框的宽度和高度 (width, height):

arduino 复制代码
gl.scissor(x, y, width, height);
  • x 和 y 是剪切框左下角的坐标。
  • width 和 height 是剪切框的宽度和高度。

4. 使用示例

以下是一个完整的示例,展示如何在 WebGL 中使用 gl.SCISSOR_TEST 来限制渲染区域:

ini 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>WebGL Scissor Test Example</title>
  <style>
    canvas {
      border: 1px solid black;
    }
  </style>
</head>
<body>
  <h1>WebGL Scissor Test Example</h1>
  <canvas id="glCanvas" width="500" height="500"></canvas>
  <script>
    // 获取 canvas 元素
    const canvas = document.getElementById('glCanvas');
    const gl = canvas.getContext('webgl');
​
    if (!gl) {
      console.error('WebGL not supported, falling back on experimental-webgl');
      gl = canvas.getContext('experimental-webgl');
    }
​
    if (!gl) {
      alert('Your browser does not support WebGL');
    }
​
    // 顶点着色器
    const vertexShaderSource = `
      attribute vec4 aVertexPosition;
      void main() {
        gl_Position = aVertexPosition;
      }
    `;
​
    // 片段着色器
    const fragmentShaderSource = `
      void main() {
        gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); // 红色
      }
    `;
​
    // 创建着色器
    function loadShader(type, source) {
      const shader = gl.createShader(type);
      gl.shaderSource(shader, source);
      gl.compileShader(shader);
      if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
        console.error('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader));
        gl.deleteShader(shader);
        return null;
      }
      return shader;
    }
​
    // 创建程序
    const vertexShader = loadShader(gl.VERTEX_SHADER, vertexShaderSource);
    const fragmentShader = loadShader(gl.FRAGMENT_SHADER, fragmentShaderSource);
​
    const shaderProgram = gl.createProgram();
    gl.attachShader(shaderProgram, vertexShader);
    gl.attachShader(shaderProgram, fragmentShader);
    gl.linkProgram(shaderProgram);
​
    if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
      console.error('Unable to initialize the shader program: ' + gl.getProgramInfoLog(shaderProgram));
    }
​
    gl.useProgram(shaderProgram);
​
    // 设置顶点数据
    const positions = [
      -0.5, -0.5,
       0.5, -0.5,
       0.5,  0.5,
      -0.5,  0.5
    ];
​
    const positionBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
​
    const aVertexPosition = gl.getAttribLocation(shaderProgram, 'aVertexPosition');
    gl.enableVertexAttribArray(aVertexPosition);
    gl.vertexAttribPointer(aVertexPosition, 2, gl.FLOAT, false, 0, 0);
​
    // 设置视口
    gl.viewport(0, 0, canvas.width, canvas.height);
​
    // 启用剪切测试
    gl.enable(gl.SCISSOR_TEST);
​
    // 设置剪切区域(只渲染右上角的 200x200 区域)
    gl.scissor(300, 300, 200, 200);
​
    // 清空颜色缓冲区
    gl.clearColor(0.0, 0.0, 0.0, 1.0); // 设置背景为黑色
    gl.clear(gl.COLOR_BUFFER_BIT);
​
    // 绘制矩形
    gl.drawArrays(gl.TRIANGLE_FAN, 0, 4);
​
    // 禁用剪切测试(可选)
    // gl.disable(gl.SCISSOR_TEST);
  </script>
</body>
</html>

在这个示例中,只有剪切区域内的像素会被渲染为红色,其他区域保持黑色。

5. 注意事项

  • 剪切区域的坐标 (x, y) 是相对于画布左下角的。
  • 如果 width 或 height 为负值,将会抛出 gl.INVALID_VALUE 错误。
  • 剪切测试通常与视口(Viewport)设置配合使用,以实现更复杂的渲染控制。
相关推荐
香芋芋圆3 小时前
iD-editor 详解|OSM官方在线编辑器,基于D3.js的轻量地图编辑器
开发语言·javascript·编辑器
晗夜未央5 小时前
任务队列反复失败,先分清重试、阻塞和结果待核对
开发语言·javascript
jktantan6 小时前
每个节点 41 字节:把一棵百万节点树拆进 14 个 typed array
前端·javascript·vue.js·算法·typescript
我命由我123457 小时前
访客系统形式(有用户概念、无用户概念)
java·开发语言·前端·javascript·python·产品运营·产品经理
程序员大阳7 小时前
副队长JavaScript教程(65)-详解JSON:轻量级数据交换格式
javascript·json·序列化·反序列化·stringify·parse
paopaokaka_luck9 小时前
基于springboot+vue的益暖微光公益服务平台(DeepSeek公益助手、善款信息追溯、志愿服务积分闭环、ECharts运营分析、活动状态自动流转)
java·前端·javascript·spring boot·mysql·架构·echarts
栀椩9 小时前
Electron 内嵌页面跨域问题(CORS/PNA)解决全记录
前端·javascript·electron
SEO_juper9 小时前
Chrome 扩展一键查看当前页面 SEO 信息:不用切页面,点一下全出来
前端·javascript·chrome
Highcharts.js9 小时前
CSUN 2026|Highcharts无障碍数据与AI分享
javascript·人工智能·数据分析·highcharts·图表开发
系统集成-鹰翔9 小时前
ERP推单数据库怎么备份:SQLite WAL模式下只复制db文件为什么可能漏任务
javascript·数据库·经验分享·后端