Skip to content

Support dynamic cookie textures with clustered lighting#8930

Merged
mvaligursky merged 1 commit into
mainfrom
mv-clustered-light-cookies
Jun 19, 2026
Merged

Support dynamic cookie textures with clustered lighting#8930
mvaligursky merged 1 commit into
mainfrom
mv-clustered-light-cookies

Conversation

@mvaligursky

Copy link
Copy Markdown
Contributor

Fixes #4926. The clustered lighting cookie atlas assumed cookie textures were static — a cookie was only copied into the shared atlas when the light's atlas slot was (re)assigned. Dynamic cookies such as a video or a procedurally updated texture were therefore frozen at their first frame (the documented workaround was to disable clustered lighting).

Changes:

  • Texture now stamps an uploadVersion (from device.renderVersion) on every content upload in markForUpload(), so content changes — including same-size video frame uploads — are detectable. renderVersionDirty only tracks property/bind-group changes and never fires for plain content uploads, so a new counter was needed.
  • Each Light records the uploadVersion it last copied into the cookie atlas. The cookie render pass re-blits a cookie whenever its texture's uploadVersion differs from that, in addition to the existing slot-reassignment and device-restore cases. Tracking is per-light (not a single global high-water mark) so a cookie that animates while its light is off-screen or unallocated is not permanently skipped.

Examples:

  • New example graphics/clustered-light-cookies: four spot lights project cookies onto a chess board, two using a procedurally generated cookie regenerated every few frames and two using a video cookie uploaded every frame. The shared cookie atlas is drawn in the corner to show it re-rendering as the content changes.

Performance:

  • Static cookies are unaffected — still copied into the atlas once. Dynamic cookies cost one extra atlas blit per content change (e.g. one per frame for a video cookie).

The clustered lighting cookie atlas assumed cookie textures were static and
only blitted a cookie into the atlas when its slot was (re)assigned, so video
or procedurally updated cookies were frozen at their first frame.

Texture now stamps an uploadVersion (device.renderVersion) on every content
upload, and each light tracks the uploadVersion it last copied into the atlas,
so the cookie renderer re-blits when the content changes.
@github-actions

Copy link
Copy Markdown

Build size report

This PR changes the size of the minified bundles.

Bundle Minified Gzip Brotli
playcanvas.min.js 2277.3 KB (+0.2 KB, +0.01%) 584.8 KB (+0.1 KB, +0.01%) 454.7 KB (−0.1 KB, −0.03%)
playcanvas.min.mjs 2274.7 KB (+0.2 KB, +0.01%) 583.9 KB (+0.1 KB, +0.01%) 454.2 KB (+0.2 KB, +0.05%)

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes clustered-lighting cookie atlasing for dynamic cookie textures (e.g. video textures or procedurally updated textures). It introduces a content-change version stamp on Texture uploads and uses it to decide when a light’s cookie needs re-blitting into the shared cookie atlas, removing the previous “static cookie” assumption.

Changes:

  • Add Texture.uploadVersion, stamped on every content upload (markForUpload()), to detect pixel-content changes independent of renderVersionDirty.
  • Track per-light cookieRenderVersion and re-blit a cookie into the atlas when the cookie texture’s uploadVersion changes (plus existing slot reassignment / device restore paths).
  • Add a new example demonstrating both procedural and video cookies updating correctly under clustered lighting.

Reviewed changes

Copilot reviewed 4 out of 6 changed files in this pull request and generated no comments.

File Description
src/scene/renderer/render-pass-cookie-renderer.js Re-blits cookies into the clustered cookie atlas when texture content changes (via uploadVersion), not just on slot reassignment / force copy.
src/scene/light.js Adds per-light cookieRenderVersion to remember which cookie content version was last copied into the atlas.
src/platform/graphics/texture.js Adds uploadVersion and stamps it in markForUpload() so content uploads can be detected by downstream systems.
examples/src/examples/graphics/clustered-light-cookies.example.mjs New example showcasing dynamic cookies (procedural + video) updating in the clustered cookie atlas.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@mvaligursky mvaligursky merged commit a2522d9 into main Jun 19, 2026
11 checks passed
@mvaligursky mvaligursky deleted the mv-clustered-light-cookies branch June 19, 2026 11:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: graphics Graphics related issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Clustered lighting cookie renderer should support changes to the texture.

2 participants