了解在不同渲染目标上的 OpenGL 混合中何时以及什么值被限制

Untangling When and What Values are Clamped in OpenGL Blending on Different Render Targets

TL;DR:当启用混合时,在什么情况下(启用标志和渲染缓冲区类型(尤其是 RGBA_F32)会限制哪些值?


我发现的夹紧机制:

  1. Shader output (via glClampColor):这貌似控制了glReadPixels,但是还有extension flags GL_CLAMP_VERTEX_COLORGL_CLAMP_FRAGMENT_COLOR 做 "something"。据我从扩展规范中得知,它们限制了顶点或片段着色器的输出。
  2. 着色器输出(通过渲染到定点):参见this answer which quotes the GL spec.: "The conversion from a floating-point value f to the corresponding unsigned normalized fixed-point value c is defined by first clamping f to the range [0, 1] . . ." By contrast, (when writing to a floating point render target, presumably), Nicol Bolas writes here片段着色器写入的内容将始终被松开.".
  3. 隐含钳位:来自documentation for glBlendFunc:“所有比例因子的范围为[0,1]。”这意味着源和目标因素在等式发生之前被限制了吗?
  4. 隐含钳位:来自documentation for glBlendEquation:“对于这些等式,所有颜色分量都被理解为具有范围 [0,1 ]." 这是否意味着源颜色和目标颜色在等式发生之前被限制?
  5. 结果限制: 来自同一页:“这些方程的结果限制在 [0,1]. 范围内“

在我对 RGBA_F32 渲染目标的实验中,发生了 none 这些钳位模式(我通过使用 glGetTexImage 从渲染目标读取回值来确认这一点)。我最好需要 (3) 发生,但我要求对文档进行澄清,以便我自己弄清楚。

你引用的部分内容很旧,可能是混淆的根源。我将从 modern GL 的角度阐述您的观点,我将为此引用 OpenGL 4.5 core profile 规范。但是,其中 none 特定于 OpenGL 4.x。这个从GL 3.2 core开始基本没变。

1. glClampColor() 唯一剩余的功能是在 glReadPixels 期间进行钳位。引用第 680 页上的规范:

Note that the FrontFace and ClampColor commands are not deprecated, as they still affect other non-deprecated functionality; however, the ClampColor targets CLAMP_VERTEX_COLOR and CLAMP_FRAGMENT_COLOR are deprecated."

钳制顶点着色器输出只对像 gl_FrontColorgl_BackColor 等 depracted 内置变量有意义。这些只需要模仿固定功能的顶点处理,根本不是一个好主意。对于通用输出,GL 没有机会知道哪些值是颜色,哪些不是。

2.片段着色器的情况类似。使用现代渲染方法,输出不再一定是颜色,而是代表通用数据,因此隐式限制值是有害的。如果需要,您始终可以在着色器中手动限制值。

规范 Reto Koradi 的回答中的引用在 GL 4.5 规范中没有变化。只有当相应的渲染目标是定点或整数格式时,着色器输出才会被限制。

3.,4. 5. 这些文件已经过时了。 GL 规范在第 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.

混合结果的钳位发生在下一步,它处理可选的 sRGB 转换(但是,那里的钳位步骤 与 sRGB 转换相关联)。引用第 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.

所以是的,当使用 GL_RGBA32F 帧缓冲区时,不会 隐式夹紧发生。实际上,这是一般情况下唯一有用的操作模式。如果您需要在第 3 步进行一些限制:只需在将因子发送到 glBlendFunc().

之前限制它们