recursal/MDN huggingface dataset:
WebGL by example
================

* Next »

*WebGL by example* is a series of live samples with short explanations that showcase WebGL concepts and capabilities.

The examples are sorted according to topic and level of difficulty, covering the WebGL rendering context, shader programming, textures, geometry, user interaction, and more.

Examples by topic
-----------------

The examples are sorted in order of increasing difficulty. But rather than just presenting them in a single long list, they are additionally divided into topics. Sometimes we revisit a topic several times, such as when needing to discuss it initially at a basic level, and later at intermediate and advanced levels.

Instead of trying to juggle shaders, geometry, and working with GPU memory, already in the first program, the examples here explore WebGL in an incremental way. We believe that it leads to a more effective learning experience and ultimately a deeper understanding of the underlying concepts.

Explanations about the examples are found in both the main text and in comments within the code. You should read all comments, because more advanced examples could not repeat comments about parts of the code that were previously explained.

### Getting to know the rendering context

Detect WebGL

This example demonstrates how to detect a WebGL rendering context and reports the result to the user.

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

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

Basic scissoring

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

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

Combining shader programming and user interaction through vertex attributes.

Textures from code

A simple demonstration of procedural texturing with fragment shaders.

### Miscellaneous advanced examples

Video textures

This example demonstrates how to use video files as textures.

* Next »
WebGL types
===========

The following types are used in WebGL interfaces.

WebGL 1
-------

These types are used within a `WebGLRenderingContext`.

| Type | Web IDL type | Description |
| --- | --- | --- |
| `GLenum` | `unsigned long` | 
 Used for enums. See also the list of
 constants.
  |
| `GLboolean` | `boolean` | A boolean value. |
| `GLbitfield` | `unsigned long` | 
 A bit field that stores multiple, logical bits. Used for example in
 `WebGLRenderingContext.clear()`.
  |
| `GLbyte` | `byte` | 8-bit twos complement signed integer. |
| `GLshort` | `short` | 16-bit twos complement signed integer. |
| `GLint` | `long` | 32-bit twos complement signed integer. |
| `GLsizei` | `long` | Used for sizes (e.g. width and height of the drawing buffer). |
| `GLintptr` | `long long` | Special type for pointer arithmetic. |
| `GLsizeiptr` | `long long` | Special type for pointer arithmetic. |
| `GLubyte` | `octet` | 8-bit unsigned integer. |
| `GLushort` | `unsigned short` | 16-bit unsigned integer. |
| `GLuint` | `unsigned long` | 32-bit unsigned integer. |
| `GLfloat` | `unrestricted float` | 32-bit IEEE floating point number. |
| `GLclampf` | `unrestricted float` | Clamped 32-bit IEEE floating point number. |

WebGL 2
-------

These types are used within a `WebGL2RenderingContext`. All WebGL 1 types are used as well.

| Type | Web IDL type | Description |
| --- | --- | --- |
| `GLint64` | `long long` | Signed 64-bit integer number. |

WebGL extensions
----------------

These types are used within WebGL extensions.

| Type | Web IDL type | Description |
| --- | --- | --- |
| `GLuint64EXT` | `long long` | Unsigned 64-bit integer number. |

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

| Specification |
| --- |
| WebGL # 5.1 |
| WebGL2 # 3.1 |
| EXT\_disjoint\_timer\_query  |

See also
--------

* `WebGLRenderingContext`
Detect WebGL
============

* « Previous
* Next »

This example demonstrates how to detect a WebGL rendering context and reports the result to the user.

Feature-detecting WebGL
-----------------------

In this first example we are going to check whether the browser supports WebGL. To that end we will try to obtain the WebGL rendering context from a `canvas` element. The WebGL rendering context is an interface, through which you can set and query the state of the graphics machine, send data to the WebGL, and execute draw commands.

Saving the state of the graphics machine within a single context interface is not unique to WebGL. This is also done in other graphics API, such as the canvas 2D rendering context. However, the properties and variables you can tweak are different for each API.


```html
<p>[ Here would go the result of WebGL feature detection ]</p>
<button>Press here to detect WebGLRenderingContext</button>
```



```css
body {
  text-align: center;
}
button {
  display: block;
  font-size: inherit;
  margin: auto;
  padding: 0.6em;
}
```



```js
// Run everything inside window load event handler, to make sure
// DOM is fully loaded and styled before trying to manipulate it.
window.addEventListener(
  "load",
  () => {
    const paragraph = document.querySelector("p");
    const button = document.querySelector("button");

    // Adding click event handler to button.
    button.addEventListener("click", detectWebGLContext, false);
    function detectWebGLContext() {
      // Create canvas element. The canvas is not added to the
      // document itself, so it is never displayed in the
      // browser window.
      const canvas = document.createElement("canvas");

      // Get WebGLRenderingContext from canvas element.
      const gl =
        canvas.getContext("webgl") || canvas.getContext("experimental-webgl");

      // Report the result.
      paragraph.textContent =
        gl instanceof WebGLRenderingContext
          ? "Congratulations! Your browser supports WebGL."
          : "Failed. Your browser or device may not support WebGL.";
    }
  },
  false,
);
```


The source code of this example is also available on GitHub.

* « Previous
* Next »
Boilerplate 1
=============

* « Previous
* Next »

This 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.

Boilerplate code for setting up WebGL rendering context
-------------------------------------------------------

By now you are quite used to seeing the same pieces of HTML, CSS, and JavaScript repeated again and again. So we are going to hide them from now on. This would allow us to focus on the interesting pieces of code that are most relevant for learning WebGL.

Specifically, the HTML has a `<p>` element that contains some descriptive text about the page and may also hold error messages; a `<canvas>` element; and optionally a `<button>`. The CSS contains rules for `body`, `canvas`, and `button`. Any additional non-trivial CSS and HTML will be displayed on the pages of specific examples.

In following examples, we will use a JavaScript helper function, `getRenderingContext()`, to initialize the WebGL rendering context. By now, you should be able to understand what the function does. Basically, it gets the WebGL rendering context from the canvas element, initializes the drawing buffer, clears it black, and returns the initialized context. In case of error, it displays an error message and returns `null`.

Finally, all JavaScript code will run within an immediate function, which is a common JavaScript technique (see Function). The function declaration and invocation will also be hidden.

### HTML


```html
<p>[ Some descriptive text about the example. ]</p>
<button>[ Optional button element. ]</button>
<canvas>Your browser does not seem to support HTML canvas.</canvas>
```

### CSS


```css
body {
  text-align: center;
}
canvas {
  display: block;
  width: 280px;
  height: 210px;
  margin: auto;
  padding: 0;
  border: none;
  background-color: black;
}
button {
  display: block;
  font-size: inherit;
  margin: auto;
  padding: 0.6em;
}
```

### JavaScript


```js
function getRenderingContext() {
  const canvas = document.querySelector("canvas");
  canvas.width = canvas.clientWidth;
  canvas.height = canvas.clientHeight;
  const gl =
    canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
  if (!gl) {
    const paragraph = document.querySelector("p");
    paragraph.innerHTML =
      "Failed to get WebGL context." +
      "Your browser or device may not support WebGL.";
    return null;
  }
  gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
  gl.clearColor(0.0, 0.0, 0.0, 1.0);
  gl.clear(gl.COLOR\_BUFFER\_BIT);
  return gl;
}
```


The source code of this example is also available on GitHub.

* « Previous
* Next »
Clearing by clicking
====================

* « Previous
* Next »

This example demonstrates how to combine user interaction with WebGL graphics operations by clearing the rendering context with a random color when the user clicks.

Clearing the rendering context with random colors
-------------------------------------------------

This example provides a simple illustration of how to combine WebGL and user interaction. Every time the user clicks the canvas or the button, the canvas is cleared with a new randomly chosen color.

Note how we embed the WebGL function calls inside the event handler function.


```html
<p>
  A very simple WebGL program that still shows some color and user interaction.
</p>
<p>
  You can repeatedly click the empty canvas or the button below to change color.
</p>
<canvas id="canvas-view">
  Your browser does not seem to support HTML canvas.
</canvas>
<button id="color-switcher">Press here to switch color</button>
```



```css
body {
  text-align: center;
}
canvas {
  display: block;
  width: 280px;
  height: 210px;
  margin: auto;
  padding: 0;
  border: none;
  background-color: black;
}
button {
  display: inline-block;
  font-size: inherit;
  margin: auto;
  padding: 0.6em;
}
```



```js
window.addEventListener(
  "load",
  function setupWebGL(evt) {
    "use strict";

    // Cleaning after ourselves. The event handler removes
    // itself, because it only needs to run once.
    window.removeEventListener(evt.type, setupWebGL, false);

    // Adding the same click event handler to both canvas and
    // button.
    const canvas = document.querySelector("#canvas-view");
    const button = document.querySelector("#color-switcher");
    canvas.addEventListener("click", switchColor, false);
    button.addEventListener("click", switchColor, false);

    // A variable to hold the WebGLRenderingContext.
    let gl;

    // The click event handler.
    function switchColor() {
      // Referring to the externally defined gl variable.
      // If undefined, try to obtain the WebGLRenderingContext.
      // If failed, alert user of failure.
      // Otherwise, initialize the drawing buffer (the viewport).
      if (!gl) {
        gl =
          canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
        if (!gl) {
          alert(
            "Failed to get WebGL context.\n" +
              "Your browser or device may not support WebGL.",
          );
          return;
        }
        gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
      }
      // Get a random color value using a helper function.
      const color = getRandomColor();
      // Set the clear color to the random color.
      gl.clearColor(color[0], color[1], color[2], 1.0);
      // Clear the context with the newly set color. This is
      // the function call that actually does the drawing.
      gl.clear(gl.COLOR\_BUFFER\_BIT);
    }

    // Random color helper function.
    function getRandomColor() {
      return [Math.random(), Math.random(), Math.random()];
    }
  },
  false,
);
```


The source code of this example is also available on GitHub.

* « Previous
* Next »
Video textures
==============

* « Previous

This example demonstrates how to use video files as textures for WebGL surfaces.

Textures from video
-------------------

The source code of this example is available on GitHub.

* « Previous
Canvas size and WebGL
=====================

* « Previous
* Next »

This WebGL 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.

Effect of canvas size on rendering with WebGL
---------------------------------------------

With `scissor()` and `clear()` we can demonstrate how the WebGL drawing buffer is affected by the size of the canvas.

The size of the first canvas is set to the styled `Element` size, determined by CSS. This is done by assigning the `width` and `height` properties of the canvas to the values of the `clientWidth` and `clientHeight` properties, respectively.

In contrast, no such assignment is done for the second canvas. The internal `width` and `height` properties of the canvas remain at default values, which are different than the actual size of the canvas `Element` in the browser window.

The effect is clearly visible when using `scissor()` and `clear()` to draw a square in the center of the canvas, by specifying its position and size in pixels. In the first canvas, we get the desired result. In the second, the square has the wrong shape, size, and position.


```html
<p>Compare the two canvases.</p>
<canvas>Your browser does not seem to support HTML canvas.</canvas>
<canvas>Your browser does not seem to support HTML canvas.</canvas>
```



```css
body {
  text-align: center;
}
canvas {
  display: inline-block;
  width: 120px;
  height: 80px;
  margin: auto;
  padding: 0;
  border: none;
  background-color: black;
}
```



```js
window.addEventListener(
  "load",
  () => {
    const [firstCanvas, secondCanvas] = document.getElementsByTagName("canvas");
    firstCanvas.width = firstCanvas.clientWidth;
    firstCanvas.height = firstCanvas.clientHeight;
    [firstCanvas, secondCanvas].forEach((canvas) => {
      const gl =
        canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
      if (!gl) {
        document.querySelector("p").textContent =
          "Failed. Your browser or device may not support WebGL.";
        return;
      }
      gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
      gl.enable(gl.SCISSOR\_TEST);
      gl.scissor(30, 10, 60, 60);
      gl.clearColor(1.0, 1.0, 0.0, 1.0);
      gl.clear(gl.COLOR\_BUFFER\_BIT);
    });
  },
  false,
);
```


The source code of this example is also available on GitHub.

* « Previous
* Next »
Animating objects with WebGL
============================

* « Previous
* Next »
Making the square rotate
------------------------

In this example, we'll actually rotate our camera. By doing so, it will look as if we are rotating the square. First we'll need some variables in which to track the current rotation of the camera.

**Note:** Add this code at the start of your "webgl-demo.js" script:


```js
let squareRotation = 0.0;
let deltaTime = 0;
```


Now we need to update the `drawScene()` function to apply the current rotation to the camera when drawing it. After translating the camera to the initial drawing position for the square, we apply the rotation.

**Note:** In your "draw-scene.js" module, update the declaration of your `drawScene()` function so it can be passed the rotation to use:


```js
function drawScene(gl, programInfo, buffers, squareRotation) {
```


**Note:** In your `drawScene()` function, right after the line `mat4.translate()` call, add this code:


```js
mat4.rotate(
  modelViewMatrix, // destination matrix
  modelViewMatrix, // matrix to rotate
  squareRotation, // amount to rotate in radians
  [0, 0, 1],
); // axis to rotate around
```


This rotates the modelViewMatrix by the current value of `squareRotation`, around the Z axis.

To actually animate, we need to add code that changes the value of `squareRotation` over time.

**Note:** Add this code at the end of your `main()` function, replacing the existing `drawScene()` call:


```js
let then = 0;

// Draw the scene repeatedly
function render(now) {
  now \*= 0.001; // convert to seconds
  deltaTime = now - then;
  then = now;

  drawScene(gl, programInfo, buffers, squareRotation);
  squareRotation += deltaTime;

  requestAnimationFrame(render);
}
requestAnimationFrame(render);
```


This code uses `requestAnimationFrame` to ask the browser to call the function "`render`" on each frame. `requestAnimationFrame` passes us the time in milliseconds since the page loaded. We convert that to seconds and then subtract from it the last time to compute `deltaTime`, which is the number of second since the last frame was rendered.

Finally, we update `squareRotation`.

View the complete code | Open this demo on a new page

* « Previous
* Next »
AudioContext: outputLatency property
====================================

 The **`outputLatency`** read-only property of
 the `AudioContext` Interface provides an estimation of the output latency
 of the current audio context.

 This is the time, in seconds, between the browser passing an audio buffer out of an
 audio graph over to the host system's audio subsystem to play, and the time at which the
 first sample in the buffer is actually processed by the audio output device.

It varies depending on the platform and the available hardware.

Value
-----

A double representing the output latency in seconds.

Examples
--------


```js
const audioCtx = new AudioContext();
console.log(audioCtx.outputLatency);
```

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

| Specification |
| --- |
| Web Audio API # dom-audiocontext-outputlatency |

Browser compatibility
---------------------

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

See also
--------

* Using the Web Audio API
* Web Audio API
AudioContext: resume() method
=============================

 The **`resume()`** method of the `AudioContext`
 interface resumes the progression of time in an audio context that has previously been
 suspended.

 This method will cause an `INVALID_STATE_ERR` exception to be thrown if
 called on an `OfflineAudioContext`.

Syntax
------


```js
resume()
```

### Parameters

None.

### Return value

 A `Promise` that resolves when the context has resumed. The promise is
 rejected if the context has already been closed.

Examples
--------

 The following snippet is taken from our AudioContext states demo (see it running live.) When the suspend/resume button is clicked, the
 `AudioContext.state` is queried — if it is `running`,
 `suspend()` is called; if it is
 `suspended`, `resume()` is called. In each case, the text label of
 the button is updated as appropriate once the promise resolves.


```js
susresBtn.onclick = () => {
  if (audioCtx.state === "running") {
    audioCtx.suspend().then(() => {
      susresBtn.textContent = "Resume context";
    });
  } else if (audioCtx.state === "suspended") {
    audioCtx.resume().then(() => {
      susresBtn.textContent = "Suspend context";
    });
  }
};
```

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

| Specification |
| --- |
| Web Audio API # dom-audiocontext-resume |

Browser compatibility
---------------------

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

See also
--------

* Using the Web Audio API
* Web Audio API
AudioContext: getOutputTimestamp() method
=========================================

 The
 **`getOutputTimestamp()`** method of the
 `AudioContext` interface returns a new `AudioTimestamp` object
 containing two audio timestamp values relating to the current audio context.

The two values are as follows:

* `AudioTimestamp.contextTime`: The time of the sample frame currently
 being rendered by the audio output device (i.e., output audio stream position), in the
 same units and origin as the context's `AudioContext.currentTime`.
 Basically, this is the time after the audio context was first created.
* `AudioTimestamp.performanceTime`: An estimation of the moment when the
 sample frame corresponding to the stored `contextTime` value was rendered
 by the audio output device, in the same units and origin as
 `performance.now()`. This is the time after the document containing the
 audio context was first rendered.
Syntax
------


```js
getOutputTimestamp()
```

### Parameters

None.

### Return value

An `AudioTimestamp` object, which has the following properties.

* `contextTime`: A point in the time coordinate system of the
 `currentTime` for the
 `BaseAudioContext`; the time after the audio context was first created.
* `performanceTime`: A point in the time coordinate system of a
 `Performance` interface; the time after the document containing the audio
 context was first rendered
Examples
--------

 In the following code we start to play an audio file after a play button is clicked,
 and start off a `requestAnimationFrame` loop running, which constantly
 outputs the `contextTime` and `performanceTime`.

You can see full code of this example at output-timestamp (see it live also).


```js
// Press the play button
playBtn.addEventListener("click", () => {
  // We can create the audioCtx as there has been some user action
  if (!audioCtx) {
    audioCtx = new AudioContext();
  }
  source = new AudioBufferSourceNode(audioCtx);
  getData();
  source.start(0);
  playBtn.disabled = true;
  stopBtn.disabled = false;
  rAF = requestAnimationFrame(outputTimestamps);
});

// Press the stop button
stopBtn.addEventListener("click", () => {
  source.stop(0);
  playBtn.disabled = false;
  stopBtn.disabled = true;
  cancelAnimationFrame(rAF);
});

// Helper function to output timestamps
function outputTimestamps() {
  const ts = audioCtx.getOutputTimestamp();
  output.textContent = `Context time: ${ts.contextTime} | Performance time: ${ts.performanceTime}`;
  rAF = requestAnimationFrame(outputTimestamps); // Reregister itself
}
```

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

| Specification |
| --- |
| Web Audio API # dom-audiocontext-getoutputtimestamp |

Browser compatibility
---------------------

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