Skip to content

WebGL Extension docs: EXT_clip_control, EXT_texture_mirror_clamp_to_edge, EXT_texture_norm16 - #46263

Open
hamishwillee wants to merge 4 commits into
mdn:mainfrom
hamishwillee:webgl-new-extensions
Open

hamishwillee wants to merge 4 commits into
mdn:mainfrom
hamishwillee:webgl-new-extensions

Conversation

@hamishwillee

@hamishwillee hamishwillee commented Oct 26, 2026 •

Copy link
Copy Markdown
Collaborator

This provides docs for EXT_clip_control and EXT_texture_mirror_clamp_to_edge, and updates the docs for EXT_texture_norm16 based on testing.

Mostly it comes from the spec, the issue itself, and driving claude to write test code to validate its claims. In other words I've been a meat puppet.
That said it matches what I see in the sources.

I'm not super confident of this API, or Claude, so I've asked for a review (I could have done much less of course and been sure it was right, but I'd rather not throw away potentially useful information).

Related docs work can be tracked in #46144 , #46145, #46146

@github-actions

github-actions Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor
Preview URLs (9 pages)

Flaws (3)

Note! 6 documents with no flaws that don't need to be listed. 🎉

Found an unexpected or unresolvable flaw? Please report it here.

URL: /en-US/docs/Web/API/EXT_clip_control
Title: EXT_clip_control extension
Flaw count: 1

  • macros:
    • Unknown browser-compat entry: api.EXT_clip_control

URL: /en-US/docs/Web/API/EXT_clip_control/clipControlEXT
Title: EXT_clip_control: clipControlEXT() method
Flaw count: 1

  • macros:
    • Unknown browser-compat entry: api.EXT_clip_control.clipControlEXT

URL: /en-US/docs/Web/API/EXT_texture_mirror_clamp_to_edge
Title: EXT_texture_mirror_clamp_to_edge extension
Flaw count: 1

  • macros:
    • Unknown browser-compat entry: api.EXT_texture_mirror_clamp_to_edge

(comment last updated: 2026-10-30 01:46:06)

@hamishwillee hamishwillee left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI notes on the sources for the claims in this PR, and which were tested in browsers. Stacked on #46261: only the last three commits belong to this PR.

- The 16-bit normalized fixed-point types `ext.R16_EXT`, `ext.RG16_EXT` and `ext.RGBA16_EXT` become available as color-renderable formats and renderbuffers and be created in these formats.

WebGL extensions are available using the {{domxref("WebGLRenderingContext.getExtension()")}} method. For more information, see also [Using Extensions](/en-US/docs/Web/API/WebGL_API/Using_Extensions) in the [WebGL tutorial](/en-US/docs/Web/API/WebGL_API/Tutorial).
The **`EXT_texture_norm16`** extension is part of the [WebGL API](/en-US/docs/Web/API/WebGL_API) and provides a set of 16-bit signed normalized and unsigned normalized formats for textures and renderbuffers.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI: Removed "texture buffer": that part of the ES spec only applies with EXT_texture_buffer (see its "Interactions with EXT_texture_buffer" section), and WebGL 2 has no texBuffer().


## Description

The formats provided by this extension store each color component as a 16-bit integer, which shaders read as a floating-point value.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI: "Normalized" is from the ES spec overview ("16 bit signed normalized and unsigned normalized fixed point"). Plain "unsigned" read like the R16UI integer formats.


The formats provided by this extension store each color component as a 16-bit integer, which shaders read as a floating-point value.
Components in the unsigned normalized formats represent values from 0.0 to 1.0, and components in the signed normalized (`SNORM`) formats represent values from -1.0 to 1.0.
All of these formats are texture-filterable, so textures in these formats can be sampled with linear filtering.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI: Spec: ES spec Table 8.13 marks all eight formats texture-filterable (TF column). Verified in Chrome 156: sampling a 2×1 texture halfway between 0 and 1 with LINEAR reads back 127. Firefox 161 does not filter them: the texture is reported incomplete ("the texture's format is not texture-filterable"), because the WebGLExtensionTextureNorm16 constructor in dom/canvas/WebGLExtensions.cpp never sets isFilterable. This documents the spec; a Firefox bug and a BCD note are to follow.


When this extension is enabled:

- The {{domxref("WebGLRenderingContext.texImage2D()")}}, {{domxref("WebGL2RenderingContext.texImage3D()")}}, {{domxref("WebGL2RenderingContext.texStorage2D()")}}, and {{domxref("WebGL2RenderingContext.texStorage3D()")}} methods accept the formats provided by this extension as internal formats.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI: From the ES spec "New Tokens" (internalFormat of TexImage2D, TexImage3D, TexStorage2D, TexStorage3D, …). Checked in Firefox Nightly with no errors: texStorage2D() with RGBA16_SNORM_EXT and texImage3D() with R16_EXT.

- The {{domxref("WebGLRenderingContext.texImage2D()")}}, {{domxref("WebGL2RenderingContext.texImage3D()")}}, {{domxref("WebGL2RenderingContext.texStorage2D()")}}, and {{domxref("WebGL2RenderingContext.texStorage3D()")}} methods accept the formats provided by this extension as internal formats.
The {{domxref("WebGLRenderingContext.texSubImage2D()")}} and {{domxref("WebGL2RenderingContext.texSubImage3D()")}} methods can update textures in these formats.
- The `ext.R16_EXT`, `ext.RG16_EXT`, and `ext.RGBA16_EXT` formats are color-renderable, so textures in these formats can be attached to framebuffers and rendered to.
The {{domxref("WebGLRenderingContext.renderbufferStorage()")}} and {{domxref("WebGL2RenderingContext.renderbufferStorageMultisample()")}} methods also accept these three formats, so that renderbuffers can be created in them.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI: ES spec "New Tokens" lists RenderbufferStorage and RenderbufferStorageMultisample for R16_EXT, RG16_EXT and RGBA16_EXT only. Checked renderbufferStorageMultisample(…, 4, ext.RGBA16_EXT, …) in Firefox Nightly with no errors.


## Description

When this extension is enabled, the {{domxref("WebGLRenderingContext.texParameter()")}} method accepts `ext.MIRROR_CLAMP_TO_EDGE_EXT` as the value of the `gl.TEXTURE_WRAP_S` and `gl.TEXTURE_WRAP_T` parameters, and of the `gl.TEXTURE_WRAP_R` parameter in {{domxref("WebGL2RenderingContext", "WebGL 2", "", 1)}} contexts.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI: The WebGL spec's "New Tokens" list texParameterf/i and samplerParameterf/i with TEXTURE_WRAP_S, TEXTURE_WRAP_T and TEXTURE_WRAP_R. TEXTURE_WRAP_R and samplers only exist in WebGL 2.

- For texture coordinates from -1 to 0, the texture is sampled as if it were mirrored at coordinate 0.
- For texture coordinates less than -1 or greater than 1, the texels at the edge of the texture are used, in the same way as with `gl.CLAMP_TO_EDGE`.

This allows an image that is symmetric, such as a glow, a vignette, or a lens flare, to be stored as a texture that contains only half of it, or only a quarter of it when the mode is used for both texture coordinates.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI: Derived from the wrap formula and the ES overview ("effectively uses a texture map twice as large as the original image"); the spec doesn't give this use case.

const ext = gl.getExtension("EXT_texture_mirror_clamp_to_edge");
```

### Drawing a symmetric image from a quarter of it

@hamishwillee hamishwillee Oct 26, 2026 •

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI: Run in headless Chromium 153 (SwiftShader), WebGL 1 and 2: the quarter-glow example draws a full glow that is symmetric in x and y, and the getTexParameter() line is true. In the sampler example, the sampler's wrap mode overrides the texture's REPEAT, but as written (wrap modes only) the sampler keeps its default NEAREST_MIPMAP_LINEAR min filter, so a texture without mipmaps samples as black.

</td>
</tr>
<tr>
<td><code>ext.CLIP_ORIGIN_EXT</code></td>

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI: From the WebGL spec "New Tokens": getParameter() accepts CLIP_ORIGIN_EXT and CLIP_DEPTH_MODE_EXT and returns a GLenum.

<code>gl.REPEAT</code> (default value), <code>gl.CLAMP_TO_EDGE</code>,
<code>gl.MIRRORED_REPEAT</code>.
<code>gl.MIRRORED_REPEAT</code>,
<code>ext.MIRROR_CLAMP_TO_EDGE_EXT</code> (when using the

@hamishwillee hamishwillee Oct 26, 2026 •

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI: From the WebGL spec "New Tokens". Also added to getTexParameter(), which returns the current wrap mode: verified in headless Chromium 153 (SwiftShader) for TEXTURE_WRAP_S and TEXTURE_WRAP_T in WebGL 1, and also TEXTURE_WRAP_R in WebGL 2.

@hamishwillee
hamishwillee marked this pull request as ready for review October 26, 2026 08:23
@hamishwillee
hamishwillee requested review from a team as code owners October 26, 2026 08:23
@hamishwillee
hamishwillee requested review from dipikabh and wbamberg and removed request for a team October 26, 2026 08:23
hamishwillee and others added 4 commits October 30, 2026 12:44
- Move usage notes into a Description section
- Drop "texture buffer": WebGL 2 has no texture buffers
- Describe the formats as unsigned/signed normalized, and what that
  means for shader values
- Note that all formats are texture-filterable
- List the other methods that accept the formats (texImage3D,
  texStorage2D/3D, renderbufferStorageMultisample)
- Note that data can be uploaded from typed arrays, and that DOM
  sources such as images and canvases generate an error

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- New EXT_clip_control and clipControlEXT() pages
- Add the extension to the WebGL sidebar, the WebGL API landing page,
  and the Using extensions list
- Add CLIP_ORIGIN_EXT and CLIP_DEPTH_MODE_EXT to getParameter()

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- New EXT_texture_mirror_clamp_to_edge page
- Add the extension to the WebGL sidebar, the WebGL API landing page,
  and the Using extensions list
- Add MIRROR_CLAMP_TO_EDGE_EXT as a wrap value to texParameter() and
  getTexParameter()

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- EXT_clip_control: zero-to-one depth still goes through depthRange();
  reversed-Z example uses antialias: false so the final blit to the
  canvas works; clarity edits to the description and example prose
- clipControlEXT(): simpler wording; link to the reversed-Z section
- EXT_texture_mirror_clamp_to_edge: coordinates below -1 use the edge
  at coordinate 1; sampler example sets a min filter so non-mipmapped
  textures aren't incomplete; clarity edits
- EXT_texture_norm16: wording fixes
- Fix the "Using Extensions" boilerplate line on all three pages

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added size/m [PR only] 51-500 LoC changed and removed size/l [PR only] 501-1000 LoC changed labels Oct 30, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Content:WebAPI Web API docs size/m [PR only] 51-500 LoC changed

1 participant