TL;DR: What values are clamped and under what circumstances (enabled flags and renderbuffer types (esp. RGBA_F32)), when blending is enabled?
The mechanisms I have found for clamping:
glClampColor
): This appears to control glReadPixels
, but there are extension flags GL_CLAMP_VERTEX_COLOR
and GL_CLAMP_FRAGMENT_COLOR
which do "something". As far as I can tell from the extension spec., they clamp the output from the vertex or fragment shader.glBlendFunc
: "All scale factors have range [0,1]." Does this mean the source and destination factors are clamped before the equation happens?glBlendEquation
: "For these equations all color components are understood to have values in the range [0,1]." Does this mean the source and destination colors are clamped before the equation happens?In my experiments on an RGBA_F32 render target, none of these modes of clamping happen (I confirm this by reading back values from the render target with glGetTexImage
). I need preferably (3) to occur, but I am requesting clarification on the documentation so that I can figure it out myself.
Part of the stuff you quoted is very old, and there might lie the root of the confusion. I'm going through your points from the perspective of modern GL, and I'm going to cite the OpenGL 4.5 core profile spec for this. However, none of that is specific to OpenGL 4.x. This is basically unchanged since GL 3.2 core.
1. glClampColor()
's only remaining function is clamping during glReadPixels
. Quoting the spec on page 680:
Note that the
FrontFace
andClampColor
commands are not deprecated, as they still affect other non-deprecated functionality; however, theClampColor
targetsCLAMP_VERTEX_COLOR
andCLAMP_FRAGMENT_COLOR
are deprecated."
Clamping the vertex shader output did only make sense for the depracted builtin varyings like gl_FrontColor
, gl_BackColor
and so on. Those were only needed to mimic the fixed-function vertex processing, and were never a good idea to use at all. With generic outputs, the GL has no chance to know which values are colors and which one's aren't.
2. The situation for the fragment shader is similiar. With modern rendering approaches, the outputs aren't necessarily colors any more, but represent generic data, so implicitly clamping the values is harmful. You always can manually clamp the values in the shader if you want to.
The quote from the spec Reto Koradi's answer is unchanged in the GL 4.5 spec. The shader outputs will only be clamped if the respective render target is of fixed-point or integer format.
3.,4. and 5. Those documentations are outdated. The GL spec has this to say about this in section 17.3.8:
If the color buffer is fixed-point, the components of the source and destination values and blend factors are each clamped to [0; 1] or [-1; 1] respectively for an unsigned normalized or signed normalized color buffer prior to evaluating the blend equation. If the color buffer is floating-point, no clamping occurs. The resulting four values are sent to the next operation. Blending applies only if the color buffer has a fixed-point or floating-point format. If the color buffer has an integer format, proceed to the next operation.
The clamping of the blending result happens in the next step, which handles the optional sRGB conversion (however, the clamping step there is not tied to the sRGB conversion). Quoting section 17.3.9:
The resulting cs values for R, G, and B, and the unmodified A form a new RGBA color value. If the color buffer is fixed-point, each component is clamped to the range [0; 1] and then converted to a fixed-point value using equation 2.3. The resulting four values are sent to the subsequent dithering operation.
So yes, when using a GL_RGBA32F
framebuffer, no implicit clamping happens at all. And actually, this is the only useful mode of operation for the generic case. If you need some clamping to occur at step 3: just clamp the factors before you send them to glBlendFunc()
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With