Strange issue with additive blending of floating point texture framebuffer


I have a simple renderer that renders spherical lights. The renderer simply renders one pass
per light, blending the results with additive blending, writing the results to a texture. The texture
is then displayed with a screen-aligned quad in the usual manner (with an overlay grid, some
axes, and some small spheres indicating the origins of the lights, for debugging purposes).

See the top two images for the results of each light pass. The third image is the result of blending
the two light passes using an RGBA8 framebuffer. However, if I use a 32-bit or 16-bit floating point
texture as the framebuffer’s color buffer, the result is the bottom image, which is clearly not the
result I’d expect.

Having not used floating point textures before: Is this the sort of thing I should be seeing?
Is there something extra I should be doing when rendering to a floating point texture?

Are you somehow generating negative color values for light 0? Try clamping it to zero (lightval = max(vec3(0.0), lightval)). The RGBA8888 textures will implicitly clamp negative values to zero, while RGBA16F/32F textures allow negative color values. You also might be getting -INF values at a certain distance from the light, depending on how you’re doing the attenuation.

Yeah, you definitely have some different math going on there somehow. The colors of the light sources aren’t even the same. Also looks like with the float buffer case you’ve got a replace not a blend going on there.

This seems like a possibility; the blue area starts at the exact radius of the red light. The RGBA8 framebuffer may be masking the issue. Will investigate.

I should mention that, individually, the two passes look the same with the RGBA32f and RGBA16f framebuffers as they do with an RGBA8 framebuffer. It’s only when blending occurs that the above happens.

Yes, seems like attenuation was the problem. Evidently there was a negative infinity being introduced that was clamped into nonexistence when the target was an RGBA8 framebuffer. Thanks for pointing me in the right direction!