Skip to content

Fix volumetric fog missing for one frame after a canvas resize - #9283

Merged
mvaligursky merged 1 commit into
mainfrom
claude/fog-scene-color-alias-resize
Sep 3, 2026
Merged

Fix volumetric fog missing for one frame after a canvas resize#9283
mvaligursky merged 1 commit into
mainfrom
claude/fog-scene-color-alias-resize

Conversation

@mvaligursky

Copy link
Copy Markdown
Contributor

The volumetric fog examples lose the fog for exactly one frame right after the window is resized.

With the volumetric fog enabled, CameraFrame renders the scene depth as an additional attachment of the scene render target. The fog combine pass samples that depth, so it cannot render into the render target it is attached to, and renders into rtSceneColor instead - an alias wrapping the same color texture without the depth. That alias has no pass of its own to resize it, so FramePassCameraFrame.frameUpdate resized it from the scene render target's dimensions.

FrameGraph.addRenderPass updates a frame pass before the passes it owns, though, and the scene render target is resized by the scene pass - one of them. On the frame the canvas resizes the alias was therefore resized to the previous size, and the this.rt.resize() which followed replaced the shared texture's GPU object while the alias kept a framebuffer attached to the one it replaced. The combine pass drew the fog into an orphaned surface nothing samples, with a stale viewport. This failed silently, as checkFramebufferStatus still reports the framebuffer as complete - WebGL keeps a deleted but attached texture alive.

Changes:

  • Evaluate the size of the scene color alias the same way the scene pass evaluates the size of the render target it shares its texture with, instead of reading it back from that render target a frame stale.

Verified on WebGL2 by stepping the frame graph one frame at a time across a resize, growing and shrinking: the alias' framebuffer now keeps the live texture and its viewport matches, and a canvas readback on the resize frame matches the frame which follows it rather than a fog-disabled reference.

The fog combine pass renders into rtSceneColor, an alias of the scene
render target wrapping the same color texture without the scene depth
attachment it samples. That alias has no pass of its own to resize it, so
the camera frame pass resized it from the scene render target's
dimensions - but FrameGraph.addRenderPass updates a frame pass before the
passes it owns, and the scene render target is resized by the scene pass,
one of them.

On the frame the canvas resized, the alias was therefore resized to the
previous size, and the following this.rt.resize() replaced the shared
texture's GPU object while the alias kept a framebuffer attached to the
one it replaced. The combine pass drew the fog into an orphaned surface
nothing samples, with a stale viewport.

Evaluate the size the same way the scene pass evaluates it instead of
reading it back a frame stale.
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown

Build size report

This PR changes the size of the minified bundles.

Bundle Minified Gzip Brotli
playcanvas.min.js 2398.2 KB (+0.1 KB, +0.00%) 616.9 KB (+0.0 KB, +0.01%) 478.5 KB —
playcanvas.min.mjs 2395.6 KB (+0.1 KB, +0.00%) 615.5 KB (+0.0 KB, +0.01%) 478.0 KB (−0.0 KB, −0.01%)

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.

🟢 Approval recommended

The change is small, localized, and aligns the alias sizing logic with the existing render-pass resize evaluation to eliminate the observed one-frame resize hazard.

Pull request overview

This PR fixes a one-frame loss of volumetric fog immediately after a canvas resize by ensuring the “scene color only” alias render target (used when sampling scene depth) is resized based on the same resize inputs as the scene pass, rather than reading stale dimensions from the scene render target.

Changes:

  • Compute rtSceneColor resize dimensions from the scene pass’ resizeSource and scaleX/scaleY (matching RenderPass.frameUpdate sizing logic).
  • Avoid a stale-size resize that could orphan the fog combine pass’ framebuffer attachment for the resize frame.
File summaries
File Description
src/extras/render-passes/frame-pass-camera-frame.js Resizes the scene-color alias using the scene pass’ resize inputs to prevent a one-frame mismatch after canvas resize.
Review details
  • Files reviewed: 1/1 changed files
  • Comments generated: 0
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@mvaligursky
mvaligursky merged commit 304cb18 into main Sep 3, 2026
11 checks passed
@mvaligursky
mvaligursky deleted the claude/fog-scene-color-alias-resize branch September 3, 2026 08:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants