Skip to content

Lighting: uniform buffer objects for light data (raise MAX_LIGHTS, modernize the lit shaders to GLSL ES 3.00) #1552

Description

@obiot

Summary

Move the per-light uniform data (uLightDir[], uLightColor[], uLightCount, uAmbient, and the 3D equivalents) out of individual uniform arrays and into a uniform buffer object, uploaded once per frame instead of set with N gl.uniform* calls. This requires porting the lit shaders to GLSL ES 3.00, and lets MAX_LIGHTS rise well above its current value of 8.

Motivation

MAX_LIGHTS = 8 (video/webgl/lighting/constants.ts) is not a design choice — it exists to keep the GLSL uniform arrays comfortably inside conservative per-shader uniform limits. Scenes that want more than 8 simultaneous lights silently drop the extras.

A UBO removes that pressure: light data becomes one buffer bound to a block, sized by the buffer rather than by the uniform-slot budget, and updated with a single bufferSubData instead of per-light uniform calls.

Prerequisite: GLSL ES 3.00 for the lit shaders

Uniform blocks do not exist in GLSL ES 1.00 — they were introduced in ES 3.00, and WebGL 2 only accepts them in #version 300 es shaders. The lit shaders are ES 1.00 today (varying, plain uniform vec3 uLightDir[__MAX_LIGHTS__]).

So this ticket is the first legitimate trigger of the rule set in #1509: individual shaders migrate to ES 3.00 when they need an ES 3.00 feature — as opposed to a wholesale dialect rewrite, which remains explicitly out of scope (the ShaderEffect wrapper and user-authored effect bodies stay ES 1.00; mixed dialects already coexist per-program, e.g. the ES 3.00 GPU tilemap shader).

Shaders in scope:

  • video/webgl/shaders/mesh-lit.frag / mesh-lit.vert
  • video/webgl/shaders/quad-multi-lit.vert
  • the video/webgl/shaders/multitexture-lit.js generator

JS side: video/webgl/lighting/pack.ts and pack3d.ts already pack light data into flat arrays, so they are the natural place to write std140-laid-out buffer contents instead.

Scope

  • Port the four lit shader sources to #version 300 es (attributein, varyingin/out, texture2Dtexture, explicit out fragment color). utils/precision.js is already #version-aware; utils/attributes.js already parses both dialects.
  • Declare a std140 uniform block for the light array; bind it with bindBufferBase / uniformBlockBinding.
  • Have pack.ts / pack3d.ts write std140-compatible layouts (mind vec3 padding to 16 bytes — the classic std140 trap).
  • Raise MAX_LIGHTS, driven by the buffer size rather than uniform slots; pick a new cap and document it.
  • Visual verification of the lit paths (spriteIlluminator, lights, the 3D lit mesh examples) — these are pixel-visible changes.

Relationship to the WebGPU backend (#1184) — honest scoping

This is not strict WebGPU groundwork, and shouldn't be justified as such:

  • The WebGPU backend rewrites these shaders in WGSL regardless, so the GLSL uniform-block work does not port.
  • The GL UBO API (bindBufferBase, uniformBlockBinding) has no WebGPU counterpart either.
  • What does transfer is the JS-side model: pack a struct into a typed array and upload it once, rather than issuing N loose uniform calls. That is exactly the WebGPU shape (write a buffer, bind a bind group), so the packing code in pack.ts / pack3d.ts gains lasting value.

Contrast with #1551, where the artifact being made neutral is a shared JS record both backends read directly — that one transfers whole. This one is mostly a WebGL 2 improvement in its own right, with a WebGPU-shaped side effect.

Scheduling

No ordering constraint — nothing in #1507, #1508, #1551 or #1184 depends on this landing first. Best picked up whenever lighting work comes up naturally. The headline is "more lights, modernized lit shaders"; WebGPU-shaped uniform packing is a bonus, not the reason.

Related: #1509 (established the "migrate a shader to ES 3.00 only when it needs a 3.00 feature" rule), #1184, #1536.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions