Investigate WebGL2 upgrade path for Goldberg Polyhedron Paint #2

Open
opened 2026-05-10 16:09:24 +00:00 by mikael-lovqvists-claude-agent · 0 comments

The Goldberg Polyhedron Paint experiment currently targets WebGL1 (OpenGL ES 2.0). This issue tracks an investigation into what WebGL2 (OpenGL ES 3.0) would unlock and whether an upgrade is worthwhile.

What WebGL2 adds

Rendering quality / efficiency

  • Integer vertex attributes — face index could be passed as int, enabling per-face data lookups in a texture rather than duplicating attributes per vertex
  • gl.UNSIGNED_INT index buffers — removes the 65535 vertex limit per draw call
  • Multiple render targets (MRT) — deferred shading pipeline becomes feasible
  • gl.HALF_FLOAT textures — cheaper storage for HDR framebuffers
  • Floating-point render targets without extensions (EXT_color_buffer_float is core)

Shading

  • textureLod / explicit LOD in shaders — useful for environment map sampling in PBR
  • texture2DArray — could store multiple noise/material layers efficiently
  • GLSL ES 3.00 — in/out instead of attribute/varying, flat interpolation (useful for per-face solid color without geometry duplication), proper integer types

Performance

  • Instanced rendering (gl.drawArraysInstanced) — if many identical sub-objects ever appear
  • Uniform Buffer Objects (UBO) — batch light/material uniforms into a single buffer instead of individual gl.uniform* calls
  • Transform feedback — could run relaxation passes on the GPU instead of JS
  • Vertex Array Objects (VAO) are core (not an extension) — reduces bind overhead on redraws
  • gl.PIXEL_PACK_BUFFER for async GPU→CPU readback — face picking currently stalls the pipeline

Texture formats

  • RED, RG internal formats — the PBR buffer (roughness + metallic) currently uses vec2 in a full RGBA texture; a proper RG texture would halve the bandwidth
  • Depth textures usable directly in shaders — shadow mapping becomes straightforward

Specific wins for this project

  1. flat interpolation — the biggest immediate win. Currently every face duplicates position/colour/PBR/noise data for all its triangulated vertices. With flat and an integer face-ID attribute the GPU can do the per-face lookup once, saving significant buffer memory at higher subdivision depths.
  2. Async face pickingPIXEL_PACK_BUFFER would let the readback happen without a GPU stall on every mouse move.
  3. VAO — small but clean; all the enableVertexAttribArray / vertexAttribPointer boilerplate collapses to a single bind.
  4. Transform feedback for relaxation — currently the sphere relaxation loop runs entirely in JS and re-uploads geometry each iteration; GPU-side transform feedback could make higher iteration counts practical.

Browser support

WebGL2 has been baseline since ~2022 (Chrome 56+, Firefox 51+, Safari 15+). There is no meaningful reason to stay on WebGL1 for a non-embedded target.

Suggested next step

Audit the current shader and buffer setup, then migrate incrementally: VAO first (zero functional change, cleaner code), then flat face-ID to cut buffer duplication, then async picking.

The Goldberg Polyhedron Paint experiment currently targets WebGL1 (OpenGL ES 2.0). This issue tracks an investigation into what WebGL2 (OpenGL ES 3.0) would unlock and whether an upgrade is worthwhile. ## What WebGL2 adds **Rendering quality / efficiency** - Integer vertex attributes — face index could be passed as `int`, enabling per-face data lookups in a texture rather than duplicating attributes per vertex - `gl.UNSIGNED_INT` index buffers — removes the 65535 vertex limit per draw call - Multiple render targets (MRT) — deferred shading pipeline becomes feasible - `gl.HALF_FLOAT` textures — cheaper storage for HDR framebuffers - Floating-point render targets without extensions (`EXT_color_buffer_float` is core) **Shading** - `textureLod` / explicit LOD in shaders — useful for environment map sampling in PBR - `texture2DArray` — could store multiple noise/material layers efficiently - GLSL ES 3.00 — `in`/`out` instead of `attribute`/`varying`, `flat` interpolation (useful for per-face solid color without geometry duplication), proper integer types **Performance** - Instanced rendering (`gl.drawArraysInstanced`) — if many identical sub-objects ever appear - Uniform Buffer Objects (UBO) — batch light/material uniforms into a single buffer instead of individual `gl.uniform*` calls - Transform feedback — could run relaxation passes on the GPU instead of JS - Vertex Array Objects (VAO) are core (not an extension) — reduces bind overhead on redraws - `gl.PIXEL_PACK_BUFFER` for async GPU→CPU readback — face picking currently stalls the pipeline **Texture formats** - `RED`, `RG` internal formats — the PBR buffer (roughness + metallic) currently uses `vec2` in a full RGBA texture; a proper `RG` texture would halve the bandwidth - Depth textures usable directly in shaders — shadow mapping becomes straightforward ## Specific wins for this project 1. **`flat` interpolation** — the biggest immediate win. Currently every face duplicates position/colour/PBR/noise data for all its triangulated vertices. With `flat` and an integer face-ID attribute the GPU can do the per-face lookup once, saving significant buffer memory at higher subdivision depths. 2. **Async face picking** — `PIXEL_PACK_BUFFER` would let the readback happen without a GPU stall on every mouse move. 3. **VAO** — small but clean; all the `enableVertexAttribArray` / `vertexAttribPointer` boilerplate collapses to a single bind. 4. **Transform feedback for relaxation** — currently the sphere relaxation loop runs entirely in JS and re-uploads geometry each iteration; GPU-side transform feedback could make higher iteration counts practical. ## Browser support WebGL2 has been baseline since ~2022 (Chrome 56+, Firefox 51+, Safari 15+). There is no meaningful reason to stay on WebGL1 for a non-embedded target. ## Suggested next step Audit the current shader and buffer setup, then migrate incrementally: VAO first (zero functional change, cleaner code), then `flat` face-ID to cut buffer duplication, then async picking.
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mikael-lovqvist/websperiments#2