Skip to content

fix(rendering): keep bloom's glow purely additive over lower layers - #693

Merged
stormmuller merged 4 commits into
devfrom
claude/modest-cannon-h79jl5
Oct 3, 2026
Merged

stormmuller merged 4 commits into
devfrom
claude/modest-cannon-h79jl5

Conversation

@stormmuller

Copy link
Copy Markdown
Member

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 outputs vec4(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 writes 0.
  • New e2e scene and spec, bloom-over-background: a bloomed foreground layer drawing a yellow sprite is presented over a background layer cleared to Color(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.
  • Docs (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-types passes with 0 errors
  • npm test passes (1731 tests)
  • npm run lint passes with 0 errors (2 existing TODO warnings)
  • npm run cspell passes with 0 errors
  • npm run check-exports passes (after npm run build)
  • Any new/changed public API is exported from the module's index.ts: no public API changed
  • Documentation under /documentation-site/docs/docs is updated (rendering/bloom.md)
  • Demos that use bloom (space-shooter, text) were checked after npm run build: docs-site typecheck and build pass, 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.
  • The full e2e suite passes 3× with --repeat-each 3. This was run against the locally installed Chromium build, because the container lacks the build pinned for @playwright/test. The existing check-types:e2e errors in text-effects-overlap.ts are also present on dev.

Changelog

  • A bullet has been added under ## [Unreleased] in CHANGELOG.md (#### Fixed)

🤖 Generated with Claude Code

https://claude.ai/code/session_016Ldg64ToB3cSB6sDGbpLt8


Generated by Claude Code

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

codecov Bot commented Oct 3, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@stormmuller
stormmuller enabled auto-merge (squash) October 3, 2026 10:09
claude and others added 2 commits October 3, 2026 10:52
…79jl5

# Conflicts:
#	CHANGELOG.md
#	documentation-site/docs/docs/rendering/bloom.md
#	src/rendering/shaders/post-process/bloom-threshold.frag.glsl
@stormmuller
stormmuller merged commit 07361a6 into dev Oct 3, 2026
12 checks passed
@stormmuller
stormmuller deleted the claude/modest-cannon-h79jl5 branch October 3, 2026 12:07
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