fix(rendering): keep bloom's glow purely additive over lower layers - #693
Merged
Merged
Conversation
The bloom composite raised the target's alpha to the halo's own, which made the glow partly cover whatever was presented beneath the camera's render target and replace it with glow color. Render targets are presented as premultiplied alpha, so the glow only needs to be added to the color: keep the scene's alpha, and drop the now-unused alpha from the threshold pass. Adds an e2e scene/spec that presents a bloomed foreground over a blue background and checks the yellow glow never lowers the blue channel. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016Ldg64ToB3cSB6sDGbpLt8
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
stormmuller
enabled auto-merge (squash)
October 3, 2026 10:09
…79jl5 # Conflicts: # CHANGELOG.md # documentation-site/docs/docs/rendering/bloom.md # src/rendering/shaders/post-process/bloom-threshold.frag.glsl
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The bloom composite set the target's alpha to
max(scene.a, bloom.a * u_intensity). That made the halo partly cover whatever was presented beneath the camera's render target, such as a background camera's layer, and replace it with glow color. A yellow glow over a blue background reduced the blue.Render targets are presented as premultiplied alpha (
ONE, ONE_MINUS_SRC_ALPHA), so the glow only needs to be added to the color. It still shows past the sprite's silhouette, over fully transparent pixels.bloom-composite.frag.glsl: now outputsvec4(scene.rgb + bloom.rgb * u_intensity, scene.a). The comment that described the old alpha blending is rewritten.bloom-threshold.frag.glsl: the threshold pass's alpha (the averaged contribution) had no use left, so it now writes0.bloom-over-background: a bloomed foreground layer drawing a yellow sprite is presented over a background layer cleared toColor(0.1, 0.3, 0.8). The spec reads back the row next to the sprite and checks two things: the glow raises red past the sprite's edge, and blue never falls below its value far from the sprite. With the old shaders the spec fails, with blue dropping from 204 to 33 next to the sprite. With the fix it passes.rendering/bloom.md) and AGENTS.md's premultiplied-alpha section updated to match.One edge case: if a bloomed camera is the only layer, cleared to transparent and presented straight onto the canvas, its glow pixels now have color but alpha
0. Chromium composites these onto the page as added light.Related issue(s)
Fixes the reported defect "010: Bloom's halo is partly opaque, so it dims the layers behind it instead of only adding light".
Verification checklist
npm run check-typespasses with 0 errorsnpm testpasses (1731 tests)npm run lintpasses with 0 errors (2 existing TODO warnings)npm run cspellpasses with 0 errorsnpm run check-exportspasses (afternpm run build)index.ts: no public API changed/documentation-site/docs/docsis updated (rendering/bloom.md)npm run build: docs-sitetypecheckandbuildpass, and both pages were loaded in headless Chromium. The space shooter's bullets still glow over the background layer, and the pages showed no errors apart from an external resource that the sandbox network blocked.--repeat-each 3. This was run against the locally installed Chromium build, because the container lacks the build pinned for@playwright/test. The existingcheck-types:e2eerrors intext-effects-overlap.tsare also present ondev.Changelog
## [Unreleased]inCHANGELOG.md(#### Fixed)🤖 Generated with Claude Code
https://claude.ai/code/session_016Ldg64ToB3cSB6sDGbpLt8
Generated by Claude Code