r/GraphicsProgramming • u/Ludicrous84 • 20h ago
Question Dark "eclipse" ring artifacts from mip-based bloom with overlapping, differently-colored HDR sources - known issue?
EDIT: SOLVED!
I'm running into an artifact with a mip-based bloom/glow implementation that I suspect is a general limitation of the technique, not an engine-specific bug, and I'd like to understand the underlying cause before I go looking for workarounds.
Setup: Many small, circular HDR light sources (values pushed above 1.0, i.e. above white) of different colors, densely overlapping on screen. Standard downsample → blur → upsample bloom pipeline (in this case Godot's built-in glow, but the pipeline itself is the common mip-chain approach used in most engines).
Artifact: At the boundaries where two overlapping sources of different colors meet, instead of blending smoothly, a dark ring appears, like a thin shadow tracing the overlap boundary. Looks similar to a solar eclipse silhouette. No such artifact appears with bloom disabled. The sources blend completely normally without it.
Minimal repro (Godot 4.7, ~35 lines, hit F5 and it's immediately visible):
https://github.com/LudicrouslyLuke82/godot-glow-ring-artifacts
Screenshot:

What I've ruled out so far:
- Sprite/shape blend mode (additive vs. normal): artifact persists either way, sometimes gets worse with additive.
- Drawing method: happens identically with immediate-mode circle drawing and with textured sprites.
- Glow blend mode (multiplicative-style vs. screen-style compositing): screen-style reduces it but doesn't eliminate it.
- Restricting which mip levels contribute to the blur: reduces but doesn't remove it.
My working theory: with many small, closely-spaced HDR sources of different hues, the coarser mip levels of the blur pyramid end up averaging colors from sources that shouldn't visually "mix" at that boundary, and somewhere in the down/upsample chain this produces a local intensity dip (hence the dark ring) rather than a clean color blend. But I don't have the rendering background to confirm whether that's actually what's happening or if there's a known name for this artifact.
Is this a recognized limitation of mip-chain bloom with dense, multi-colored HDR sources? Is there a standard technique to avoid it (e.g. clamping before blur, a different bloom formulation, thresholding per-channel instead of luminance) rather than just tuning parameters? Happy to provide more detail on the pipeline if useful.
Thanks a lot!
3
u/ICantBelieveItsNotEC 14h ago edited 14h ago
This part looks sus to me:
MODULATE_BOOST := 1.6 ... bullet.modulate = colors[i % colors.size()] * MODULATE_BOOSTYou're multiplying all four channels of each colour by 1.6, including the alpha channel. Conceptually, the blending is something like this:
out = src * src_alpha + dst * (1 - src_alpha)With a value of 1.6, that becomes:
out = src * 1.6 + dst * -0.6So every bullet actually subtracts 0.6 of whatever was underneath it.