Notification：body 属性 - Web API 接口参考

Notification：body 属性
====================

**备注：** 此特性在 Web Worker 中可用

**安全上下文:** 此项功能仅在一些支持的浏览器的安全上下文（HTTPS）中可用。

`Notification` 接口的 **`body`** 只读属性指示通知的正文字符串，该字符串在 `Notification()` 构造函数的 `body` 选项中指定。

值
-

一个字符串。

示例
--

```js
function spawnNotification(theBody, theIcon, theTitle) {
  const options = {
    body: theBody,
    icon: theIcon,
  };
  const n = new Notification(theTitle, options);

  console.log(n.body);
}
```

规范
--

| Specification |
| --- |
| Notifications API Standard # dom-notification-body |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* 使用 Notification API


Notification：maxActions 静态属性 - Web API 接口参考

Notification：maxActions 静态属性
============================

**备注：** 此特性在 Web Worker 中可用

**安全上下文:** 此项功能仅在一些支持的浏览器的安全上下文（HTTPS）中可用。

**实验性:** **这是一项实验性技术**
在将其用于生产之前，请仔细检查浏览器兼容性表格。

`Notification` 接口的 **`maxActions`** 属性返回设备和用户代理支持的最大操作数量。实际上，这是会被用户代理遵守的 `Notification.actions` 数组中的元素的最大数量。

值
-

一个表示用户代理和设备可以向用户呈现的通知操作的最大数量的整数。

示例
--

以下代码片段打印了支持的操作的最大数量。

```js
const maxActions = Notification.maxActions;
console.log(`此设备最多可以对每个通知显示 ${maxActions} 个操作。`);
```

规范
--

| Specification |
| --- |
| Notifications API Standard # dom-notification-maxactions |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* 使用 Notification API
* `Notification.actions`


Notification：permission 静态属性 - Web API 接口参考

Notification：permission 静态属性
============================

**备注：** 此特性在 Web Worker 中可用

**安全上下文:** 此项功能仅在一些支持的浏览器的安全上下文（HTTPS）中可用。

`Notification` 接口的只读属性 `permission` 表明当前用户是否授予当前来源（origin）显示 web 通知的权限。

值
-

一个表示当前权限的字符串。其值可以是：

`granted`

用户已经明确地授予了当前来源显示系统通知的权限。

`denied`

用户已经明确地拒绝了当前来源显示系统通知的权限。

`default`

用户是否授予当前来源显示系统通知的权限的决定是未知的；在这种情况下，应用的行为与该值为 `denied` 的情况相同。

示例
--

如果你想首先检查是否支持通知，然后检查是否已授予当前来源发送通知的权限，然后在发送通知之前请求权限（如果需要），则可以使用以下代码段。

```js
function notifyMe() {
  if (!("Notification" in window)) {
    // 检查浏览器是否支持桌面通知
    alert("此浏览器不支持桌面通知");
  } else if (Notification.permission === "granted") {
    // 检查通知权限是否已经被授予；如果是的话，创建一条通知
    const notification = new Notification("你好呀！");
    // …
  } else if (Notification.permission !== "denied") {
    // 我们需要请求用户的许可
    Notification.requestPermission().then((permission) => {
      // 如果用户同意，让我们创建一个通知
      if (permission === "granted") {
        const notification = new Notification("你好呀！");
        // …
      }
    });
  }
  // 最后，如果用户拒绝了通知，而你想要尊重他们，就没有必要再打扰他们了
}
```

规范
--

| Specification |
| --- |
| Notifications API Standard # dom-notification-permission |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* Notification API
* 使用 Notification API
* Permission API (en-US)
* 使用 Permission API


Notification：renotify 属性 - Web API 接口参考

Notification：renotify 属性
========================

**备注：** 此特性在 Web Worker 中可用

**安全上下文:** 此项功能仅在一些支持的浏览器的安全上下文（HTTPS）中可用。

**实验性:** **这是一项实验性技术**
在将其用于生产之前，请仔细检查浏览器兼容性表格。

`Notification` 接口的 **`renotify`** 只读属性指定在新通知替换旧通知后是否应当通知用户，在 `Notification()` 构造函数的 `renotify` 选项中指定。

值
-

一个布尔值。默认值为 `false`；设为 `true` 将会重新通知用户。

示例
--

以下代码片段用于在一个通知被替换以后触发重新向用户发送通知；它创建一个简单的 `options` 对象，然后调用 `Notification()` 构造函数触发通知。

```js
const options = {
  body: "你提交的代码收到了 3 条新的审阅意见。",
  renotify: true,
};

const n = new Notification("新评论活动", options);

console.log(n.renotify); // "true"
```

规范
--

| Specification |
| --- |
| Notifications API Standard # dom-notification-renotify |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* 使用 Notification API


Notification：timestamp 属性 - Web API 接口参考

Notification：timestamp 属性
=========================

**备注：** 此特性在 Web Worker 中可用

**安全上下文:** 此项功能仅在一些支持的浏览器的安全上下文（HTTPS）中可用。

**实验性:** **这是一项实验性技术**
在将其用于生产之前，请仔细检查浏览器兼容性表格。

`Notification` 接口的 **`timestamp`** 只读属性返回一个数字。此属性通过  `Notification()` 构造函数的 `timestamp` 选项指定。

通知的时间戳可以表示创建通知的事件的时间（自 1970 年 1 月 1 日 00:00:00 UTC 时间以来的毫秒数），或者它可以是你希望与通知相关联的任意时间戳。例如，一个即将召开的会议的时间戳可以设置在未来，而一条错过的消息的时间戳可以设置在过去。

值
-

一个表示时间戳的数字，以 Unix 时间形式按毫秒为单位给出。

示例
--

以下代码片段会触发一条通知；首先创建一个简单的 `options` 对象，然后使用 `Notification()` 构造函数触发通知。

```js
const dts = Math.floor(Date.now());

const options = {
  body: "你提交的代码收到了 3 条新的审阅意见。",
  timestamp: dts,
};

const n = new Notification("新的评论活动", options);

console.log(n.timestamp); // 输出 timestamp
```

规范
--

| Specification |
| --- |
| Notifications API Standard # dom-notification-timestamp |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* 使用 Notification API


Path2D.addPath() - Web API 接口参考

Path2D.addPath()
================

**`Path2D.addPath()`** 是 Canvas 2D API 根据指定路径变量添加路径的方法。

语法
--
```

void path.addPath(path [, transform]);
```

### 参数

`path`

需要添加的 `Path2D` 路径。

`transform` 可选

`DOMMatrix` 作为新增路径的变换矩阵。

示例
--

### 在已有的路径上添加一条路径

这是一段使用 `addPath` 方法的简单的代码片段。

#### HTML

```html
<canvas id="canvas"></canvas>
```

#### JavaScript

```js
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");

// Create first path and add a rectangle
let p1 = new Path2D();
p1.rect(0, 0, 100, 150);

// Create second path and add a rectangle
let p2 = new Path2D();
p2.rect(0, 0, 100, 75);

// Create transformation matrix that moves 200 points to the right
let m = new DOMMatrix();
m.a = 1;
m.b = 0;
m.c = 0;
m.d = 1;
m.e = 200;
m.f = 0;

// Add second path to the first path
p1.addPath(p2, m);

// Draw the first path
ctx.fill(p1);
```

#### 结果

规范
--

| Specification |
| --- |
| HTML Standard # dom-path2d-addpath-dev |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* 接口定义，`Path2D`


Path2D() - Web API 接口参考

Path2D()
========

**实验性:** **这是一项实验性技术**
在将其用于生产之前，请仔细检查浏览器兼容性表格。

**`Path2D()`** 构造函数返回一个新的 `Path2D` 对象的实例，可以选择另一条路径作为参数（创建一个拷贝），或者选择 SVG path 数据构成的字符串。

语法
--
```

new Path2D();
new Path2D(path);
new Path2D(d);
```

### 参数

`path` 可选

当调用另一个 `Path2D` 对象时，会创建一个 `path` 变量的拷贝。

`d` 可选

当调用 SVG path 数据构成的字符串时，会根据描述创建一个新的路径。

示例
--

### 创建和拷贝路径

这是一段简单的代码片段，创建和拷贝 `Path2D` 路径。
```

<canvas id="canvas"></canvas>
```

```js
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");

let path1 = new Path2D();
path1.rect(10, 10, 100, 100);

let path2 = new Path2D(path1);
path2.moveTo(220, 60);
path2.arc(170, 60, 50, 0, 2 \* Math.PI);

ctx.stroke(path2);
```

### 使用 SVG 路径

这是一段简单的代码片段，使用 SVG path data 创建一个 `Path2D` 路径。路径将会移动到点 (`M10 10`) ，然后向右侧水平移动 80 个点 (`h 80`)，然后向下 80 个点 (`v 80`)，然后向左 80 个点 (`h -80`)，最后回到起始点 (`z`)。
```

<canvas id="canvas"></canvas>
```

```js
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");

let p = new Path2D("M10 10 h 80 v 80 h -80 Z");
ctx.fill(p);
```

规范
--

| Specification |
| --- |
| HTML Standard # dom-path2d-dev |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* `Path2D`, 这个构造函数属于此接口。


HTMLVideoElement: leavepictureinpicture event - Web API 接口参考

HTMLVideoElement: leavepictureinpicture event
=============================================

**`leavepictureinpicture`** 事件会在 `HTMLVideoElement` 成功离开画中画模式时触发。

此事件不可取消，也不会冒泡。

语法
--

在 `addEventListener()`等方法中使用事件方法名，或者设置事件处理器属性。

```js
addEventListener("leavepictureinpicture", (event) => {});

onleavepictureinpicture = (event) => {};
```

事件类型
----

`PictureInPictureEvent` (en-US) 继承自 `Event`。

Event

PictureInPictureEvent

(en-US)事件属性
----

继承自 `Event` 的 `PictureInPictureEvent` (en-US)。

示例
--

这些示例为 `leavepictureinpicture` 事件增加事件侦听器，然后在该事件处理程序对事件触发做出反应时发布消息。

使用 `addEventListener()`:

```js
const video = document.querySelector('#video');
const button = document.querySelector('#button');

function onExitPip() {
  console.log("Picture-in-Picture mode deactivated!");
}

video.addEventListener("leavepictureinpicture", onExitPip, false);

button.onclick = function() => {
  if (document.pictureInPictureElement) {
    document.exitPictureInPicture();
  }
}
```

使用事件处理程序 `onleavepictureinpicture`:

```js
const video = document.querySelector('#video');
const button = document.querySelector('#button');

function onExitPip() {
  console.log("Picture-in-Picture mode deactivated!");
}

video.onleavepictureinpicture = onExitPip;

button.onclick = function() => {
  if (document.pictureInPictureElement) {
    document.exitPictureInPicture();
  }
}
```

规范
--

| Specification |
| --- |
| Picture-in-Picture # eventdef-htmlvideoelement-leavepictureinpicture |
| Picture-in-Picture # dom-htmlvideoelement-onleavepictureinpicture |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* `HTMLVideoElement`
* `Picture-in-Picture_API`


HTMLVideoElement: enterpictureinpicture event - Web API 接口参考

HTMLVideoElement: enterpictureinpicture event
=============================================

**`enterpictureinpicture`** 事件会在 `HTMLVideoElement` 成功进入画中画模式时触发。

此事件不可取消，也不会冒泡

语法
--

在 `addEventListener()`使用事件的名称，或者设置事件处理器属性。

```js
addEventListener("enterpictureinpicture", (event) => {});

onenterpictureinpicture = (event) => {};
```

事件类型
----

`PictureInPictureEvent` (en-US) 继承自 `Event` 。

Event

PictureInPictureEvent

(en-US)事件属性
----

此接口继承他的父类 `Event` 的属性。

示例
--

这些示例为 `enterpictureinpicture` 事件添加事件侦听器，然后在该事件处理程序对事件触发做出反应时发布消息。

使用 `addEventListener()`:

```js
const video = document.querySelector('#video');
const button = document.querySelector('#button');

function onEnterPip() {
  console.log("Picture-in-Picture mode activated!");
}

video.addEventListener('enterpictureinpicture', onEnterPip, false);

button.onclick = function() => {
  video.requestPictureInPicture();
}
```

使用事件处理程序 `onenterpictureinpicture` :

```js
const video = document.querySelector('#video');
const button = document.querySelector('#button');

function onEnterPip() {
  console.log("Picture-in-Picture mode activated!");
}

video.onenterpictureinpicture = onEnterPip;

button.onclick = function() => {
  video.requestPictureInPicture();
}
```

规范
--

| Specification |
| --- |
| Picture-in-Picture # eventdef-htmlvideoelement-enterpictureinpicture |
| Picture-in-Picture # dom-htmlvideoelement-onenterpictureinpicture |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* `HTMLVideoElement`
* `Picture-in-Picture_API`


HTMLVideoElement.videoWidth - Web API 接口参考

HTMLVideoElement.videoWidth
===========================

`HTMLVideoElement` 接口提供只读的 **`videoWidth`** 属性，指示视频的 固有宽度，使用 css 的像素值表示。
 简单来说，这是媒体的初始宽度。

参见 `HTMLVideoElement.videoHeight` > About intrinsic width and height 查看更多细节。

属性
--

 整数值，以 CSS 的像素值指定视频的固有宽度。
 如果元素的 `readyState` 是`HTMLMediaElement.HAVE_NOTHING`，则此属性的值为 0，因为视频和开头帧的大小并不能知道。

规范
--

| Specification |
| --- |
| HTML Standard # dom-video-videowidth-dev |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


HTMLVideoElement.videoHeight - Web API 接口参考

HTMLVideoElement.videoHeight
============================

`HTMLVideoElement` 接口提供只读的 **`videoHeight`** 属性，指示视频的 固有高度 ，使用 CSS 的像素值表示。
 简单来说，这是媒体的初始高度。

属性
--

 整数值，以 CSS 的像素值指定视频的固有高度。
 如果元素的 `readyState` 是 `HTMLMediaElement.HAVE_NOTHING`，则此属性的值为 0，因为视频和开头图片的大小并不能知道

### 关于固定的宽高

user agent 通过从媒体的原始像素宽度和高度开始计算元素媒体的固有宽度和高度，然后考虑以下因素：

* 媒体的宽高比。
* 媒体的镜头校正（以媒体中心点为中心的一个匹配目标长宽比的子矩形；译者注：用于校正媒体存在的暗角）。
* 目标设备的分辨率。
* 媒体格式所需要的任何其他因素。

如果元素当前显示的是视频的开头帧而不是呈现的视频内容，那么开头帧的固有大小将被视为元素 `<video>` 的大小。

 如果任何时候媒体的固有大小发生变化，但是元素的 `readyState` 不是 `HAVE_NOTHING`，则将会向该`<video>`元素发送 `resize` 事件。
 当元素从显示的开头帧切换到显示视频内容时，或者当显示的视频内容时。

示例
--

此示例为 `resize` 事件创建的处理程序，该事件调整 `<video>` 元素的大小以匹配其内容的固定大小。

```js
let v = document.getElementById("myVideo");

v.addEventListener(
  "resize",
  (ev) => {
    let w = v.videoWidth;
    let h = v.videoHeight;

    if (w && h) {
      v.style.width = w;
      v.style.height = h;
    }
  },
  false,
);
```

 请注意，只有当 `videoWidth` 和 `videoHeight` 都不是 0 的情况，才会应用更改。
 这样可以避免在还没有关于大小的情况下，应用无效的更改。

规范
--

| Specification |
| --- |
| HTML Standard # dom-video-videoheight-dev |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


HTMLVideoElement.disablePictureInPicture - Web API 接口参考

HTMLVideoElement.disablePictureInPicture
========================================

`HTMLVideoElement` 提供的 **`disablePictureInPicture`** HTML 属性用于指示是否应该向用户建议画中画的功能，或者自动请求该功能。

属性
--

一个布尔值，如果为`true`,阻止用户代理向用户建议该功能。

规范
--

| Specification |
| --- |
| Picture-in-Picture # disable-pip |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


HTMLVideoElement.requestPictureInPicture() - Web API 接口参考

HTMLVideoElement.requestPictureInPicture()
==========================================

**`HTMLVideoElement`** 接口提供的 **`requestPictureInPicture()`** 方法会发出异步请求，并以画中画的模式显示视频。

该方法不能保证视频进入画中画。如果授予了进入画中画的权限，则将返回一个 `Promise`，最终完成后将收到一个 `enterpictureinpicture` 事件，来表示它现在处于画中画状态。

语法
--

```js
requestPictureInPicture()
```

### 返回值

`PictureInPictureWindow` 对象将由 `Promise` 最终完成后获得。可以用于监听用户何时调整该浮动窗口的大小。

示例
--

本示例请求视频进入画中画模式，并设置事件监听以处理窗口大小的调整。

```js
function enterPictureInPicture() {
  videoElement.requestPictureInPicture().then((pictureInPictureWindow) => {
    pictureInPictureWindow.addEventListener(
      "resize",
      () => onPipWindowResize(),
      false,
    );
  });
}
```

规范
--

| Specification |
| --- |
| Picture-in-Picture # request-pip |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* `<video>` 元素
* `HTMLVideoElement.disablePictureInPicture`
* `Document.pictureInPictureEnabled`
* `Document.exitPictureInPicture()`
* `Document.pictureInPictureElement`
* `:picture-in-picture`


OscillatorNode.detune - Web API 接口参考

OscillatorNode.detune
=====================

`OscillatorNode` 的 `detune 属性的接口`是 a-rate `AudioParam` ，代表振荡频率的失谐量（cents）。

语法
--

```js
var oscillator = audioCtx.createOscillator();
oscillator.detune.value = 100; // value in cents
```

**备注：** 虽然返回的 `AudioParam` 是只读的，但是它表示的值不是。

### 值

一个 a-rate `AudioParam` 的值

示例
--

下面的例子使用 `AudioContext` 创建了一个 oscillator node。这是已经在运行的例子，查看 Violent Theremin demo (see app.js 是相关源码)。

```js
// create web audio api context
var audioCtx = new (window.AudioContext || window.webkitAudioContext)();

// create Oscillator node
var oscillator = audioCtx.createOscillator();

oscillator.type = "square";
oscillator.frequency.value = 440; // value in hertz
oscillator.detune.value = 100; // value in cents
oscillator.start();
```

规范
--

| Specification |
| --- |
| Web Audio API # dom-oscillatornode-detune |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* Using the Web Audio API (en-US)


OscillatorNode.setPeriodicWave() - Web API 接口参考

OscillatorNode.setPeriodicWave()
================================

`OscillatorNode` 接口的 **`setPeriodicWave()`** 方法用来指向 `PeriodicWave`，PeriodicWave 定义了一个周期性波形能够形成 oscillator 的输出，当`type` (en-US) 是 `custom` 的时候。

**备注：** 该方法取代了废弃的 `OscillatorNode.setWaveTable()`.

语法
--
```

OscillatorNode.setPeriodicWave(wave);
```

### 参数

`wave`

一个 `PeriodicWave` 对象，表示特定的波形用来形成 oscillator 的输出。

### 返回值

`undefined`示例
--

下面示例说明了 `createPeriodicWave() 方法的简单使用`, 从一个周期波形中重新生成了一个正弦波形。

```js
var real = new Float32Array(2);
var imag = new Float32Array(2);
var ac = new AudioContext();
var osc = ac.createOscillator();

real[0] = 0;
imag[0] = 0;
real[1] = 1;
imag[1] = 0;

var wave = ac.createPeriodicWave(real, imag);

osc.setPeriodicWave(wave);

osc.connect(ac.destination);

osc.start();
osc.stop(2);
```

这段代码可以运行因为通过定义一个正弦波形使得声音包含了基础的音调。

这里，我们用两个值创建一个`PeriodicWave`。第一个值是直流偏移，是 oscillator 开始的时候的值。这里 0 很合适，因为我们想要在 [-1.0; 1.0] 这个范围的中间值开始。

第二个和后面的值是正弦和余弦内容。可以把它看做傅里叶变换的结果，使得可以从时间阈值得到频率阈值。这里通过 `createPeriodicWave() 方法，可以指定频率，并且浏览器执行逆傅里叶变换来得到一个时间阈值缓冲。`Here, we only set one component at full volume (1.0) on the fundamental tone, so we get a sine wave.

规范
--

| Specification |
| --- |
| Web Audio API # dom-oscillatornode-setperiodicwave |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* Using the Web Audio API (en-US)
* AudioContext.createPeriodicWave (en-US)


OscillatorNode.frequency - Web API 接口参考

OscillatorNode.frequency
========================

`OscillatorNode` 的 `frequency 属性的接口`是 a-rate `AudioParam`，表示振荡的频率，单位 HZ（hertz）

语法
--

```js
var oscillator = audioCtx.createOscillator();
oscillator.frequency.value = 440; // value in hertz
```

**备注：** 虽然返回的 `AudioParam` 是只读的，但是它表示的值不是。

### 值

一个 a-rate `AudioParam` 的值

示例
--

下列示例使用 `AudioContext` 创建了一个 oscillator node. 这是一个用于展示的示例，查看 Violent Theremin demo (see app.js 是相关代码).

```js
// create web audio api context
var audioCtx = new (window.AudioContext || window.webkitAudioContext)();

// create Oscillator node
var oscillator = audioCtx.createOscillator();

oscillator.type = "square";
oscillator.frequency.value = 440; // value in hertz
oscillator.start();
```

规范
--

| Specification |
| --- |
| Web Audio API # dom-oscillatornode-frequency |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* Using the Web Audio API (en-US)


OscillatorNode() - Web API 接口参考

OscillatorNode()
================

**实验性:** **这是一项实验性技术**
在将其用于生产之前，请仔细检查浏览器兼容性表格。

**`OscillatorNode()`** 构造器创建了一个新的 `OscillatorNode` 对象，也是 `AudioNode` 类型，表示一个周期的波形，例如正弦波，用来在不同的对象中定义其可选属性的值

如果属性的默认值可接受，也可以选择使用 `AudioContext.createOscillator()` (en-US) 工厂方法构造 `OscillatorNode` 对象。

语法
--
```

var oscillatorNode = new OscillatorNode(context, options)
```

### 参数

`context`

指向 `AudioContext` 的引用。

`options` 可选

一个用来给 oscillator node 的属性指定值得对象，该对象中省略的属性都将采用默认值

`type`

oscillator node 产生的波形的形状。可用的值有 '`sine`', '`square`', '`sawtooth`', '`triangle`' 和 '`custom`'，默认值是'sine'。

`detune`

音高微调值（cents）可以对给定的频率值进行偏移。默认值是 0.

`frequency`

周期性波形的频率 (in hertz)。默认值是 440.

`periodicWave`

任意的周期性波形，通过一个 `PeriodicWave` 对象描述。

规范
--

| Specification |
| --- |
| Web Audio API # dom-oscillatornode-oscillatornode |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


CSSImportRule：layerName 属性 - Web API 接口参考

CSSImportRule：layerName 属性
==========================

Baseline 2022
-------------

Newly availableSince March 2022, this feature works across the latest devices and browser versions. This feature might not work in older devices or browsers.

* Learn more
* See full compatibility
* Report feedback
`CSSImportRule` (en-US) 接口的 **`layerName`** 只读属性返回由 `@import` at 规则创建的层叠层的名称。

如果创建的层是匿名的，则字符串为空（`""`），如果没有创建层，则为 `null` 对象。

值
-

一个字符串，可以为空，或者是 `null` 对象。

示例
--

该文档的单个样式表包含三个 `@import` 规则。第一个声明将样式表导入到一个具名层。第二个声明将样式表导入到一个匿名层。第三个声明在没有层声明的情况下导入一个样式表。

`layerName` 属性返回与导入的样式表关联的层的名称。

```css
@import url("style1.css") layer(layer-1);
@import url("style2.css") layer;
@import url("style3.css");
```

```js
const myRules = document.styleSheets[0].cssRules;
console.log(myRules[0].layerName); // 返回 `"layer-1"`
console.log(myRules[1].layerName); // 返回 `""`（匿名层）
console.log(myRules[2].layerName); // 返回 `null`
```

规范
--

| Specification |
| --- |
| CSS Object Model (CSSOM) # dom-cssimportrule-layername |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* 学习区：层叠层
* `@import` 和 `@layer`


WebGL 相关常量 - Web API 接口参考

WebGL 相关常量
==========

WebGL API 提供了一些常量，这些常量常作为参数传入函数调用，或常作为函数的返回值。所有这些常量都是 `GLenum` (en-US) 类型。

标准 WebGL 常量挂载在 WebGL 的两个渲染上下文环境（`WebGLRenderingContext` 和`WebGL2RenderingContext`）中，因此，以形如`gl.CONSTANT_NAME`的形式使用 WebGL 常量：

```js
var canvas = document.getElementById("myCanvas");
var gl = canvas.getContext("webgl");

gl.getParameter(gl.LINE\_WIDTH);
```

其中一些常量也由 WebGL 扩展 提供，如下方提供的 清单：

```js
var debugInfo = gl.getExtension("WEBGL\_debug\_renderer\_info");
var vendor = gl.getParameter(debugInfo.UNMASKED\_VENDOR\_WEBGL);
```

WebGL tutorial 中有更多关于 WebGL 的信息，示例和如何开始 WebGL 编程的其他资源。

常量表
---

* 标准 WebGL 1 常量
* 标准 WebGL 2 常量
* WebGL 扩展常量
标准 WebGL 1 常量
-------------

这些常量定义在 `WebGLRenderingContext` 接口中。

### 清除缓存

常量传入 `WebGLRenderingContext.clear()` 作为清除缓冲区掩码（buffer masks）。

| 常量名称 | 值 | 说明 |
| --- | --- | --- |
| `DEPTH_BUFFER_BIT` | 0x00000100 | 传递给 `clear` 来清除深度缓冲区。 |
| `STENCIL_BUFFER_BIT` | 0x00000400 | 传递给 `clear` 来清除当前模板缓冲区。 |
| `COLOR_BUFFER_BIT` | 0x00004000 | 传递给 `clear` 来清除颜色缓冲区。 |

### 指定渲染图元 Rendering primitives

传递给 `WebGLRenderingContext.drawElements()` 或`WebGLRenderingContext.drawArrays()` 的常量来指定要以何种原始类型渲染。

| 常量名称 | 值 | 说明 |
| --- | --- | --- |
| `POINTS` | 0x0000 | 传递给 `drawElements` 或`drawArrays` 画点。 |
| `LINES` | 0x0001 | 传递给 `drawElements` 或`drawArrays` 画线段。每个顶点链接到它的下一个顶点。每两点画一条线段。 |
| `LINE_LOOP` | 0x0002 | 传递给 `drawElements` 或`drawArrays` 画回路。每两个点被当作是一条独立的线段。线段首尾相连。 |
| `LINE_STRIP` | 0x0003 | 传递给 `drawElements` 或`drawArrays` 画一个从第一个顶点到最后一个顶点绘制一组相连的线段。 |
| `TRIANGLES` | 0x0004 | 传递给`drawElements` 或`drawArrays`画三角形。每三个点创建一个独立的三角形。 |
| `TRIANGLE_STRIP` | 0x0005 | 传递给 `drawElements` 或 `drawArrays` 画一组相连的三角形带。 |
| `TRIANGLE_FAN` | 0x0006 | 传递给 `drawElements` 或`drawArrays` 画一组连接的三角形。以第一个点做原点，每个顶点都连着它的前一个点和第一个顶点（类似风扇）。 |

### 混合模式

传递给 `WebGLRenderingContext.blendFunc()` 或`WebGLRenderingContext.blendFuncSeparate()` (en-US) 的常量来指定混合模式 (同时用于或分别用于 RBG 和 alpha).

| 常量名称 | 值 | 说明 |
| --- | --- | --- |
| `ZERO` | 0 | 传递给`blendFunc` 或 `blendFuncSeparate` 以关闭分量。 |
| `ONE` | 1 | 传递给 `blendFunc` 或 `blendFuncSeparate` 以打开分量。 |
| `SRC_COLOR` | 0x0300 | 传递给 `blendFunc` 或 `blendFuncSeparate` 以将分量乘以源元素颜色分量。 |
| `ONE_MINUS_SRC_COLOR` | 0x0301 | 传递给 `blendFunc` 或 `blendFuncSeparate` 以将分量乘以 1 减去源颜色分量。 |
| `SRC_ALPHA` | 0x0302 | 传递给 `blendFunc` 或 `blendFuncSeparate` 以将分量乘以源颜色的 alpha 值。 |
| `ONE_MINUS_SRC_ALPHA` | 0x0303 | 传递给 `blendFunc` 或 `blendFuncSeparate` 以将分量乘以一个源颜色的 alpha 值。 |
| `DST_ALPHA` | 0x0304 | 传递给 `blendFunc` 或 `blendFuncSeparate` 以将分量乘以目标颜色的 alpha 值。 |
| `ONE_MINUS_DST_ALPHA` | 0x0305 | 传递给 `blendFunc` 或 `blendFuncSeparate` 以将分量乘以 1 减去目标颜色的 alpha 值。 |
| `DST_COLOR` | 0x0306 | 传递给 `blendFunc` 或 `blendFuncSeparate` 以将分量乘以目标颜色分量。 |
| `ONE_MINUS_DST_COLOR` | 0x0307 | 传递给 `blendFunc` 或 `blendFuncSeparate` 以将分量乘以 1 减去目标颜色分量。 |
| `SRC_ALPHA_SATURATE` | 0x0308 | 传递给 `blendFunc` 或 `blendFuncSeparate` 以将分量乘以源颜色 alpha 与目标颜色 alpha 中的最小值。 |
| `CONSTANT_COLOR` | 0x8001 | 传递给 `blendFunc` 或 `blendFuncSeparate` 以指定常量颜色的混合函数。 |
| `ONE_MINUS_CONSTANT_COLOR` | 0x8002 | 传递给 `blendFunc` 或 `blendFuncSeparate` 以指定 1 减去常量颜色的混合函数。 |
| `CONSTANT_ALPHA` | 0x8003 | 传递给 `blendFunc` 或 `blendFuncSeparate` 以指定常量 alpha 混合函数。 |
| `ONE_MINUS_CONSTANT_ALPHA` | 0x8004 | 传递给 `blendFunc` 或 `blendFuncSeparate` 以指定 1 减去一个常量 alpha 的混合函数。 |

### 混合方程

传递给 `WebGLRenderingContext.blendEquation()` 或 `WebGLRenderingContext.blendEquationSeparate()` (en-US) 的常量，以控制混合的计算方式（同时用于或分别用于 RBG 和 alpha）。

| 常量名称 | 值 | 说明 |
| --- | --- | --- |
| `FUNC_ADD` | 0x8006 | 传递给 `blendEquation` 或 `blendEquationSeparate` 来设置加法混合函数。 |
| `FUNC_SUBSTRACT` | 0x800A | 传递给 `blendEquation` 或 `blendEquationSeparate` 来指定减法混合函数（源 - 目标） |
| `FUNC_REVERSE_SUBTRACT` | 0x800B | 传递给 `blendEquation` 或 `blendEquationSeparate` 指定反向减法函数（目标 - 源） |

### 获取 GL 参数信息

传递给 `WebGLRenderingContext.getParameter()` 的常量，用以指定要返回的信息。

| 常量名称 | 值 | 说明 |
| --- | --- | --- |
| `BLEND_EQUATION` | 0x8009 | 传递给 `getParameter` 以获取当前的 RGB 混合函数。 |
| `BLEND_EQUATION_RGB` | 0x8009 | 传递给 `getParameter` 以获取当前的 RGB 混合函数。与 BLEND\_EQUATION 相同。 |
| `BLEND_EQUATION_ALPHA` | 0x883D | 传递给 `getParameter` 以获取当前的 alpha 函数。与 BLEND\_EQUATION 相同。 |
| `BLEND_DST_RGB` | 0x80C8 | 传递给 `getParameter` 以获取当前的目标 RGB 混合函数。 |
| `BLEND_SRC_RGB` | 0x80C9 | 传递给 `getParameter` 以获取当前的源 RGB 混合函数。 |
| `BLEND_DST_ALPHA` | 0x80CA | 传递给 `getParameter` 以获取当前目标的 alpha 混合函数。 |
| `BLEND_SRC_ALPHA` | 0x80CB | 传递给 `getParameter` 以获取当前的源 alpha 混合函数。 |
| `BLEND_COLOR` | 0x8005 | 传递给 `getParameter` 以返回当前的混合颜色。 |
| `ARRAY_BUFFER_BINDING` | 0x8894 | 传递给 `getParameter` 获取数组缓冲区绑定。 |
| `ELEMENT_ARRAY_BUFFER_BINDING` | 0x8895 | 传递给 `getParameter` 获取当前元素数组缓冲区。 |
| `LINE_WIDTH` | 0x0B21 | 传递给 `getParameter` 获取当前的 `lineWidth` (由 `lineWidth` 方法设置)。 |
| `ALIASED_POINT_SIZE_RANGE` | 0x846D | 传递给 `getParameter` 获取使用 `gl.POINTS` 绘制的点的大小。 |
| `ALIASED_LINE_WIDTH_RANGE` | 0x846E | 传递给 `getParameter` 得到一条线的可用宽度范围。返回一个长度为 2 的数组。其中低值为 0，高值为 1。 |
| `CULL_FACE_MODE` | 0x0B45 | 传递给 `getParameter` 获取当前的`cullFace` 值。应该返回 `FRONT`, `BACK`, 或 `FRONT_AND_BACK`。 |
| `FRONT_FACE` | 0x0B46 | 传递给 `getParameter` 以确定当前的 `frontFace` 值。应该 `CW` 或 `CCW`。 |
| `DEPTH_RANGE` | 0x0B70 | 传递给 `getParameter` 返回长度为 2 的浮点数数组，以表示当前深度范围。 |
| `DEPTH_WRITEMASK` | 0x0B72 | 传递给 `getParameter` 确定是否启用深度缓冲区写入操作。 |
| `DEPTH_CLEAR_VALUE` | 0x0B73 | 传递给 `getParameter` 确定当前的深度清除值。 |
| `DEPTH_FUNC` | 0x0B74 | 传递给 `getParameter` 获取当前的深度函数。返回 `NEVER`, `ALWAYS`, `LESS`, `EQUAL`, `LEQUAL`, `GREATER`, `GEQUAL`, 或 `NOTEQUAL`。 |
| `STENCIL_CLEAR_VALUE` | 0x0B91 | 传递给 `getParameter` 获取将消除的模板值。 |
| `STENCIL_FUNC` | 0x0B92 | 传递给 `getParameter` 获取当前的模板函数。返回 `NEVER`, `ALWAYS`, `LESS`, `EQUAL`, `LEQUAL`, `GREATER`, `GEQUAL`, 或 `NOTEQUAL`。 |
| `STENCIL_FAIL` | 0x0B94 | 传递给 `getParameter` 获取当前模板的失效函数。应该返回 `KEEP`, `REPLACE`, `INCR`, `DECR`, `INVERT`, `INCR_WRAP`, 或 `DECR_WRAP`。 |
| `STENCIL_PASS_DEPTH_FAIL` | 0x0B95 | 如果深度缓冲区测试失败，则传递给 `getParameter` 以获取当前模板失败函数。应该返回 `KEEP`, `REPLACE`, `INCR`, `DECR`, `INVERT`, `INCR_WRAP`, 或 `DECR_WRAP`。 |
| `STENCIL_PASS_DEPTH_PASS` | 0x0B96 | 如果深度缓冲区测试通过，则传递给 `getParameter` 以获取当前模板失败函数。应该返回 `KEEP`, `REPLACE`, `INCR`, `DECR`, `INVERT`, `INCR_WRAP`, 或 `DECR_WRAP`。 |
| `STENCIL_REF` | 0x0B97 | 传递给 `getParameter` 获取用于模板测试的参考值。 |
| `STENCIL_VALUE_MASK` | 0x0B93 |  |
| `STENCIL_WRITEMASK` | 0x0B98 |  |
| `STENCIL_BACK_FUNC` | 0x8800 |  |
| `STENCIL_BACK_FAIL` | 0x8801 |  |
| `STENCIL_BACK_PASS_DEPTH_FAIL` | 0x8802 |  |
| `STENCIL_BACK_PASS_DEPTH_PASS` | 0x8803 |  |
| `STENCIL_BACK_REF` | 0x8CA3 |  |
| `STENCIL_BACK_VALUE_MASK` | 0x8CA4 |  |
| `STENCIL_BACK_WRITEMASK` | 0x8CA5 |  |
| `VIEWPORT` | 0x0BA2 | 返回带有当前视口尺寸的四个元素的 `Int32Array` |
| `SCISSOR_BOX` | 0x0C10 | 返回带有当前裁剪盒子尺寸的四个元素的 `Int32Array` 。 |
| `COLOR_CLEAR_VALUE` | 0x0C22 |  |
| `COLOR_WRITEMASK` | 0x0C23 |  |
| `UNPACK_ALIGNMENT` | 0x0CF5 |  |
| `PACK_ALIGNMENT` | 0x0D05 |  |
| `MAX_TEXTURE_SIZE` | 0x0D33 |  |
| `MAX_VIEWPORT_DIMS` | 0x0D3A |  |
| `SUBPIXEL_BITS` | 0x0D50 |  |
| `RED_BITS` | 0x0D52 |  |
| `GREEN_BITS` | 0x0D53 |  |
| `BLUE_BITS` | 0x0D54 |  |
| `ALPHA_BITS` | 0x0D55 |  |
| `DEPTH_BITS` | 0x0D56 |  |
| `STENCIL_BITS` | 0x0D57 |  |
| `POLYGON_OFFSET_UNITS` | 0x2A00 |  |
| `POLYGON_OFFSET_FACTOR` | 0x8038 |  |
| `TEXTURE_BINDING_2D` | 0x8069 |  |
| `SAMPLE_BUFFERS` | 0x80A8 |  |
| `SAMPLES` | 0x80A9 |  |
| `SAMPLE_COVERAGE_VALUE` | 0x80AA |  |
| `SAMPLE_COVERAGE_INVERT` | 0x80AB |  |
| `COMPRESSED_TEXTURE_FORMATS` | 0x86A3 |  |
| `VENDOR` | 0x1F00 |  |
| `RENDERER` | 0x1F01 |  |
| `VERSION` | 0x1F02 |  |
| `IMPLEMENTATION_COLOR_READ_TYPE` | 0x8B9A |  |
| `IMPLEMENTATION_COLOR_READ_FORMAT` | 0x8B9B |  |
| `BROWSER_DEFAULT_WEBGL` | 0x9244 |  |

### Buffers

传递给`WebGLRenderingContext.bufferData()`, `WebGLRenderingContext.bufferSubData()` (en-US), `WebGLRenderingContext.bindBuffer()`, or `WebGLRenderingContext.getBufferParameter()` (en-US) 的变量。

| 常量名称 | 值 | 说明 |
| --- | --- | --- |
| `STATIC_DRAW` | 0x88E4 | Passed to `bufferData` as a hint about whether the contents of the buffer are likely to be used often and not change often. |
| `STREAM_DRAW` | 0x88E0 | Passed to `bufferData` as a hint about whether the contents of the buffer are likely to not be used often. |
| `DYNAMIC_DRAW` | 0x88E8 | Passed to `bufferData` as a hint about whether the contents of the buffer are likely to be used often and change often. |
| `ARRAY_BUFFER` | 0x8892 | Passed to `bindBuffer` or `bufferData` to specify the type of buffer being used. |
| `ELEMENT_ARRAY_BUFFER` | 0x8893 | Passed to `bindBuffer` or `bufferData` to specify the type of buffer being used. |
| `BUFFER_SIZE` | 0x8764 | Passed to `getBufferParameter` to get a buffer's size. |
| `BUFFER_USAGE` | 0x8765 | Passed to `getBufferParameter` to get the hint for the buffer passed in when it was created. |

### Vertex attributes

Constants passed to `WebGLRenderingContext.getVertexAttrib()` (en-US).

| 常量名称 | 值 | 说明 |
| --- | --- | --- |
| `CURRENT_VERTEX_ATTRIB` | 0x8626 | Passed to `getVertexAttrib` to read back the current vertex attribute. |
| `VERTEX_ATTRIB_ARRAY_ENABLED` | 0x8622 |  |
| `VERTEX_ATTRIB_ARRAY_SIZE` | 0x8623 |  |
| `VERTEX_ATTRIB_ARRAY_STRIDE` | 0x8624 |  |
| `VERTEX_ATTRIB_ARRAY_TYPE` | 0x8625 |  |
| `VERTEX_ATTRIB_ARRAY_NORMALIZED` | 0x886A |  |
| `VERTEX_ATTRIB_ARRAY_POINTER` | 0x8645 |  |
| `VERTEX_ATTRIB_ARRAY_BUFFER_BINDING` | 0x889F |  |

### Culling

Constants passed to `WebGLRenderingContext.cullFace()`.

| 常量名称 | 值 | 说明 |
| --- | --- | --- |
| `CULL_FACE` | 0x0B44 | Passed to `enable`/`disable` to turn on/off culling. Can also be used with `getParameter` to find the current culling method. |
| `FRONT` | 0x0404 | Passed to `cullFace` to specify that only front faces should be drawn. |
| `BACK` | 0x0405 | Passed to `cullFace` to specify that only back faces should be drawn. |
| `FRONT_AND_BACK` | 0x0408 | Passed to `cullFace` to specify that front and back faces should be drawn. |

### Enabling and disabling

Constants passed to `WebGLRenderingContext.enable()` or `WebGLRenderingContext.disable()` (en-US).

| 常量名称 | 值 | 说明 |
| --- | --- | --- |
| `BLEND` | 0x0BE2 | Passed to `enable`/`disable` to turn on/off blending. Can also be used with `getParameter` to find the current blending method. |
| `DEPTH_TEST` | 0x0B71 | 通过 `enable`/`disable` 来打开/关闭深度测试。也可以使用 `getParameter` 来查询深度测试。LEQUAL |
| `DITHER` | 0x0BD0 | Passed to `enable`/`disable` to turn on/off dithering. Can also be used with `getParameter` to find the current dithering method. |
| `POLYGON_OFFSET_FILL` | 0x8037 | Passed to `enable`/`disable` to turn on/off the polygon offset. Useful for rendering hidden-line images, decals, and or solids with highlighted edges. Can also be used with `getParameter` to query the scissor test. |
| `SAMPLE_ALPHA_TO_COVERAGE` | 0x809E | Passed to `enable`/`disable` to turn on/off the alpha to coverage. Used in multi-sampling alpha channels. |
| `SAMPLE_COVERAGE` | 0x80A0 | Passed to `enable`/`disable` to turn on/off the sample coverage. Used in multi-sampling. |
| `SCISSOR_TEST` | 0x0C11 | Passed to `enable`/`disable` to turn on/off the scissor test. Can also be used with `getParameter` to query the scissor test. |
| `STENCIL_TEST` | 0x0B90 | Passed to `enable`/`disable` to turn on/off the stencil test. Can also be used with `getParameter` to query the stencil test. |
|  |  |  |

### Errors

Constants returned from `WebGLRenderingContext.getError()` (en-US).

| 常量名称 | 值 | 说明 |
| --- | --- | --- |
| `NO_ERROR` | 0 | Returned from `getError`. |
| `INVALID_ENUM` | 0x0500 | Returned from `getError`. |
| `INVALID_VALUE` | 0x0501 | Returned from `getError`. |
| `INVALID_OPERATION` | 0x0502 | Returned from `getError`. |
| `OUT_OF_MEMORY` | 0x0505 | Returned from `getError`. |
| `CONTEXT_LOST_WEBGL` | 0x9242 | Returned from `getError`. |

### Front face directions

Constants passed to `WebGLRenderingContext.frontFace()` (en-US).

| 常量名称 | 值 | 说明 |
| --- | --- | --- |
| `CW` | 0x0900 | Passed to `frontFace` to specify the front face of a polygon is drawn in the clockwise direction |
| `CCW` | 0x0901 | Passed to `frontFace` to specify the front face of a polygon is drawn in the counter clockwise direction |

### Hints

Constants passed to `WebGLRenderingContext.hint()` (en-US)

| 常量名称 | 值 | 说明 |
| --- | --- | --- |
| `DONT_CARE` | 0x1100 | There is no preference for this behavior. |
| `FASTEST` | 0x1101 | The most efficient behavior should be used. |
| `NICEST` | 0x1102 | The most correct or the highest quality option should be used. |
| `GENERATE_MIPMAP_HINT` | 0x8192 | Hint for the quality of filtering when generating mipmap images with `WebGLRenderingContext.generateMipmap()` (en-US). |

### Data types

| 常量名称 | 值 | 说明 |
| --- | --- | --- |
| `BYTE` | 0x1400 |  |
| `UNSIGNED_BYTE` | 0x1401 |  |
| `SHORT` | 0x1402 |  |
| `UNSIGNED_SHORT` | 0x1403 |  |
| `INT` | 0x1404 |  |
| `UNSIGNED_INT` | 0x1405 |  |
| `FLOAT` | 0x1406 |  |

### Pixel formats

| 常量名称 | 值 | 说明 |
| --- | --- | --- |
| `DEPTH_COMPONENT` | 0x1902 |  |
| `ALPHA` | 0x1906 |  |
| `RGB` | 0x1907 |  |
| `RGBA` | 0x1908 |  |
| `LUMINANCE` | 0x1909 |  |
| `LUMINANCE_ALPHA` | 0x190A |  |

### Pixel types

| 常量名称 | 值 | 说明 |
| --- | --- | --- |
| `UNSIGNED_BYTE` | 0x1401 |  |
| `UNSIGNED_SHORT_4_4_4_4` | 0x8033 |  |
| `UNSIGNED_SHORT_5_5_5_1` | 0x8034 |  |
| `UNSIGNED_SHORT_5_6_5` | 0x8363 |  |

### Shaders

Constants passed to `WebGLRenderingContext.createShader()` or `WebGLRenderingContext.getShaderParameter()`

| 常量名称 | 值 | 说明 |
| --- | --- | --- |
| `FRAGMENT_SHADER` | 0x8B30 | Passed to `createShader` to define a fragment shader. |
| `VERTEX_SHADER` | 0x8B31 | Passed to `createShader` to define a vertex shader |
| `COMPILE_STATUS` | 0x8B81 | Passed to `getShaderParamter` to get the status of the compilation. Returns false if the shader was not compiled. You can then query `getShaderInfoLog` to find the exact error |
| `DELETE_STATUS` | 0x8B80 | Passed to `getShaderParamter` to determine if a shader was deleted via `deleteShader`. Returns true if it was, false otherwise. |
| `LINK_STATUS` | 0x8B82 | Passed to `getProgramParameter` after calling `linkProgram` to determine if a program was linked correctly. Returns false if there were errors. Use `getProgramInfoLog` to find the exact error. |
| `VALIDATE_STATUS` | 0x8B83 | Passed to `getProgramParameter` after calling `validateProgram` to determine if it is valid. Returns false if errors were found. |
| `ATTACHED_SHADERS` | 0x8B85 | Passed to `getProgramParameter` after calling `attachShader` to determine if the shader was attached correctly. Returns false if errors occurred. |
| `ACTIVE_ATTRIBUTES` | 0x8B89 | Passed to `getProgramParameter` to get the number of attributes active in a program. |
| `ACTIVE_UNIFORMS` | 0x8B86 | Passed to `getProgramParamter` to get the number of uniforms active in a program. |
| `MAX_VERTEX_ATTRIBS` | 0x8869 |  |
| `MAX_VERTEX_UNIFORM_VECTORS` | 0x8DFB |  |
| `MAX_VARYING_VECTORS` | 0x8DFC |  |
| `MAX_COMBINED_TEXTURE_IMAGE_UNITS` | 0x8B4D |  |
| `MAX_VERTEX_TEXTURE_IMAGE_UNITS` | 0x8B4C |  |
| `MAX_TEXTURE_IMAGE_UNITS` | 0x8872 | Implementation dependent number of maximum texture units. At least 8. |
| `MAX_FRAGMENT_UNIFORM_VECTORS` | 0x8DFD |  |
| `SHADER_TYPE` | 0x8B4F |  |
| `SHADING_LANGUAGE_VERSION` | 0x8B8C |  |
| `CURRENT_PROGRAM` | 0x8B8D |  |

### Depth or stencil tests

Constants passed to `WebGLRenderingContext.depthFunc()` or `WebGLRenderingContext.stencilFunc()` (en-US).

| Constant name | Value | Description |
| --- | --- | --- |
| `NEVER` | 0x0200 | Passed to `depthFunction` or `stencilFunction` to specify depth or stencil tests will never pass. i.e. Nothing will be drawn. |
| `ALWAYS` | 0x0207 | Passed to `depthFunction` or `stencilFunction` to specify depth or stencil tests will always pass. i.e. Pixels will be drawn in the order they are drawn. |
| `LESS` | 0x0201 | Passed to `depthFunction` or `stencilFunction` to specify depth or stencil tests will pass if the new depth value is less than the stored value. |
| `EQUAL` | 0x0202 | Passed to `depthFunction` or `stencilFunction` to specify depth or stencil tests will pass if the new depth value is equals to the stored value. |
| `LEQUAL` | 0x0203 | 如果新深度值小于或等于存储值，则通过 `depthFunction` 或 `stencilFunction` 指定深度或模板测试。 |
| `GREATER` | 0x0204 | Passed to `depthFunction` or `stencilFunction` to specify depth or stencil tests will pass if the new depth value is greater than the stored value. |
| `GEQUAL` | 0x0206 | Passed to `depthFunction` or `stencilFunction` to specify depth or stencil tests will pass if the new depth value is greater than or equal to the stored value. |
| `NOTEQUAL` | 0x0205 | Passed to `depthFunction` or `stencilFunction` to specify depth or stencil tests will pass if the new depth value is not equal to the stored value. |

### Stencil actions

Constants passed to `WebGLRenderingContext.stencilOp()` (en-US).

| Constant name | Value | Description |
| --- | --- | --- |
| `KEEP` | 0x1E00 |  |
| `REPLACE` | 0x1E01 |  |
| `INCR` | 0x1E02 |  |
| `DECR` | 0x1E03 |  |
| `INVERT` | 0x150A |  |
| `INCR_WRAP` | 0x8507 |  |
| `DECR_WRAP` | 0x8508 |  |

### Textures

Constants passed to `WebGLRenderingContext.texParameteri()` (en-US), `WebGLRenderingContext.texParameterf()` (en-US), `WebGLRenderingContext.bindTexture()`, `WebGLRenderingContext.texImage2D()`, and others.

| Constant name | Value | Description |
| --- | --- | --- |
| `NEAREST` | 0x2600 |  |
| `LINEAR` | 0x2601 |  |
| `NEAREST_MIPMAP_NEAREST` | 0x2700 |  |
| `LINEAR_MIPMAP_NEAREST` | 0x2701 |  |
| `NEAREST_MIPMAP_LINEAR` | 0x2702 |  |
| `LINEAR_MIPMAP_LINEAR` | 0x2703 |  |
| `TEXTURE_MAG_FILTER` | 0x2800 |  |
| `TEXTURE_MIN_FILTER` | 0x2801 |  |
| `TEXTURE_WRAP_S` | 0x2802 |  |
| `TEXTURE_WRAP_T` | 0x2803 |  |
| `TEXTURE_2D` | 0x0DE1 |  |
| `TEXTURE` | 0x1702 |  |
| `TEXTURE_CUBE_MAP` | 0x8513 |  |
| `TEXTURE_BINDING_CUBE_MAP` | 0x8514 |  |
| `TEXTURE_CUBE_MAP_POSITIVE_X` | 0x8515 |  |
| `TEXTURE_CUBE_MAP_NEGATIVE_X` | 0x8516 |  |
| `TEXTURE_CUBE_MAP_POSITIVE_Y` | 0x8517 |  |
| `TEXTURE_CUBE_MAP_NEGATIVE_Y` | 0x8518 |  |
| `TEXTURE_CUBE_MAP_POSITIVE_Z` | 0x8519 |  |
| `TEXTURE_CUBE_MAP_NEGATIVE_Z` | 0x851A |  |
| `MAX_CUBE_MAP_TEXTURE_SIZE` | 0x851C |  |
| `TEXTURE0 - 31` | 0x84C0 - 0x84DF | A texture unit. |
| `ACTIVE_TEXTURE` | 0x84E0 | The current active texture unit. |
| `REPEAT` | 0x2901 |  |
| `CLAMP_TO_EDGE` | 0x812F |  |
| `MIRRORED_REPEAT` | 0x8370 |  |

### Uniform types

| Constant name | Value | Description |
| --- | --- | --- |
| `FLOAT_VEC2` | 0x8B50 |  |
| `FLOAT_VEC3` | 0x8B51 |  |
| `FLOAT_VEC4` | 0x8B52 |  |
| `INT_VEC2` | 0x8B53 |  |
| `INT_VEC3` | 0x8B54 |  |
| `INT_VEC4` | 0x8B55 |  |
| `BOOL` | 0x8B56 |  |
| `BOOL_VEC2` | 0x8B57 |  |
| `BOOL_VEC3` | 0x8B58 |  |
| `BOOL_VEC4` | 0x8B59 |  |
| `FLOAT_MAT2` | 0x8B5A |  |
| `FLOAT_MAT3` | 0x8B5B |  |
| `FLOAT_MAT4` | 0x8B5C |  |
| `SAMPLER_2D` | 0x8B5E |  |
| `SAMPLER_CUBE` | 0x8B60 |  |

### Shader precision-specified types

| Constant name | Value | Description |
| --- | --- | --- |
| `LOW_FLOAT` | 0x8DF0 |  |
| `MEDIUM_FLOAT` | 0x8DF1 |  |
| `HIGH_FLOAT` | 0x8DF2 |  |
| `LOW_INT` | 0x8DF3 |  |
| `MEDIUM_INT` | 0x8DF4 |  |
| `HIGH_INT` | 0x8DF5 |  |

### Framebuffers and renderbuffers

| Constant name | Value | Description |
| --- | --- | --- |
| `FRAMEBUFFER` | 0x8D40 |  |
| `RENDERBUFFER` | 0x8D41 |  |
| `RGBA4` | 0x8056 |  |
| `RGB5_A1` | 0x8057 |  |
| `RGB565` | 0x8D62 |  |
| `DEPTH_COMPONENT16` | 0x81A5 |  |
| `STENCIL_INDEX` | 0x1901 |  |
| `STENCIL_INDEX8` | 0x8D48 |  |
| `DEPTH_STENCIL` | 0x84F9 |  |
| `RENDERBUFFER_WIDTH` | 0x8D42 |  |
| `RENDERBUFFER_HEIGHT` | 0x8D43 |  |
| `RENDERBUFFER_INTERNAL_FORMAT` | 0x8D44 |  |
| `RENDERBUFFER_RED_SIZE` | 0x8D50 |  |
| `RENDERBUFFER_GREEN_SIZE` | 0x8D51 |  |
| `RENDERBUFFER_BLUE_SIZE` | 0x8D52 |  |
| `RENDERBUFFER_ALPHA_SIZE` | 0x8D53 |  |
| `RENDERBUFFER_DEPTH_SIZE` | 0x8D54 |  |
| `RENDERBUFFER_STENCIL_SIZE` | 0x8D55 |  |
| `FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE` | 0x8CD0 |  |
| `FRAMEBUFFER_ATTACHMENT_OBJECT_NAME` | 0x8CD1 |  |
| `FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL` | 0x8CD2 |  |
| `FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE` | 0x8CD3 |  |
| `COLOR_ATTACHMENT0` | 0x8CE0 |  |
| `DEPTH_ATTACHMENT` | 0x8D00 |  |
| `STENCIL_ATTACHMENT` | 0x8D20 |  |
| `DEPTH_STENCIL_ATTACHMENT` | 0x821A |  |
| `NONE` | 0 |  |
| `FRAMEBUFFER_COMPLETE` | 0x8CD5 |  |
| `FRAMEBUFFER_INCOMPLETE_ATTACHMENT` | 0x8CD6 |  |
| `FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT` | 0x8CD7 |  |
| `FRAMEBUFFER_INCOMPLETE_DIMENSIONS` | 0x8CD9 |  |
| `FRAMEBUFFER_UNSUPPORTED` | 0x8CDD |  |
| `FRAMEBUFFER_BINDING` | 0x8CA6 |  |
| `RENDERBUFFER_BINDING` | 0x8CA7 |  |
| `MAX_RENDERBUFFER_SIZE` | 0x84E8 |  |
| `INVALID_FRAMEBUFFER_OPERATION` | 0x0506 |  |

### Pixel storage modes

Constants passed to `WebGLRenderingContext.pixelStorei()`.

| Constant name | Value | Description |
| --- | --- | --- |
| `UNPACK_FLIP_Y_WEBGL` | 0x9240 |  |
| `UNPACK_PREMULTIPLY_ALPHA_WEBGL` | 0x9241 |  |
| `UNPACK_COLORSPACE_CONVERSION_WEBGL` | 0x9243 |  |

Additional constants defined WebGL 2
------------------------------------

These constants are defined on the `WebGL2RenderingContext` interface. All WebGL 1 constants are also available in a WebGL 2 context.

### Getting GL parameter information

Constants passed to `WebGLRenderingContext.getParameter()` to specify what information to return.

| Constant name | Value | Description |
| --- | --- | --- |
| `READ_BUFFER` | 0x0C02 |  |
| `UNPACK_ROW_LENGTH` | 0x0CF2 |  |
| `UNPACK_SKIP_ROWS` | 0x0CF3 |  |
| `UNPACK_SKIP_PIXELS` | 0x0CF4 |  |
| `PACK_ROW_LENGTH` | 0x0D02 |  |
| `PACK_SKIP_ROWS` | 0x0D03 |  |
| `PACK_SKIP_PIXELS` | 0x0D04 |  |
| `TEXTURE_BINDING_3D` | 0x806A |  |
| `UNPACK_SKIP_IMAGES` | 0x806D |  |
| `UNPACK_IMAGE_HEIGHT` | 0x806E |  |
| `MAX_3D_TEXTURE_SIZE` | 0x8073 |  |
| `MAX_ELEMENTS_VERTICES` | 0x80E8 |  |
| `MAX_ELEMENTS_INDICES` | 0x80E9 |  |
| `MAX_TEXTURE_LOD_BIAS` | 0x84FD |  |
| `MAX_FRAGMENT_UNIFORM_COMPONENTS` | 0x8B49 |  |
| `MAX_VERTEX_UNIFORM_COMPONENTS` | 0x8B4A |  |
| `MAX_ARRAY_TEXTURE_LAYERS` | 0x88FF |  |
| `MIN_PROGRAM_TEXEL_OFFSET` | 0x8904 |  |
| `MAX_PROGRAM_TEXEL_OFFSET` | 0x8905 |  |
| `MAX_VARYING_COMPONENTS` | 0x8B4B |  |
| `FRAGMENT_SHADER_DERIVATIVE_HINT` | 0x8B8B |  |
| `RASTERIZER_DISCARD` | 0x8C89 |  |
| `VERTEX_ARRAY_BINDING` | 0x85B5 |  |
| `MAX_VERTEX_OUTPUT_COMPONENTS` | 0x9122 |  |
| `MAX_FRAGMENT_INPUT_COMPONENTS` | 0x9125 |  |
| `MAX_SERVER_WAIT_TIMEOUT` | 0x9111 |  |
| `MAX_ELEMENT_INDEX` | 0x8D6B |  |

### Textures

Constants passed to `WebGLRenderingContext.texParameteri()` (en-US), `WebGLRenderingContext.texParameterf()` (en-US), `WebGLRenderingContext.bindTexture()`, `WebGLRenderingContext.texImage2D()`, and others.

| Constant name | Value | Description |
| --- | --- | --- |
| `RED` | 0x1903 |  |
| `RGB8` | 0x8051 |  |
| `RGBA8` | 0x8058 |  |
| `RGB10_A2` | 0x8059 |  |
| `TEXTURES_3D` | 0x806F |  |
| `TEXTURE_WRAP_R` | 0x8072 |  |
| `TEXTURE_MIN_LOD` | 0x813A |  |
| `TEXTURE_MAX_LOD` | 0x813B |  |
| `TEXTURE_BASE_LEVEL` | 0x813C |  |
| `TEXTURE_MAX_LEVEL` | 0x813D |  |
| `TEXTURE_COMPARE_MODE` | 0x884C |  |
| `TEXTURE_COMPARE_FUNC` | 0x884D |  |
| `SRGB` | 0x8C40 |  |
| `SRGB8` | 0x8C41 |  |
| `SRGB8_ALPHA8` | 0x8C43 |  |
| `COMPARE_REF_TO_TEXTURE` | 0x884E |  |
| `RGBA32F` | 0x8814 |  |
| `RGB32F` | 0x8815 |  |
| `RGBA16F` | 0x881A |  |
| `RGB16F` | 0x881B |  |
| `TEXTURE_2D_ARRAY` | 0x8C1A |  |
| `TEXTURE_BINDING_2D_ARRAY` | 0x8C1D |  |
| `R11F_G11F_B10F` | 0x8C3A |  |
| `RGB9_E5` | 0x8C3D |  |
| `RGBA32UI` | 0x8D70 |  |
| `RGB32UI` | 0x8D71 |  |
| `RGBA16UI` | 0x8D76 |  |
| `RGB16UI` | 0x8D77 |  |
| `RGBA8UI` | 0x8D7C |  |
| `RGB8UI` | 0x8D7D |  |
| `RGBA32I` | 0x8D82 |  |
| `RGB32I` | 0x8D83 |  |
| `RGBA16I` | 0x8D88 |  |
| `RGB16I` | 0x8D89 |  |
| `RGBA8I` | 0x8D8E |  |
| `RGB8I` | 0x8D8F |  |
| `RED_INTEGER` | 0x8D94 |  |
| `RGB_INTEGER` | 0x8D98 |  |
| `RGBA_INTEGER` | 0x8D99 |  |
| `R8` | 0x8229 |  |
| `RG8` | 0x822B |  |
| R16F | 0x822D |  |
| R32F | 0x822E |  |
| RG16F | 0x822F |  |
| RG32F | 0x8230 |  |
| R8I | 0x8231 |  |
| R8UI | 0x8232 |  |
| R16I | 0x8233 |  |
| R16UI | 0x8234 |  |
| R32I | 0x8235 |  |
| R32UI | 0x8236 |  |
| RG8I | 0x8237 |  |
| RG8UI | 0x8238 |  |
| RG16I | 0x8239 |  |
| RG16UI | 0x823A |  |
| RG32I | 0x823B |  |
| RG32UI | 0x823C |  |
| R8\_SNORM | 0x8F94 |  |
| RG8\_SNORM | 0x8F95 |  |
| RGB8\_SNORM | 0x8F96 |  |
| RGBA8\_SNORM | 0x8F97 |  |
| `RGB10_A2UI` | 0x906F |  |
| `COMPRESSED_R11_EAC` | 0x9270 |  |
| `COMPRESSED_SIGNED_R11_EAC` | 0x9271 |  |
| `COMPRESSED_RG11_EAC` | 0x9272 |  |
| `COMPRESSED_SIGNED_RG11_EAC` | 0x9273 |  |
| `COMPRESSED_RGB8_ETC2` | 0x9274 |  |
| `COMPRESSED_SRGB8_ETC2` | 0x9275 |  |
| `COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2` | 0x9276 |  |
| `COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC` | 0x9277 |  |
| `COMPRESSED_RGBA8_ETC2_EAC` | 0x9278 |  |
| `COMPRESSED_SRGB8_ALPHA8_ETC2_EAC` | 0x9279 |  |
| `TEXTURE_IMMUTABLE_FORMAT` | 0x912F |  |
| `TEXTURE_IMMUTABLE_LEVELS` | 0x82DF |  |

### Pixel types

| Constant name | Value | Description |
| --- | --- | --- |
| `UNSIGNED_INT_2_10_10_10_REV` | 0x8368 |  |
| `UNSIGNED_INT_10F_11F_11F_REV` | 0x8C3B |  |
| `UNSIGNED_INT_5_9_9_9_REV` | 0x8C3E |  |
| `FLOAT_32_UNSIGNED_INT_24_8_REV` | 0x8DAD |  |
| UNSIGNED\_INT\_24\_8 | 0x84FA |  |
| `HALF_FLOAT` | 0x140B |  |
| `RG` | 0x8227 |  |
| `RG_INTEGER` | 0x8228 |  |
| `INT_2_10_10_10_REV` | 0x8D9F |  |

### Queries

| Constant name | Value | Description |
| --- | --- | --- |
| `CURRENT_QUERY` | 0x8865 |  |
| `QUERY_RESULT` | 0x8866 |  |
| `QUERY_RESULT_AVAILABLE` | 0x8867 |  |
| `ANY_SAMPLES_PASSED` | 0x8C2F |  |
| `ANY_SAMPLES_PASSED_CONSERVATIVE` | 0x8D6A |  |

### Draw buffers

| Constant name | Value | Description |
| --- | --- | --- |
| `MAX_DRAW_BUFFERS` | 0x8824 |  |
| `DRAW_BUFFER0` | 0x8825 |  |
| `DRAW_BUFFER1` | 0x8826 |  |
| `DRAW_BUFFER2` | 0x8827 |  |
| `DRAW_BUFFER3` | 0x8828 |  |
| `DRAW_BUFFER4` | 0x8829 |  |
| `DRAW_BUFFER5` | 0x882A |  |
| `DRAW_BUFFER6` | 0x882B |  |
| `DRAW_BUFFER7` | 0x882C |  |
| `DRAW_BUFFER8` | 0x882D |  |
| `DRAW_BUFFER9` | 0x882E |  |
| `DRAW_BUFFER10` | 0x882F |  |
| `DRAW_BUFFER11` | 0x8830 |  |
| `DRAW_BUFFER12` | 0x8831 |  |
| `DRAW_BUFFER13` | 0x8832 |  |
| `DRAW_BUFFER14` | 0x8833 |  |
| `DRAW_BUFFER15` | 0x8834 |  |
| `MAX_COLOR_ATTACHMENTS` | 0x8CDF |  |
| `COLOR_ATTACHMENT1` | 0x8CE1 |  |
| `COLOR_ATTACHMENT2` | 0x8CE2 |  |
| `COLOR_ATTACHMENT3` | 0x8CE3 |  |
| `COLOR_ATTACHMENT4` | 0x8CE4 |  |
| `COLOR_ATTACHMENT5` | 0x8CE5 |  |
| `COLOR_ATTACHMENT6` | 0x8CE6 |  |
| `COLOR_ATTACHMENT7` | 0x8CE7 |  |
| `COLOR_ATTACHMENT8` | 0x8CE8 |  |
| `COLOR_ATTACHMENT9` | 0x8CE9 |  |
| `COLOR_ATTACHMENT10` | 0x8CEA |  |
| `COLOR_ATTACHMENT11` | 0x8CEB |  |
| `COLOR_ATTACHMENT12` | 0x8CEC |  |
| `COLOR_ATTACHMENT13` | 0x8CED |  |
| `COLOR_ATTACHMENT14` | 0x8CEE |  |
| `COLOR_ATTACHMENT15` | 0x8CEF |  |

### Samplers

| Constant name | Value | Description |
| --- | --- | --- |
| `SAMPLER_3D` | 0x8B5F |  |
| `SAMPLER_2D_SHADOW` | 0x8B62 |  |
| `SAMPLER_2D_ARRAY` | 0x8DC1 |  |
| `SAMPLER_2D_ARRAY_SHADOW` | 0x8DC4 |  |
| `SAMPLER_CUBE_SHADOW` | 0x8DC5 |  |
| `INT_SAMPLER_2D` | 0x8DCA |  |
| `INT_SAMPLER_3D` | 0x8DCB |  |
| `INT_SAMPLER_CUBE` | 0x8DCC |  |
| `INT_SAMPLER_2D_ARRAY` | 0x8DCF |  |
| `UNSIGNED_INT_SAMPLER_2D` | 0x8DD2 |  |
| `UNSIGNED_INT_SAMPLER_3D` | 0x8DD3 |  |
| `UNSIGNED_INT_SAMPLER_CUBE` | 0x8DD4 |  |
| `UNSIGNED_INT_SAMPLER_2D_ARRAY` | 0x8DD7 |  |
| `MAX_SAMPLES` | 0x8D57 |  |
| `SAMPLER_BINDING` | 0x8919 |  |

### Buffers

| Constant name | Value | Description |
| --- | --- | --- |
| `PIXEL_PACK_BUFFER` | 0x88EB |  |
| `PIXEL_UNPACK_BUFFER` | 0x88EC |  |
| `PIXEL_PACK_BUFFER_BINDING` | 0x88ED |  |
| `PIXEL_UNPACK_BUFFER_BINDING` | 0x88EF |  |
| `COPY_READ_BUFFER` | 0x8F36 |  |
| `COPY_WRITE_BUFFER` | 0x8F37 |  |
| `COPY_READ_BUFFER_BINDING` | 0x8F36 |  |
| `COPY_WRITE_BUFFER_BINDING` | 0x8F37 |  |

### Data types

| Constant name | Value | Description |
| --- | --- | --- |
| `FLOAT_MAT2x3` | 0x8B65 |  |
| `FLOAT_MAT2x4` | 0x8B66 |  |
| `FLOAT_MAT3x2` | 0x8B67 |  |
| `FLOAT_MAT3x4` | 0x8B68 |  |
| `FLOAT_MAT4x2` | 0x8B69 |  |
| `FLOAT_MAT4x3` | 0x8B6A |  |
| `UNSIGNED_INT_VEC2` | 0x8DC6 |  |
| `UNSIGNED_INT_VEC3` | 0x8DC7 |  |
| `UNSIGNED_INT_VEC4` | 0x8DC8 |  |
| `UNSIGNED_NORMALIZED` | 0x8C17 |  |
| `SIGNED_NORMALIZED` | 0x8F9C |  |

### Vertex attributes

| Constant name | Value | Description |
| --- | --- | --- |
| `VERTEX_ATTRIB_ARRAY_INTEGER` | 0x88FD |  |
| `VERTEX_ATTRIB_ARRAY_DIVISOR` | 0x88FE |  |

### Transform feedback

| Constant name | Value | Description |
| --- | --- | --- |
| `TRANSFORM_FEEDBACK_BUFFER_MODE` | 0x8C7F |  |
| `MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS` | 0x8C80 |  |
| `TRANSFORM_FEEDBACK_VARYINGS` | 0x8C83 |  |
| `TRANSFORM_FEEDBACK_BUFFER_START` | 0x8C84 |  |
| `TRANSFORM_FEEDBACK_BUFFER_SIZE` | 0x8C85 |  |
| `TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN` | 0x8C88 |  |
| `MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS` | 0x8C8A |  |
| `MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS` | 0x8C8B |  |
| `INTERLEAVED_ATTRIBS` | 0x8C8C |  |
| `SEPARATE_ATTRIBS` | 0x8C8D |  |
| `TRANSFORM_FEEDBACK_BUFFER` | 0x8C8E |  |
| `TRANSFORM_FEEDBACK_BUFFER_BINDING` | 0x8C8F |  |
| `TRANSFORM_FEEDBACK` | 0x8E22 |  |
| `TRANSFORM_FEEDBACK_PAUSED` | 0x8E23 |  |
| `TRANSFORM_FEEDBACK_ACTIVE` | 0x8E24 |  |
| `TRANSFORM_FEEDBACK_BINDING` | 0x8E25 |  |

### Framebuffers and renderbuffers

| Constant name | Value | Description |
| --- | --- | --- |
| `FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING` | 0x8210 |  |
| `FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE` | 0x8211 |  |
| `FRAMEBUFFER_ATTACHMENT_RED_SIZE` | 0x8212 |  |
| `FRAMEBUFFER_ATTACHMENT_GREEN_SIZE` | 0x8213 |  |
| `FRAMEBUFFER_ATTACHMENT_BLUE_SIZE` | 0x8214 |  |
| `FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE` | 0x8215 |  |
| `FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE` | 0x8216 |  |
| `FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE` | 0x8217 |  |
| `FRAMEBUFFER_DEFAULT` | 0x8218 |  |
| `DEPTH_STENCIL_ATTACHMENT` | 0x821A |  |
| `DEPTH_STENCIL` | 0x84F9 |  |
| `DEPTH24_STENCIL8` | 0x88F0 |  |
| `DRAW_FRAMEBUFFER_BINDING` | 0x8CA6 |  |
| `READ_FRAMEBUFFER` | 0x8CA8 |  |
| `DRAW_FRAMEBUFFER` | 0x8CA9 |  |
| `READ_FRAMEBUFFER_BINDING` | 0x8CAA |  |
| `RENDERBUFFER_SAMPLES` | 0x8CAB |  |
| `FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER` | 0x8CD4 |  |
| `FRAMEBUFFER_INCOMPLETE_MULTISAMPLE` | 0x8D56 |  |

### Uniforms

| Constant name | Value | Description |
| --- | --- | --- |
| `UNIFORM_BUFFER` | 0x8A11 |  |
| `UNIFORM_BUFFER_BINDING` | 0x8A28 |  |
| `UNIFORM_BUFFER_START` | 0x8A29 |  |
| `UNIFORM_BUFFER_SIZE` | 0x8A2A |  |
| `MAX_VERTEX_UNIFORM_BLOCKS` | 0x8A2B |  |
| `MAX_FRAGMENT_UNIFORM_BLOCKS` | 0x8A2D |  |
| `MAX_COMBINED_UNIFORM_BLOCKS` | 0x8A2E |  |
| `MAX_UNIFORM_BUFFER_BINDINGS` | 0x8A2F |  |
| `MAX_UNIFORM_BLOCK_SIZE` | 0x8A30 |  |
| `MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS` | 0x8A31 |  |
| `MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS` | 0x8A33 |  |
| `UNIFORM_BUFFER_OFFSET_ALIGNMENT` | 0x8A34 |  |
| `ACTIVE_UNIFORM_BLOCKS` | 0x8A36 |  |
| `UNIFORM_TYPE` | 0x8A37 |  |
| `UNIFORM_SIZE` | 0x8A38 |  |
| `UNIFORM_BLOCK_INDEX` | 0x8A3A |  |
| `UNIFORM_OFFSET` | 0x8A3B |  |
| `UNIFORM_ARRAY_STRIDE` | 0x8A3C |  |
| `UNIFORM_MATRIX_STRIDE` | 0x8A3D |  |
| `UNIFORM_IS_ROW_MAJOR` | 0x8A3E |  |
| `UNIFORM_BLOCK_BINDING` | 0x8A3F |  |
| `UNIFORM_BLOCK_DATA_SIZE` | 0x8A40 |  |
| `UNIFORM_BLOCK_ACTIVE_UNIFORMS` | 0x8A42 |  |
| `UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES` | 0x8A43 |  |
| `UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER` | 0x8A44 |  |
| `UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER` | 0x8A46 |  |

### Sync objects

| Constant name | Value | Description |
| --- | --- | --- |
| `OBJECT_TYPE` | 0x9112 |  |
| `SYNC_CONDITION` | 0x9113 |  |
| `SYNC_STATUS` | 0x9114 |  |
| `SYNC_FLAGS` | 0x9115 |  |
| `SYNC_FENCE` | 0x9116 |  |
| `SYNC_GPU_COMMANDS_COMPLETE` | 0x9117 |  |
| `UNSIGNALED` | 0x9118 |  |
| `SIGNALED` | 0x9119 |  |
| `ALREADY_SIGNALED` | 0x911A |  |
| `TIMEOUT_EXPIRED` | 0x911B |  |
| `CONDITION_SATISFIED` | 0x911C |  |
| `WAIT_FAILED` | 0x911D |  |
| `SYNC_FLUSH_COMMANDS_BIT` | 0x00000001 |  |

### Miscellaneous constants

| Constant name | Value | Description |
| --- | --- | --- |
| `COLOR` | 0x1800 |  |
| DEPTH | 0x1801 |  |
| `STENCIL` | 0x1802 |  |
| `MIN` | 0x8007 |  |
| MAX | 0x8008 |  |
| `DEPTH_COMPONENT24` | 0x81A6 |  |
| `STREAM_READ` | 0x88E1 |  |
| `STREAM_COPY` | 0x88E2 |  |
| `STATIC_READ` | 0x88E5 |  |
| `STATIC_COPY` | 0x88E6 |  |
| `DYNAMIC_READ` | 0x88E9 |  |
| `DYNAMIC_COPY` | 0x88EA |  |
| `DEPTH_COMPONENT32F` | 0x8CAC |  |
| `DEPTH32F_STENCIL8` | 0x8CAD |  |
| `INVALID_INDEX` | 0xFFFFFFFF |  |
| `TIMEOUT_IGNORED` | -1 |  |
| `MAX_CLIENT_WAIT_TIMEOUT_WEBGL` | 0x9247 |  |

Constants defined in WebGL extensions
-------------------------------------

### `ANGLE_instanced_arrays`

| Constant name | Value | Description |
| --- | --- | --- |
| `VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE` | 0x88FE | Describes the frequency divisor used for instanced rendering. |

### `WEBGL_debug_renderer_info` (en-US)

| Constant name | Value | Description |
| --- | --- | --- |
| `UNMASKED_VENDOR_WEBGL` | 0x9245 | Passed to `getParameter` to get the vendor string of the graphics driver. |
| `UNMASKED_RENDERER_WEBGL` | 0x9246 | Passed to `getParameter` to get the renderer string of the graphics driver. |

### `EXT_texture_filter_anisotropic` (en-US)

| Constant name | Value | Description |
| --- | --- | --- |
| `MAX_TEXTURE_MAX_ANISOTROPY_EXT` | 0x84FF | Returns the maximum available anisotropy. |
| `TEXTURE_MAX_ANISOTROPY_EXT` | 0x84FE | Passed to `texParameter` to set the desired maximum anisotropy for a texture. |

### `WEBGL_compressed_texture_s3tc` (en-US)

| Constant name | Value | Description |
| --- | --- | --- |
| `COMPRESSED_RGB_S3TC_DXT1_EXT` | 0x83F0 | A DXT1-compressed image in an RGB image format. |
| `COMPRESSED_RGBA_S3TC_DXT1_EXT` | 0x83F1 | A DXT1-compressed image in an RGB image format with a simple on/off alpha value. |
| `COMPRESSED_RGBA_S3TC_DXT3_EXT` | 0x83F2 | A DXT3-compressed image in an RGBA image format. Compared to a 32-bit RGBA texture, it offers 4:1 compression. |
| `COMPRESSED_RGBA_S3TC_DXT5_EXT` | 0x83F3 | A DXT5-compressed image in an RGBA image format. It also provides a 4:1 compression, but differs to the DXT3 compression in how the alpha compression is done. |

### `WEBGL_compressed_texture_es3` (en-US)

| Constant name | Value | Description |
| --- | --- | --- |
| `COMPRESSED_R11_EAC` | 0x9270 | One-channel (red) unsigned format compression. |
| `COMPRESSED_SIGNED_R11_EAC` | 0x9271 | One-channel (red) signed format compression. |
| `COMPRESSED_RG11_EAC` | 0x9272 | Two-channel (red and green) unsigned format compression. |
| `COMPRESSED_SIGNED_RG11_EAC` | 0x9273 | Two-channel (red and green) signed format compression. |
| `COMPRESSED_RGB8_ETC2` | 0x9274 | Compresses RBG8 data with no alpha channel. |
| `COMPRESSED_RGBA8_ETC2_EAC` | 0x9275 | Compresses RGBA8 data. The RGB part is encoded the same as `RGB_ETC2`, but the alpha part is encoded separately. |
| `COMPRESSED_SRGB8_ETC2` | 0x9276 | Compresses sRBG8 data with no alpha channel. |
| `COMPRESSED_SRGB8_ALPHA8_ETC2_EAC` | 0x9277 | Compresses sRGBA8 data. The sRGB part is encoded the same as `SRGB_ETC2`, but the alpha part is encoded separately. |
| `COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2` | 0x9278 | Similar to `RGB8_ETC`, but with ability to punch through the alpha channel, which means to make it completely opaque or transparent. |
| `COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2` | 0x9279 | Similar to `SRGB8_ETC`, but with ability to punch through the alpha channel, which means to make it completely opaque or transparent. |

### `WEBGL_compressed_texture_pvrtc` (en-US)

| Constant name | Value | Description |
| --- | --- | --- |
| `COMPRESSED_RGB_PVRTC_4BPPV1_IMG` | 0x8C00 | RGB compression in 4-bit mode. One block for each 4×4 pixels. |
| `COMPRESSED_RGBA_PVRTC_4BPPV1_IMG` | 0x8C02 | RGBA compression in 4-bit mode. One block for each 4×4 pixels. |
| `COMPRESSED_RGB_PVRTC_2BPPV1_IMG` | 0x8C01 | RGB compression in 2-bit mode. One block for each 8×4 pixels. |
| `COMPRESSED_RGBA_PVRTC_2BPPV1_IMG` | 0x8C03 | RGBA compression in 2-bit mode. One block for each 8×4 pixe |

### `WEBGL_compressed_texture_etc1` (en-US)

| Constant name | Value | Description |
| --- | --- | --- |
| `COMPRESSED_RGB_ETC1_WEBGL` | 0x8D64 | Compresses 24-bit RGB data with no alpha channel. |

### `WEBGL_compressed_texture_atc`

| Constant name | Value | Description |
| --- | --- | --- |
| `COMPRESSED_RGB_ATC_WEBGL` | 0x8C92 | Compresses RGB textures with no alpha channel. |
| `COMPRESSED_RGBA_ATC_EXPLICIT_ALPHA_WEBGL` | 0x8C92 | Compresses RGBA textures using explicit alpha encoding (useful when alpha transitions are sharp). |
| `COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL` | 0x87EE | Compresses RGBA textures using interpolated alpha encoding (useful when alpha transitions are gradient). |

### `WEBGL_depth_texture` (en-US)

| Constant name | Value | Description |
| --- | --- | --- |
| `UNSIGNED_INT_24_8_WEBGL` | 0x84FA | Unsigned integer type for 24-bit depth texture data. |

### `OES_texture_half_float` (en-US)

| Constant name | Value | Description |
| --- | --- | --- |
| `HALF_FLOAT_OES` | 0x8D61 | Half floating-point type (16-bit). |

### `WEBGL_color_buffer_float` (en-US)

| Constant name | Value | Description |
| --- | --- | --- |
| `RGBA32F_EXT` | 0x8814 | RGBA 32-bit floating-point color-renderable format. |
| `RGB32F_EXT` | 0x8815 | RGB 32-bit floating-point color-renderable format. |
| `FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT` | 0x8211 |  |
| `UNSIGNED_NORMALIZED_EXT` | 0x8C17 |  |

### `EXT_blend_minmax` (en-US)

| Constant name | Value | Description |
| --- | --- | --- |
| `MIN_EXT` | 0x8007 | Produces the minimum color components of the source and destination colors. |
| `MAX_EXT` | 0x8008 | Produces the maximum color components of the source and destination colors. |

### `EXT_sRGB` (en-US)

| Constant name | Value | Description |
| --- | --- | --- |
| `SRGB_EXT` | 0x8C40 | Unsized sRGB format that leaves the precision up to the driver. |
| `SRGB_ALPHA_EXT` | 0x8C42 | Unsized sRGB format with unsized alpha component. |
| `SRGB8_ALPHA8_EXT` | 0x8C43 | Sized (8-bit) sRGB and alpha formats. |
| `FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT` | 0x8210 | Returns the framebuffer color encoding. |

### `OES_standard_derivatives` (en-US)

| Constant name | Value | Description |
| --- | --- | --- |
| `FRAGMENT_SHADER_DERIVATIVE_HINT_OES` | 0x8B8B | Indicates the accuracy of the derivative calculation for the GLSL built-in functions: `dFdx`, `dFdy`, and `fwidth`. |

### `WEBGL_draw_buffers` (en-US)

| Constant name | Value | Description |
| --- | --- | --- |
| `COLOR_ATTACHMENT0_WEBGL` | 0x8CE0 | Framebuffer color attachment point |
| `COLOR_ATTACHMENT1_WEBGL` | 0x8CE1 | Framebuffer color attachment point |
| `COLOR_ATTACHMENT2_WEBGL` | 0x8CE2 | Framebuffer color attachment point |
| `COLOR_ATTACHMENT3_WEBGL` | 0x8CE3 | Framebuffer color attachment point |
| `COLOR_ATTACHMENT4_WEBGL` | 0x8CE4 | Framebuffer color attachment point |
| `COLOR_ATTACHMENT5_WEBGL` | 0x8CE5 | Framebuffer color attachment point |
| `COLOR_ATTACHMENT6_WEBGL` | 0x8CE6 | Framebuffer color attachment point |
| `COLOR_ATTACHMENT7_WEBGL` | 0x8CE7 | Framebuffer color attachment point |
| `COLOR_ATTACHMENT8_WEBGL` | 0x8CE8 | Framebuffer color attachment point |
| `COLOR_ATTACHMENT9_WEBGL` | 0x8CE9 | Framebuffer color attachment point |
| `COLOR_ATTACHMENT10_WEBGL` | 0x8CEA | Framebuffer color attachment point |
| `COLOR_ATTACHMENT11_WEBGL` | 0x8CEB | Framebuffer color attachment point |
| `COLOR_ATTACHMENT12_WEBGL` | 0x8CEC | Framebuffer color attachment point |
| `COLOR_ATTACHMENT13_WEBGL` | 0x8CED | Framebuffer color attachment point |
| `COLOR_ATTACHMENT14_WEBGL` | 0x8CEE | Framebuffer color attachment point |
| `COLOR_ATTACHMENT15_WEBGL` | 0x8CEF | Framebuffer color attachment point |
| `DRAW_BUFFER0_WEBGL` | 0x8825 | Draw buffer |
| `DRAW_BUFFER1_WEBGL` | 0x8826 | Draw buffer |
| `DRAW_BUFFER2_WEBGL` | 0x8827 | Draw buffer |
| `DRAW_BUFFER3_WEBGL` | 0x8828 | Draw buffer |
| `DRAW_BUFFER4_WEBGL` | 0x8829 | Draw buffer |
| `DRAW_BUFFER5_WEBGL` | 0x882A | Draw buffer |
| `DRAW_BUFFER6_WEBGL` | 0x882B | Draw buffer |
| `DRAW_BUFFER7_WEBGL` | 0x882C | Draw buffer |
| `DRAW_BUFFER8_WEBGL` | 0x882D | Draw buffer |
| `DRAW_BUFFER9_WEBGL` | 0x882E | Draw buffer |
| `DRAW_BUFFER10_WEBGL` | 0x882F | Draw buffer |
| `DRAW_BUFFER11_WEBGL` | 0x8830 | Draw buffer |
| `DRAW_BUFFER12_WEBGL` | 0x8831 | Draw buffer |
| `DRAW_BUFFER13_WEBGL` | 0x8832 | Draw buffer |
| `DRAW_BUFFER14_WEBGL` | 0x8833 | Draw buffer |
| `DRAW_BUFFER15_WEBGL` | 0x8834 | Draw buffer |
| `MAX_COLOR_ATTACHMENTS_WEBGL` | 0x8CDF | Maximum number of framebuffer color attachment points |
| `MAX_DRAW_BUFFERS_WEBGL` | 0x8824 | Maximum number of draw buffers |

### `OES_vertex_array_object`

| Constant name | Value | Description |
| --- | --- | --- |
| `VERTEX_ARRAY_BINDING_OES` | 0x85B5 | The bound vertex array object (VAO). |

### `EXT_disjoint_timer_query` (en-US)

| Constant name | Value | Description |
| --- | --- | --- |
| `QUERY_COUNTER_BITS_EXT` | 0x8864 | The number of bits used to hold the query result for the given target. |
| `CURRENT_QUERY_EXT` | 0x8865 | The currently active query. |
| `QUERY_RESULT_EXT` | 0x8866 | The query result. |
| `QUERY_RESULT_AVAILABLE_EXT` | 0x8867 | A Boolean indicating whether or not a query result is available. |
| `TIME_ELAPSED_EXT` | 0x88BF | Elapsed time (in nanoseconds). |
| `TIMESTAMP_EXT` | 0x8E28 | The current time. |
| `GPU_DISJOINT_EXT` | 0x8FBB | A Boolean indicating whether or not the GPU performed any disjoint operation. |

Specifications
--------------

| Specification |
| --- |
| WebGL # 5.14 |
| WebGL2 # 3.7 |

See also
--------

* `WebGLRenderingContext`


一个 2D WebGL 动画的基础示例 - Web API 接口参考

一个 2D WebGL 动画的基础示例
===================

在这个 WebGL 示例中，我们创建一个画布，并在其中使用 WebGL 渲染旋转正方形。我们用来表示场景的坐标系与画布的坐标系相同。也就是说，（0, 0）这个坐标在左上角，右下角是坐标在（600, 460）。

旋转正方形示例
-------

### Vertex shader

首先，让我们看一下顶点着色器。它的工作如同以往，是将我们用于场景的坐标转换为剪贴空间的坐标（即系统中的（0，0）位于上下文的中心，每个轴从 -1.0 扩展到 1.0，而不管上下文的实际大小）。

```html
<script id="vertex-shader" type="x-shader/x-vertex">
 attribute vec2 aVertexPosition;

 uniform vec2 uScalingFactor;
 uniform vec2 uRotationVector;

 void main() {
 vec2 rotatedPosition = vec2(
 aVertexPosition.x \* uRotationVector.y +
 aVertexPosition.y \* uRotationVector.x,
 aVertexPosition.y \* uRotationVector.y -
 aVertexPosition.x \* uRotationVector.x
 );

 gl\_Position = vec4(rotatedPosition \* uScalingFactor, 0.0, 1.0);
 }
</script>
```

主程序与我们共享属性 aVertexPosition，它是顶点在其使用的任何坐标系中的位置。我们需要转换这些值，以便位置的两个组件都在 -1.0 到 1.0 的范围内。通过乘以基于上下文宽高比的缩放因子，可以很容易地完成此操作。我们很快就会看到这个计算。

我们也可以通过一次变换来旋转这个图形。The rotated position of the vertex is computed by applying the rotation vector, found in the uniform `uRotationVector`, that's been computed by the JavaScript code.

Then the final position is computed by multiplying the rotated position by the scaling vector provided by the JavaScript code in `uScalingFactor`. The values of `z` and `w` are fixed at 0.0 and 1.0, respectively, since we're drawing in 2D.

The standard WebGL global `gl_Position` is then set to the transformed and rotated vertex's position.

### Fragment shader

Next comes the fragment shader. Its role is to return the color of each pixel in the shape being rendered. Since we're drawing a solid, untextured object with no lighting applied, this is exceptionally simple:

```html
<script id="fragment-shader" type="x-shader/x-fragment">
 #ifdef GL\_ES
 precision highp float;
 #endif

 uniform vec4 uGlobalColor;

 void main() {
 gl\_FragColor = uGlobalColor;
 }
</script>
```

This starts by specifying the precision of the `float` type, as required. Then we set the global `gl_FragColor` to the value of the uniform `uGlobalColor`, which is set by the JavaScript code to the color being used to draw the square.

### HTML

The HTML consists solely of the `<canvas>` that we'll obtain a WebGL context on.

```html
<canvas id="glcanvas" width="600" height="460">
  Oh no! Your browser doesn't support canvas!
</canvas>
```

### Globals and initialization

First, the global variables. We won't discuss these here; instead, we'll talk about them as they're used in the code to come.

```js
let gl = null;
let glCanvas = null;

// Aspect ratio and coordinate system
// details

let aspectRatio;
let currentRotation = [0, 1];
let currentScale = [1.0, 1.0];

// Vertex information

let vertexArray;
let vertexBuffer;
let vertexNumComponents;
let vertexCount;

// Rendering data shared with the
// scalers.

let uScalingFactor;
let uGlobalColor;
let uRotationVector;
let aVertexPosition;

// Animation timing

let previousTime = 0.0;
let degreesPerSecond = 90.0;
```

Initializing the program is handled through a `load` event handler called `startup()`:

```js
window.addEventListener("load", startup, false);

function startup() {
  glCanvas = document.getElementById("glcanvas");
  gl = glCanvas.getContext("webgl");

  const shaderSet = [
    {
      type: gl.VERTEX\_SHADER,
      id: "vertex-shader",
    },
    {
      type: gl.FRAGMENT\_SHADER,
      id: "fragment-shader",
    },
  ];

  shaderProgram = buildShaderProgram(shaderSet);

  aspectRatio = glCanvas.width / glCanvas.height;
  currentRotation = [0, 1];
  currentScale = [1.0, aspectRatio];

  vertexArray = new Float32Array([
    -0.5, 0.5, 0.5, 0.5, 0.5, -0.5, -0.5, 0.5, 0.5, -0.5, -0.5, -0.5,
  ]);

  vertexBuffer = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY\_BUFFER, vertexBuffer);
  gl.bufferData(gl.ARRAY\_BUFFER, vertexArray, gl.STATIC\_DRAW);

  vertexNumComponents = 2;
  vertexCount = vertexArray.length / vertexNumComponents;

  currentAngle = 0.0;

  animateScene();
}
```

After getting the WebGL context, `gl`, we need to begin by building the shader program. Here, we're using code designed to let us add multiple shaders to our program quite easily. The array `shaderSet` contains a list of objects, each describing one shader function to be compiled into the program. Each function has a type (one of `gl.VERTEX_SHADER` or `gl.FRAGMENT_SHADER`) and an ID (the ID of the `<script>` element containing the shader's code).

The shader set is passed into the function `buildShaderProgram()`, which returns the compiled and linked shader program. We'll look at how this works next.

Once the shader program is built, we compute the aspect ratio of our context by dividing its width by its height. Then we set the current rotation vector for the animation to `[0, 1]`, and the scaling vector to `[1.0, aspectRatio]`. The scaling vector, as we saw in the vertex shader, is used to scale the coordinates to fit the -1.0 to 1.0 range.

The array of vertices is created next, as a `Float32Array` with six coordinates (three 2D vertices) per triangle to be drawn, for a total of 12 values.

As you can see, we're using a coordinate system of -1.0 to 1.0 for each axis. Why, you may ask, do we need to do any adjustments at all? This is simply because our context is not square. We're using a context that's 600 pixels wide and 460 tall. Each of those dimensions is mapped to the range -1.0 to 1.0. Since the two axes aren't the same length, if we don't adjust the values of one of the two axes, the square will get stretched out in one direction or the other. So we need to normalize these values.

Once the vertex array has been created, we create a new GL buffer to contain them by calling `gl.createBuffer()`. We bind the standard WebGL array buffer reference to that by calling `gl.bindBuffer()` and then copy the vertex data into the buffer using `gl.bufferData()`. The usage hint `gl.STATIC_DRAW` is specified, telling WebGL that the data will be set only one time and never modified, but will be used repeatedly. This lets WebGL consider any optimizations it can apply that may improve performance based on that information.

With the vertex data now provided to WebGL, we set `vertexNumComponents` to the number of components in each vertex (2, since they're 2D vertexes) and `vertexCount` to the number of vertexes in the vertex list.

Then the current rotation angle (in degrees) is set to 0.0, since we haven't performed any rotation yet, and the rotation speed (in degrees per screen refresh period, typically 60 FPS) is set to 6.

Finally, `animateScene()` is called to render the first frame and schedule the rendering of the next frame of the animation.

### Compiling and linking the shader program

The `buildShaderProgram()` function accepts as input an array of objects describing a set of shader functions to be compiled and linked into the shader program and returns the shader program after it's been built and linked.

```js
function buildShaderProgram(shaderInfo) {
  const program = gl.createProgram();

  shaderInfo.forEach((desc) => {
    const shader = compileShader(desc.id, desc.type);

    if (shader) {
      gl.attachShader(program, shader);
    }
  });

  gl.linkProgram(program);

  if (!gl.getProgramParameter(program, gl.LINK\_STATUS)) {
    console.log("Error linking shader program:");
    console.log(gl.getProgramInfoLog(program));
  }

  return program;
}
```

First, `gl.createProgram()` is called to create a new, empty, GLSL program.

Then, for each shader in the specified list of shaders, we call a `compileShader()` function to compile it, passing into it the ID and type of the shader function to build. Each of those objects includes, as mentioned before, the ID of the `<script>` element the shader code is found in and the type of shader it is. The compiled shader is attached to the shader program by passing it into `gl.attachShader()`.

**备注：** We could go a step farther here, actually, and look at the value of the `<script>` element's `type` attribute to determine the shader type.

Once all of the shaders are compiled, the program is linked using `gl.linkProgram()`.

If an error occurrs while linking the program, the error message is logged to console.

Finally, the compiled program is returned to the caller.

### Compiling an individual shader

The `compileShader()` function, below, is called by `buildShaderProgram()` to compile a single shader.

```js
function compileShader(id, type) {
  const code = document.getElementById(id).firstChild.nodeValue;
  const shader = gl.createShader(type);

  gl.shaderSource(shader, code);
  gl.compileShader(shader);

  if (!gl.getShaderParameter(shader, gl.COMPILE\_STATUS)) {
    console.log(
      `Error compiling ${
 type === gl.VERTEX\_SHADER ? "vertex" : "fragment"
 } shader:`,
    );
    console.log(gl.getShaderInfoLog(shader));
  }
  return shader;
}
```

The code is fetched from the HTML document by obtaining the value of the text node contained within the `<script>` element with the specified ID. Then a new shader of the specified type is created using `gl.createShader()`.

The source code is sent into the new shader by passing it into `gl.shaderSource()`, and then the shader is compiled using `gl.compileShader()`

Compile errors are logged to the console. Note the use of a template literal string to insert the correct shader type string into the message that gets generated. The actual error details are obtained by calling `gl.getShaderInfoLog()` (en-US).

Finally, the compiled shader is returned to the caller (which is the `buildShaderProgram()` function.

### Drawing and animating the scene

The `animateScene()` function is called to render each animation frame.

```js
function animateScene() {
  gl.viewport(0, 0, glCanvas.width, glCanvas.height);
  gl.clearColor(0.8, 0.9, 1.0, 1.0);
  gl.clear(gl.COLOR\_BUFFER\_BIT);

  const radians = (currentAngle \* Math.PI) / 180.0;
  currentRotation[0] = Math.sin(radians);
  currentRotation[1] = Math.cos(radians);

  gl.useProgram(shaderProgram);

  uScalingFactor = gl.getUniformLocation(shaderProgram, "uScalingFactor");
  uGlobalColor = gl.getUniformLocation(shaderProgram, "uGlobalColor");
  uRotationVector = gl.getUniformLocation(shaderProgram, "uRotationVector");

  gl.uniform2fv(uScalingFactor, currentScale);
  gl.uniform2fv(uRotationVector, currentRotation);
  gl.uniform4fv(uGlobalColor, [0.1, 0.7, 0.2, 1.0]);

  gl.bindBuffer(gl.ARRAY\_BUFFER, vertexBuffer);

  aVertexPosition = gl.getAttribLocation(shaderProgram, "aVertexPosition");

  gl.enableVertexAttribArray(aVertexPosition);
  gl.vertexAttribPointer(
    aVertexPosition,
    vertexNumComponents,
    gl.FLOAT,
    false,
    0,
    0,
  );

  gl.drawArrays(gl.TRIANGLES, 0, vertexCount);

  requestAnimationFrame((currentTime) => {
    const deltaAngle =
      ((currentTime - previousTime) / 1000.0) \* degreesPerSecond;

    currentAngle = (currentAngle + deltaAngle) % 360;

    previousTime = currentTime;
    animateScene();
  });
}
```

The first thing that needs to be done in order to draw a frame of the animation is to clear the background to the desired color. In this case, we set the viewport based on the size of the `<canvas>`, call `clearColor()` to set the color to use when clearing content, then we clear the buffer with `clear()`.

Next, the current rotation vector is computed by converting the current rotation in degrees (`currentAngle`) into radians, then setting the first component of the rotation vector to the sine of that value and the second component to the cosine. The `currentRotation` vector is now the location of the point on the unit circle located at the angle `currentAngle`.

`useProgram()` is called to activate the GLSL shading program we established previously. Then we obtain the locations of each of the uniforms used to share information between the JavaScript code and the shaders (with `getUniformLocation()` (en-US)).

The uniform named `uScalingFactor` is set to the `currentScale` value previously computed; this, as you may recall, is the value used to adjust the coordinate system based on the aspect ratio of the context. This is done using `uniform2fv()` (en-US) (since this is a 2-value floating-point vector).

`uRotationVector` is set to the current rotation vector (`currentRotation)`, also using `uniform2fv()`.

`uGlobalColor` is set using `uniform4fv()` (en-US) to the color we wish to use when drawing the square. This is a 4-component floating-point vector (one component each for red, green, blue, and alpha).

Now that that's all out of the way, we can set up the vertex buffer and draw our shape, first, the buffer of vertexes that will be used to draw the triangles of the shape is set by calling `bindBuffer()`. Then the vertex position attribute's index is obtained from the shader program by calling `getAttribLocation()`.

With the index of the vertex position attribute now available in `aVertexPosition`, we call `enableVertexAttribArray()` to enable the position attribute so it can be used by the shader program (in particular, by the vertex shader).

Then the vertex buffer is bound to the `aVertexPosition` attribute by calling `vertexAttribPointer()`. This step is not obvious, since this binding is almost a side effect. But as a result, accessing `aVertexPosition` now obtains data from the vertex buffer.

With the association in place between the vertex buffer for our shape and the `aVertexPosition` attribute used to deliver vertexes one by one into the vertex shader, we're ready to draw the shape by calling `drawArrays()`.

At this point, the frame has been drawn. All that's left to do is to schedule to draw the next one. That's done here by calling `requestAnimationFrame()`, which asks that a callback function be executed the next time the browser is ready to update the screen.

Our `requestAnimationFrame()` callback receives as input a single parameter, `currentTime`, which specifies the time at which the frame drawing began. We use that and the saved time at which the last frame was drawn, `previousTime`, along with the number of degrees per second the square should rotate (`degreesPerSecond`) to calculate the new value of `currentAngle`. Then the value of `previousTime` is updated and we call `animateScene()` to draw the next frame (and in turn schedule the next frame to be drawn, ad infinitum).

结果
--

This is a pretty simple example, since it's just drawing one simple object, but the concepts used here extend to much more complex animations.

参见
--

* WebGL API
* WebGL tutorial


WebGL 的例子 - Web API 接口参考

WebGL 的例子
=========

* 下一页 »

WebGL *例子*是一系列附有简短的解释的样本用来展示 WebGL 的概念和功能。这些示例根据主题和难度级别进行排序，涵盖 WebGL 渲染上下文，着色器编程，纹理，几何图形，用户交互等。

主题例子
----

这些范例是有浅到深的，它们除了是一个个可以让你实现的例子外，还和主题高度重合，当我们需要在中级和高级阶段实现这个例子时有时我们会重复此例子的基础内容。

在第一个程序中，并没有尝试着色着色器，几何图形和使用GPU 内存，这里的示例以渐进的方式探索 WebGL。我们相信它会带来更有效的学习体验，并最终更深入地理解底层概念。

有关这些例子的解释可以在代码的正文和注释中找到。你应该阅读所有注释，因为更高级的示例不会重复注释以前的代码。

### 开始了解渲染上下文

检测 WebGL

这个例子演示如何检测 WebGL 渲染上下文并且反馈给用户。

Clearing with colors

How to clear the rendering context with a solid color.

Clearing by clicking

How to combine user interaction with graphics operations. Clearing the rendering context with a random color when the user clicks.

Simple color animation

A very basic color animation, done by clearing the WebGL drawing buffer with a different random color every second.

Color masking (en-US)

Modifying random colors by applying color masking and thus limiting the range of displayed colors to specific shades.

Basic scissoring (en-US)

How to draw simple rectangles and squares with scissoring operations.

Canvas size and WebGL

The example explores the effect of setting (or not setting) the canvas size to its element size in CSS pixels, as it appears in the browser window.

Boilerplate 1

The example describes repeated pieces of code that will be hidden from now on, as well as defining a JavaScript utility function to make WebGL initialization easier.

Scissor animation

Some animation fun with scissoring and clearing operations.

Raining rectangles (en-US)

A simple game that demonstrates clearing with solid colors, scissoring, animation, and user interaction.

### Shader programming basics

Hello GLSL

A very basic shader program that draws a solid color square.

Hello vertex attributes (en-US)

Combining shader programming and user interaction through vertex attributes.

Textures from code (en-US)

A simple demonstration of procedural texturing with fragment shaders.

### Miscellaneous advanced examples

Video textures (en-US)

This example demonstrates how to use video files as textures.

* 下一页 »


WebGL 教程 - Web API 接口参考

WebGL 教程
========

WebGL 使得网页在支持 HTML `<canvas>` 标签的浏览器中，不需要使用任何插件，便可以使用基于 OpenGL ES 2.0 的 API 在 canvas 中进行 3D 渲染。WebGL 程序由 javascript 的控制代码，和在计算机的图形处理单元（GPU, Graphics Processing Unit）中执行的特效代码 (shader code，渲染代码) 组成。WebGL 元素可以和其他 HTML 元素混合，并且会和页面的其他部分或页面背景相合成。

此教程从基础开始讲解如何使用`<canvas>` 元素来画 WebGL 图形。提供的例子会让你对 WebGL 有更清晰的认识，并且会提供代码片段方便你构建自己的内容。

开始之前
----

使用 `<canvas>` 元素并不困难，但你需要基本的 HTML 和 JavaScript 知识。一些老浏览器不支持`<canvas>` 元素和 WebGL，但所有最近的主流浏览器都支持它们.。为了能在 canvas 中绘制图形，我们使用 Javascript 的上下文环境（context）对象，此对象可以动态创建图形。

在本教程中
-----

开始 WebGL

如何设置 WebGL 上下文环境。

给 WebGL 的上下文环境添加 2D 内容

如何用 WebGl 渲染简单的平面化图形。

在 WebGL 中使用着色器 (shader) 去赋予颜色

演示如何使用着色器给图形添加颜色。

用 WebGL 让对象动起来

展示如何旋转移动物体来实现简单动画效果。

使用 WebGL 创建 3D 物体

展示如何创建并设置一个 3D 物体动画 (这里使用立方体).

在 WebGL 中使用纹理贴图 (texture)

展示如何投射纹理贴图到物体的各个面。

WebGL 中的灯光

如何在 WebGL 上下文环境中模拟灯光效果。

WebGL 中的动画纹理贴图

展示如何让纹理贴图动起来; 在此例中，会投射一个 Ogg 格式的视频在一个旋转立方体的各个面上。


Data in WebGL - Web API 接口参考

Data in WebGL
=============

GLSL 为 Shader 提供了三种不同作用的数据存储，每种都有一个特定的用例。每种数据依作用不同可以被一种或者全部 shader 访问（取决于数据存储类型），也可能通过站点的 Javascript 代码进行访问，这取决于变量的特定类型。

GLSL 数据类型
---------

<<关于 基本数据类型，向量等，参见 Khronos WebGL Wiki 的文档：Data Type (GLSL) >>

GLSL 变量
-------

GLSL 中有三种类型的“变量”或者说数据存储类型。每一种类型都有特定的目标和使用方法：: **attributes**、**varyings**和**uniforms**.

### Attributes

**Attributes** 可以被 JavaScript 代码操作，也可以在 vertex shader 中被作为变量访问。Attributes 通常被用于存储颜色、纹理坐标以及其他需要在 JavaScript 代码和 vertex shader 之间互相传递的数据。

```js
// init colors
const vertexColors = [
  vec4(0.0, 0.0, 0.0, 1.0), // black
  vec4(1.0, 0.0, 0.0, 1.0), // red
  vec4(1.0, 1.0, 0.0, 1.0), // yellow
  vec4(0.0, 1.0, 0.0, 1.0), // green
  vec4(0.0, 0.0, 0.0, 1.0), // black
  vec4(1.0, 0.0, 0.0, 1.0), // red
  vec4(1.0, 1.0, 0.0, 1.0), // yellow
  vec4(0.0, 1.0, 0.0, 1.0), // green
];
const cBuffer = gl.createBuffer();
```

```js
// continued
// create buffer to store colors and reference it to "vColor" which is in GLSL
gl.bindBuffer(gl.ARRAY\_BUFFER, cBuffer);
gl.bufferData(gl.ARRAY\_BUFFER, flatten(vertexColors), gl.STATIC\_DRAW);

const vColor = gl.getAttribLocation(program, "vColor");
gl.vertexAttribPointer(vColor, 4, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(vColor);
```

```cpp
//glsl
attribute  vec4 vColor;

void main()
{
  fColor = vColor;
}
```

### Varyings

**Varyings** 在 vertex shader 中定义，用于从 vertex shader 向 fragment shader 传递数据。通常传递 normal vector 等在 vertex shader 中计算生成的数据会使用 varying。

<<how to use>>

### Uniforms

**Uniform** 通常是由 JavaScript 代码设置并且在 vertex shader 和 fragment shader 中都能够访问。使用 uniform 设定在一帧的所有绘制中相同的数据，例如光源颜色、亮度、全局变换以及透视数据等等。

<<添加细节>>

Buffers
-------

<<添加信息>>

Textures
--------

<<添加信息>>


Matrix math for the web - Web API 接口参考

Matrix math for the web
=======================

矩阵可以用于表示空间中的对象的变换，并且是 Web 页面可视化的重要工具。本文探索如何创建并配合CSS3 变换和 matrix3d 变换类型使用矩阵。

虽然本文为了便于解释而使用了 CSS3，矩阵却是许多技术中的核心概念，包括 WebGL 和着色器。本文也是MDN content kit的一部分。示例使用了一组全局对象 MDN 下的工具函数。

什么是变换矩阵？
--------

虽然存在许多类型的矩阵，但我们感兴趣的是三维变换矩阵。这种矩阵由一个 4x4 方阵，共 16 个值组成。在 JavaScript 中，可以很方便的用数组表示矩阵。比如典型的单位矩阵。单位阵乘上一个点或者矩阵，其结果保持不变。

```js
var identityMatrix = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
```

说到乘法，这种运算用于矩阵是什么样的呢？最简单的例子是矩阵乘一个点。你可能注意到，三维空间中的点和一个 4x4 矩阵并不匹配，为此我们加上了额外的第四维 W。一般来说，把 W 设为 1 就可以了。W 维度还有一些额外的用途超出本文的讨论范围。

注意矩阵和点的对齐方式：

```js
[1, 0, 0, 0,
 0, 1, 0, 0,
 0, 0, 1, 0,
 0, 0, 0, 1]

[4, 3, 2, 1] // 在 [x, y, z, w] 处求点积
```

### 定义相乘函数

我们在示例代码中定义了一个乘法函数——`multiplyMatrixAndPoint()`：

```js
function multiplyMatrixAndPoint(matrix, point) {
  // 给矩阵的每一部分一个简单的变量名，列数（c）与行数（r）
  var c0r0 = matrix[0],
    c1r0 = matrix[1],
    c2r0 = matrix[2],
    c3r0 = matrix[3];
  var c0r1 = matrix[4],
    c1r1 = matrix[5],
    c2r1 = matrix[6],
    c3r1 = matrix[7];
  var c0r2 = matrix[8],
    c1r2 = matrix[9],
    c2r2 = matrix[10],
    c3r2 = matrix[11];
  var c0r3 = matrix[12],
    c1r3 = matrix[13],
    c2r3 = matrix[14],
    c3r3 = matrix[15];

  // 定义点坐标
  var x = point[0];
  var y = point[1];
  var z = point[2];
  var w = point[3];

  // 点坐标和第一列对应相乘，再求和
  var resultX = x \* c0r0 + y \* c0r1 + z \* c0r2 + w \* c0r3;

  // 点坐标和第二列对应相乘，再求和
  var resultY = x \* c1r0 + y \* c1r1 + z \* c1r2 + w \* c1r3;

  // 点坐标和第三列对应相乘，再求和
  var resultZ = x \* c2r0 + y \* c2r1 + z \* c2r2 + w \* c2r3;

  // 点坐标和第四列对应相乘，再求和
  var resultW = x \* c3r0 + y \* c3r1 + z \* c3r2 + w \* c3r3;

  return [resultX, resultY, resultZ, resultW];
}
```

现在我们可以使用上面的函数将一个点乘上一个矩阵。乘以单位阵将会返回原值：

```js
// identityResult 等于 [4,3,2,1]
var identityResult = multiplyMatrixAndPoint(identityMatrix, [4, 3, 2, 1]);
```

返回同一个点并没有什么用处，但还有一些其他的矩阵可以作用于点，返回有用的结果。接下来我们将演示其中一些矩阵。

### 两个矩阵相乘

除了把矩阵和点相乘，你也可以把两个矩阵相乘。之前的函数可以帮助我们简化这个过程：

```js
function multiplyMatrices(matrixA, matrixB) {
  // 将第二个矩阵按列切片
  var column0 = [matrixB[0], matrixB[4], matrixB[8], matrixB[12]];
  var column1 = [matrixB[1], matrixB[5], matrixB[9], matrixB[13]];
  var column2 = [matrixB[2], matrixB[6], matrixB[10], matrixB[14]];
  var column3 = [matrixB[3], matrixB[7], matrixB[11], matrixB[15]];

  // 将每列分别和矩阵相乘
  var result0 = multiplyMatrixAndPoint(matrixA, column0);
  var result1 = multiplyMatrixAndPoint(matrixA, column1);
  var result2 = multiplyMatrixAndPoint(matrixA, column2);
  var result3 = multiplyMatrixAndPoint(matrixA, column3);

  // 把结果重新组合成矩阵
  return [
    result0[0],
    result1[0],
    result2[0],
    result3[0],
    result0[1],
    result1[1],
    result2[1],
    result3[1],
    result0[2],
    result1[2],
    result2[2],
    result3[2],
    result0[3],
    result1[3],
    result2[3],
    result3[3],
  ];
}
```

### 用法

让我们看一看实际使用：

```js
var someMatrix = [4, 0, 0, 0, 0, 3, 0, 0, 0, 0, 5, 0, 4, 8, 4, 1];

var identityMatrix = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];

// 返回 someMatrix 的数组表示
var someMatrixResult = multiplyMatrices(identityMatrix, someMatrix);
```

**警告：** 这些函数是为了解释的清晰而编写，而不是为了速度或者内存管理。这些函数新建了大量数组，可能在实时运算时导致垃圾回收的巨大开销。在实际产品中最好使用优化过的函数。比如glMatrix就是一个注重速度和性能的库。

平移矩阵
----

平移矩阵基于单位矩阵。它将一个对象沿 x，y，z 其中一个方向进行移动。最简单的想象平移的方式是设想拿起一个咖啡杯。咖啡杯必须保持直立和朝向以免咖啡洒出来。它可以离开桌子在空间中移动。

现在我们还喝不到这个杯子里的咖啡，因为在平移矩阵的单独作用下杯子并不能倾斜。在之后的部分，我们会讨论新的矩阵，来解决这个问题。

```js
var x = 50;
var y = 100;
var z = 0;

var translationMatrix = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, x, y, z, 1];
```

用矩阵操作 DOM
---------

一个非常简单的开始使用矩阵的方法是使用 CSS3 里的 `matrix3d` 变换。首先，我们新建一个简单的 `<div>` 并加上一些内容。这里样式没有展示出来，但我们将其设置成了页面居中且固定宽度与高度。我们同样为变换设定了动画以便清晰的观察发生的变化。

```html
<div id="move-me" class="transformable">
  <h2>Move me with a matrix</h2>
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit...</p>
</div>
```

最后，我们会为每一个例子生成一个 4x4 矩阵，然后更新<div>的样式，对其应用一个 matrix3d 变换。要记住即使矩阵有四行四列，也要将其写成单行 16 个值。

```js
// 从矩阵数组创建 matrix3d 样式属性
function matrixArrayToCssMatrix(array) {
  return "matrix3d(" + array.join(",") + ")";
}

// 获取 DOM 元素
var moveMe = document.getElementById("move-me");

// 返回结果如："matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 50, 100, 0, 1);"
var matrix3dRule = matrixArrayToCssMatrix(translationMatrix);

// 设置变换
moveMe.style.transform = matrix3dRule;
```

在 JSFiddle 中查看

![An example of matrix translation](/zh-CN/docs/Web/API/WebGL_API/Matrix_math_for_the_web/matrix-translation.jpg)

缩放矩阵
----

缩放矩阵使对象的高度、宽度和深度三个维度的其中之一变大或变小。在典型（笛卡尔）坐标系中，这将使得 x，y，z 坐标拉伸或收缩。

```js
var w = 1.5; // width (x)
var h = 0.7; // height (y)
var d = 1; // depth (z)

var scaleMatrix = [w, 0, 0, 0, 0, h, 0, 0, 0, 0, d, 0, 0, 0, 0, 1];
```

在 JSFiddle 中查看

![An example of matrix scaling](/zh-CN/docs/Web/API/WebGL_API/Matrix_math_for_the_web/matrix-scale.jpg)

旋转矩阵
----

旋转矩阵比平移和缩放矩阵要稍复杂一些。其中用到了三角函数来完成旋转。尽管这部分不会把步骤讲得过于详细，但是下例有简单的说明。

```js
// 不借助矩阵将点绕原点旋转
var point = [10, 2];

// 计算到原点的距离
var distance = Math.sqrt(point[0] \* point[0] + point[1] \* point[1]);

// 60 度
var rotationInRadians = Math.PI / 3;

var transformedPoint = [
  Math.cos(rotationInRadians) \* distance,
  Math.sin(rotationInRadians) \* distance,
];
```

我们可以将上述步骤表示为一个矩阵，并且单独应用到 x，y，和 z 坐标。下面是绕 Z 轴旋转的表示：

```js
var sin = Math.sin;
var cos = Math.cos;

// NOTE: There is no perspective in these transformations, so a rotation
// at this point will only appear to only shrink the div

var a = Math.PI \* 0.3; // 转角

// 绕 Z 轴旋转
var rotateZMatrix = [
  cos(a),
  -sin(a),
  0,
  0,
  sin(a),
  cos(a),
  0,
  0,
  0,
  0,
  1,
  0,
  0,
  0,
  0,
  1,
];
```

在 JSFiddle 中查看

![](/zh-CN/docs/Web/API/WebGL_API/Matrix_math_for_the_web/matrix-rotation.jpg)

这里是一组返回旋转矩阵的函数。要注意的是由于没有加入透视，所以旋转看起来没有那么 3D。这就好像摄像机在极近距离拍摄一个物体——透视的感觉消失了。

```js
function rotateAroundXAxis(a) {
  return [1, 0, 0, 0, 0, cos(a), -sin(a), 0, 0, sin(a), cos(a), 0, 0, 0, 0, 1];
}

function rotateAroundYAxis(a) {
  return [cos(a), 0, sin(a), 0, 0, 1, 0, 0, -sin(a), 0, cos(a), 0, 0, 0, 0, 1];
}

function rotateAroundZAxis(a) {
  return [cos(a), -sin(a), 0, 0, sin(a), cos(a), 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
}
```

在 JSFiddle 中查看

矩阵组合
----

矩阵的真正厉害之处在于矩阵的组合。当一组特定类型的矩阵连乘起来，它们保留了变换的经过并且是可逆的。这意味着如果平移、旋转和缩放矩阵组合在一起，当我们使用逆变换并颠倒应用的顺序，可以得到原来的点。

矩阵相乘的结果与顺序有关。两个数相乘时，a \* b = c，和 b \* a = c 都是正确的。例如，3 \* 4 = 12，和 4 \* 3 = 12。在数学上这些数被称为**可交换**。矩阵不能保证交换顺序后的运算结果，所以矩阵是**不可交换**的。

另一个需要记住的点是在 WebGL 和 CSS3 中的矩阵相乘需要和变换发生的顺序相反。例如，缩放对象到 80%，向下移动 200 像素，然后绕原点旋转 90 度在伪代码中应该像下面这样。
```

  transformation = rotate * translate * scale
```

### 组合多种变换

我们将使用的函数是工具函数的一部分。其接受矩阵的数组并把它们乘起来。在 WebGL 着色器代码里，这内建在语言里，并且我们可以使用 \* 运算符。除此之外，本例使用了一个缩放函数，一个平移函数，它们返回之前定义的矩阵。

```js
var transformMatrix = MDN.multiplyArrayOfMatrices([
  rotateAroundZAxis(Math.PI \* 0.5), // 第 3 步：旋转 90 度
  translate(0, 200, 0), // 第 2 步：下移 100 像素
  scale(0.8, 0.8, 0.8), // 第 1 步：缩小
]);
```

在 JSFiddle 中查看

![An example of matrix composition](/zh-CN/docs/Web/API/WebGL_API/Matrix_math_for_the_web/matrix-composition.jpg)

最后是展示矩阵用途的有趣的一步，看看怎样颠倒这些步骤并得到最开始的单位矩阵。

```js
var transformMatrix = MDN.multiplyArrayOfMatrices([
  scale(1.25, 1.25, 1.25), // 第 6 步：放大
  translate(0, -200, 0), // 第 5 步：上移
  rotateAroundZAxis(-Math.PI \* 0.5), // 第 4 步：倒转
  rotateAroundZAxis(Math.PI \* 0.5), // 第 3 步：旋转 90 度
  translate(0, 200, 0), // 第 2 步：下移 100 像素
  scale(0.8, 0.8, 0.8), // 第 1 步：缩小
]);
```

为什么矩阵这么重要？
----------

矩阵之所以重要，是因为它可以用少量的数字描述大量的空间中的变换，并且能轻易地在程序间共享。矩阵可以不同的坐标空间，甚至一些矩阵乘法可以将一组数据从一个坐标空间映射到另一个坐标空间。矩阵能够高效率地保存生成它们的每一步变换。

对于在 WebGL 中使用，显卡尤其擅长大量的点乘矩阵运算。各种各样的运算，如点定位、光线运算、动态角色，都依赖这个基础工具。


WebGL best practices - Web API 接口参考

WebGL best practices
====================

WebGL 是一个复杂的 API，通常我们不能明显的知道它的推荐使用方式。该页面涵盖了各种专业知识的建议，不仅仅是列举出什么该做，什么不该做，还有详细的解释为什么要这样做。你可以将本文档作为指导你选择的方法，确保你无论在何种浏览器以及硬件上都使用了正确的技巧。

需要避免的事情
-------

* 确保应用程序运行时不会产生任何 WebGL 错误（如 getError() 返回的）. In Firefox, every WebGL error (until a certain limit), and some other WebGL issues, are reported as a JavaScript warning with a descriptive message. 在 Firefox 中，所有 WebGL 错误（直至超出数量限制）以及其他一些 WebGL 问题，都会以一段提供描述的 JavaScript 警告报告出来。你不想自己的应用在用户的控制台打印出一堆东西对吧？你当然不想了。
* 你应该永远不去触碰 WebGL shader 里的 `#ifdef GL_ES`；虽然前边的一些例子使用了这个，这并无必要，因为这个条件判断在 WebGL shader 中始终为 true。
* 在 fragment shader 中使用 `highp` 精度将阻碍你的内容在某些旧的移动设备上正确运行。这里，你可以使用 `mediump`；但是，你需要知道，由于在大多移动设备上的精度丢失，这经常导致渲染失败，这在典型的 PC 机型上没有问题。通常来说，在 vertex 和 fragment shader 中仅使用 `highp` ，除非 shaders 通过了各大平台的测试。从 Firefox 11 开始，WebGL 的 `getShaderPrecisionFormat()` 函数的实现，允许你判断 `highp` 是否得到支持，进而允许你可以查询到实际的精度。
需要记住的事情
-------

* 在客户端/浏览器使用某些 WebGL 功能前，还是建议先使用 WebGL `getParameter()` 方法，获取此类参数的范围，这些数据反映了你的客户端能够支持的真实应用范围。例如，使用 `webgl.getParameter(webgl.MAX_TEXTURE_SIZE)`可以查询设备上支持的最大的 2D 纹理尺寸。从 Firefox 10 开始，WebGL 属性 `webgl.min_capability_mode` 则可以被用来测试最小性能模式下的实际表现，以测试可移植性。
* 特别要注意的是，只有在 `webgl.getParameter(webgl.MAX_VERTEX_TEXTURE_IMAGE_UNITS)` 大于零时，才能使用 vertex shaders 中的纹理。然而，目前的移动硬件上是不支持的 (译者：待确认文档时效性)。
* 大多数 WebGL 扩展的可用性取决于客户端。在使用 WebGL 扩展时，如果可能的话，尝试通过优雅地适应不支持它们的情况，使它们成为可选的。从 Firefox 10 开始，属性 `webgl.disable-extensions` 允许模拟列出哪些扩展是不支持的，以测试可移植性。
* 另外，即使支持 `OES_texture_float` 扩展，也可能不支持渲染浮点类型数据的纹理。通常，这在当前的移动硬件上是不支持的 (译者：待确认文档时效性)。要检查是否支持浮点类型数据，必须调用 `checkFramebufferStatus()` 来验证。
* 实际渲染到画布的分辨率可以不同于样式表最终强制画布显示的分辨率。如果考虑性能，你应该试着渲染到一个低分辨率 WebGL 上下文，并使用 CSS 来升级它的画布到你想要的尺寸。
一般性能提示
------

* Anything that requires syncing the CPU and GPU sides is potentially very slow, so if possible you should try to avoid doing that in your main rendering loops. This includes the following WebGL calls: `getError()`, `readPixels()`, and `finish()`. WebGL getter calls such as `getParameter()` and `getUniformLocation()` should be considered slow too, so try to cache their results in a JavaScript variable.
* Fewer, larger draw operations will improve performance. If you have 1000 sprites to paint, try to do it as a single `drawArrays()` or `drawElements()` call. You can draw degenerate (flat) triangles if you need to draw discontinuous objects as a single `drawArrays()` call.
* Fewer state changes will also improve performance. In particular, if you can pack multiple images into a single texture and select them by using the appropriate texture coordinates, that can help you do fewer texture binding changes, which improves performance.
    + In some rare cases, packing greyscale textures which belong together into the color channels of a single texture might help.
* Smaller textures perform better than larger ones. For this reason, mipmapping can be a performance win.
* Simpler shaders perform better than complex ones. In particular, if you can remove an `if` statement from a shader, that will make it run faster. Division and math functions like `log()` should be considered expensive too.
    + However, nowadays even mobile devices possess powerful GPUs that are capable of running even relatively complex shader programs. Moreover, because shaders are compiled, the eventual machine code that actually runs on the hardware may be highly optimized. What may seem like an expensive function call may in fact compile into only few (or even a single) machine instructions. This is particularly true for GLSL functions that typically operate on vectors, such as `normalize()`, `dot()` and `mix()`. The best advice in that regard is to use the built-in functions, rather than try to implement, for example, one's own version of a dot-product or linear interpolation, which may in fact compile to larger and less optimized machine code. Finally, it is important to keep in mind that GPUs are constructed to do complex mathematical calculations in hardware, and therefore, may support math functions, such as `sin()`, `cos()` and other, through dedicated machine instructions.
* Do as much as you can in the vertex shader, rather than in the fragment shader. Because, per rendering pass, fragment shaders run many more times than vertex shaders, any calculation that can be done on the vertices and then just interpolated among fragments is a performance boon (this interpolation is done "automagically" for you, through the fixed functionality rasterization phase of the OpenGL pipeline). For example, a simple animation of a textured surface can be achieved through a time-dependent transformation of texture coordinates (simplest case is to add a uniform vector to the texture coordinates attribute vector). If visually acceptable, one can transform the texture coordinates in the vertex shader rather than in the fragment shader, to get better performance.
* Always have vertex attrib 0 array enabled. If you draw with vertex attrib 0 array disabled, you will force the browser to do complicated emulation when running on desktop OpenGL (e.g. on Mac OSX). This is because in desktop OpenGL, nothing gets drawn if vertex attrib 0 is not array-enabled. You can use `bindAttribLocation()` to force a vertex attribute to use location `0`, and use `enableVertexAttribArray()` to make it array-enabled.