Repository navigation
Effects: a renderable keeps its opacity through its effects - #1792
Merged
Merged
Conversation
A renderable drawn through two or more post effects (or through one, on a UIPanel, ProgressBar or Trail, which set postEffectNeedsCapture) is drawn opaque into a render target of its own, and the chain's last blit composites the result. That blit drew with an opaque white tint, so the opacity the renderable was drawn at, its own and its containers', never reached the screen: setOpacity() or a fade did nothing while the effects were on. Fixes #1791. beginPostEffect records the opacity it was begun under, per nesting depth, and endPostEffect hands it to the chain's last blit only, as the blit's tint. The blits between effects stay opaque, and a camera's chain composites whole. Same on WebGL and WebGPU: blitEffect and the batchers' blitTexture take an optional alpha (1 by default). The sprite example's red monster now fades through Outline + Glow. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SeWCkETjW35ZbXDRswV1hx
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.
Description
Fixes #1791: a renderable drawn through two or more post effects ignored its opacity on WebGL and WebGPU.
With two or more effects (or one, on a renderable that sets
postEffectNeedsCapture:UIPanel,ProgressBar,Trail), the renderable is drawn opaque into a render target of its own, and the chain's last blit composites the result onto the screen. That blit drew with an opaque white tint, so the opacity the renderable was drawn at, its own and its containers', never reached the screen.setOpacity()or a fading tween changed nothing while the effects were on. With one effect drawn straight on the sprite it always worked, and Canvas never had the bug.It was the opacity being dropped, not a shader problem: every effect already multiplies by the vertex color, which a blit set to opaque white.
beginPostEffectrecords the opacity it was begun under, one slot per nesting depth, next to the projection it already saves.endPostEffectpasses it to the chain's last blit only, as the blit's tint. The ping-pong blits between effects stay opaque, so the opacity is applied once. A camera's chain composites whole, as before.blitEffect(and the batchers'blitTexture) take an optionalalpha, 1 by default, so existing callers are unchanged.Same change on WebGL (
QuadBatcher,LitQuadBatcher) and WebGPU (WebGPUQuadBatcher).Example: the sprite example's red monster now wears Outline + Glow while it fades, so the case stays in view.
Type of change
Checklist
pnpm lintpasses): eslint and biome on the changed files,tscon melonjspnpm testpasses): 364 files, 9096 testspnpm build)Tests:
tests/effect-chain-opacity.spec.js(new, WebGL pixels): a white sprite at opacity 0.2 over black reads 51 through 0, 1, 2 and 3 effects; an opaque one stays 255; a parent's opacity multiplies in; a chain inside a chain lands at both opacities once each;"lighter"at 0.5 matches the one-effect result; one effect withpostEffectNeedsCapturefades; a camera chain stays whole.tests/webgpu_post_effect_flow.spec.js: the alpha each blit gets, for a sprite chain, a camera chain and nested chains.Checked in a browser: in the sprite example the two-effect monster stays solid before the fix and fades with the others after it, on WebGPU and WebGL; Canvas fades as before. No console errors.
🤖 Generated with Claude Code
https://claude.ai/code/session_01SeWCkETjW35ZbXDRswV1hx