【openGL4.x手册13】色彩混合blend

一、说明

   混合是 OpenGL 渲染管道的阶段,它从片段着色器获取片段颜色输出,并将它们与这些输出映射到的颜色缓冲区中的颜色组合在一起。混合参数可以允许以各种方式组合每个输出的源颜色和目标颜色。

二、透明度

   透明度排序
   混合可用于使对象看起来透明。这不是它的唯一用途,而是它的主要用途之一。这样做需要你采取某些步骤,其中一些步骤很难处理。有关详细信息,请参阅链接页面。

三、片段输出

   OpenGL 管道的片段处理阶段的结果,无论是否使用片段着色器,都是零个或多个颜色值。片段处理还有其他输出,但混合仅处理颜色。

   这些颜色必须写入当前帧缓冲区中的零个或多个颜色缓冲区。通过调用 glDrawBuffers 或 glDrawBuffer,每个片段输出颜色都与特定缓冲区匹配(或丢弃)。安排匹配后,可以将颜色写入该缓冲区。

   当混合处于活动状态时,来自片段处理器的输入颜色不仅会覆盖输出缓冲区中当前的相应值,而且会根据函数将两种颜色组合在一起。

四、绘制缓冲区混合

ARB 扩展 ARB_draw_buffers_blend
   鉴于此功能的可用性,用户可以为每个缓冲区指定不同的混合参数或方程式。

   注意:所有 AMD/ATI 3.x 级硬件(HD2000、3000 和 4000 系列)都实现了ARB_draw_buffers_blend。NVIDIA 的 4.0 之前的硬件无法实现这一点。
   如果此功能可用,则对于下面描述的每个函数,都有一个等效的函数,该函数的名称末尾有一个“i”(扩展版本为“iARB”)。此函数在开头采用一个附加参数,即一个无符号整数,表示绘制缓冲区索引,此函数调用要更改其混合数据。因此,给定函数 glBlendFuncSeparate,有一个 glBlendFuncSeparatei,其第一个参数是绘制缓冲区索引。

   请注意,glEnablei/glDisablei 函数不是此功能的一部分。启用/禁用与特定缓冲区的混合功能是 3.0 的核心功能。而绘制缓冲区混合是关于为不同缓冲区指定不同混合参数的能力。

五、源、目标和缓冲区

   片段着色器可以写入多种颜色。这些颜色通过 glDrawBuffers 映射到 Framebuffer 中的特定图像。在每个片段着色器输出值上独立进行混合。

   混合操作在源颜色和目标颜色之间进行。源颜色是片段着色器写入的值。目标颜色是帧缓冲区中图像的颜色。在讨论源颜色和目标颜色时,将使用粗体字来表示颜色。颜色 S 是源颜色;颜色 D 是目标颜色;颜色 O 是写入缓冲区的输出颜色。

   S、D 等表示该颜色的所有分量。Srgb 仅表示源颜色的 RGB 分量。Da 表示目标颜色的 alpha 分量。

   所有的加法和乘法都是分量的。针对颜色的标量乘法也是分量乘法。

   片段着色器输出的源颜色 S 如果目标缓冲区的图像格式是规范化的整数格式,则源颜色 S 输出将被固定为 [0, 1]。否则,它将按给定的方式使用。

   从缓冲区读取的目标颜色 D 也会发生变化。如果有问题的缓冲区使用sRGB图像格式,并且当前启用了GL_FRAMEBUFFER_SRGB,则正在读取的值将被线性化,从sRGB色彩空间转换为线性色彩空间。这发生在混合之前。

   如果 D 来自的缓冲区包含整数格式(实际的、非规范化的整数),则完全跳过该缓冲区的混合。S 将直接写入 O。

六、混合启用

   必须通过调用 glEnablei(GL_BLEND, i) 来启用混合,其中 i 是一个整数,表示要启用混合的缓冲区。片段着色器写入的每个缓冲区都可以单独启用和禁用混合。glDisablei 可用于禁用混合。

   可以使用 glEnable 和 glDisable 启用或禁用所有缓冲区的混合。

   当对缓冲区禁用混合时,片段着色器中的颜色将直接写入该缓冲区。启用混合后,将使用以下混合公式之一来确定写入该缓冲区的颜色。

   请注意,如果图像格式是某种形式的浮点,则混合仅适用于特定缓冲区。常规浮点数或归一化整数。如果它是非规范化整数,则该缓冲区的混合行为就像它被禁用一样。

七、混合方程

   缓冲区的混合状态有两个分量。第一个定义了用于混合的基本方程。此等式定义了与源颜色和目标颜色相关的基本数学运算。第二个混合组件是参数。每个方程都有许多参数;这些参数可用于修改所使用的基本数学计算。

   在计算输出颜色时,使用两个方程:一个用于输出颜色的 RGB 部分,另一个用于输出颜色的 alpha。如果您想执行诸如混合源颜色和目标颜色之类的操作,但将源 alpha 作为生成它的片段输出,这将非常有用。

   这两个方程是用以下函数设置的:

 void glBlendEquationSeparate(GLenum modeRGB​, GLenum modeAlpha​);

   modeRGB 是用于输出颜色的 RGB 部分的方程式,modeAlpha 是用于 alpha 部分的方程式。

   可能的公式如下:

   GL_FUNC_ADD:源颜色和目标颜色相互添加。O = sS + dD。s 和 d 是混合参数,在相加之前乘以 S 和 D 中的每一个。
   GL_FUNC_SUBTRACT:从源中减去目标。O = sS - dD。源和目标乘以混合参数。
   GL_FUNC_REVERSE_SUBTRACT:从目标中减去源。O = dD - sS。源和目标乘以混合参数。
   GL_MIN:输出颜色是源颜色和目标颜色的组件最小值。因此,在 RGB 方程中执行GL_MIN意味着 Or = min(Sr, Dr), Og = min(Sg, Dg),依此类推。此方程的参数 s 和 d 被忽略。
   GL_MAX:输出颜色是源颜色和目标颜色的组件最大值。此方程的参数 s 和 d 被忽略。

八、混合参数

   其中三个混合方程通过参数修改源颜色和目标颜色。这些方程可以分解为两个单独的方程:

  • Orgb = srgb * Srgb + drgb * Drgb
  • Oa = sa * Sa + da * Da
    两个减法方程也是如此。这将 RGB 分量计算与 alpha 计算分开。因此,有 4 种可能的混合参数。

   这些参数由此函数指定:

 void glBlendFuncSeparate(GLenum srcRGB​, GLenum dstRGB​, GLenum srcAlpha​, GLenum dstAlpha​)

srcRGB 值指定 srgb 参数。dstRGB 指定 drgb。srcAlpha 表示 sa,而 dstAlpha 指定 da。

   对于不使用参数(GL_MIN 和 GL_MAX)的混合方程,参数值毫无意义。它们不会影响输出值,您也不必设置它们。

   参数可以采用的值如下所示。

8.1 常量值

   参数 GL_ONE 和 GL_ZERO 是常量值。GL_ONE表示 1.0,GL_ZERO 表示 0.0。

   如果要进行直接加法,O = S + D,则需要将源和目标都设置为GL_ONE,并使用GL_FUNC_ADD函数。

8.2 颜色

   有许多参数是从源颜色和目标颜色或其组件派生的。

   GL_SRC_COLOR 和 GL_DST_COLOR 表示 S 和 D 本身,适用于特定方程。因此,在 RGB 方程中设置 GL_SRC_COLOR 意味着获得 Srgb;在 alpha 方程中设置它意味着得到 Sa。

   例如,如果您想要的混合是源颜色和目标颜色的直线相乘,则 O = S * D,则应设置 GL_FUNC_ADD 函数。然后将该方程的 source 参数设置为 GL_DST_COLOR,并将 destination 参数设置为 GL_ZERO(我们不想做加法,所以把加法项清空)。这将给出 O = D * S + 0 * D。

   还有GL_ONE_MINUS_SRC_COLOR和GL_ONE_MINUS_DST_COLOR。这些正是他们所说的:1.0 - 这些颜色的值。这是一个分量减法。请注意,如果目标缓冲区是浮点缓冲区,则 source 和 dest 不限于 [0, 1] 范围。

   也可以单独获得 alpha 组件。GL_SRC_ALPHA 和 GL_DST_ALPHA 表示 Sa 和 Da,无论使用哪个方程。还有GL_ONE_MINUS_SRC_ALPHA和GL_ONE_MINUS_DST_ALPHA,其工作原理如上。Sa 和 Da 是标量,因此它们与源颜色和目标颜色的乘法是分量级的。

   传统的 alpha 混合方程设置如下:

glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);

   这将根据源 alpha 在源颜色和目标颜色之间执行线性插值。alpha 函数和参数只需将源 alpha 写入输出。如果源 alpha 需要与目标 alpha 混合,则可以改用以下混合参数:

glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

   这将对颜色和源 alpha 执行线性插值。源 alpha 的参数是 GL_ONE 而不是 GL_SRC_ALPHA,因为它已经乘以源 alpha。

   执行预乘 alpha 混合(对标准线性插值的轻微修改)通常很有用。预乘之所以如此命名,是因为 RGB 源颜色已经乘以 alpha。这通常由图像编辑软件在生成纹理时完成,但它也可以作为片段着色器操作完成,甚至可以通过传递到顶点着色器的每个顶点颜色数据来完成。无论发生什么情况,片段着色器输出的值实际上已经乘以 alpha 分量,因此混合方程必须考虑到这一点。

   其设置如下。请注意,alpha 设置保持不变,并且将半透明图层堆叠在一起的合成最终会使输出不透明。

glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

8.3 混合颜色

   您可以设置可用于混合的恒定颜色。这称为混合颜色。它设置了以下功能:

 void glBlendColor(GLclampf red​, GLclampf green​, GLclampf blue​, GLclampf alpha​);

   混合颜色是一个状态值,如混合公式和混合参数。因此,它不能在单个绘制调用中更改;片段着色器无法写入、修改甚至访问混合颜色。所有缓冲区共享相同的混合颜色。

   混合颜色仅作为参数进行访问。这些枚举器是 GL_CONSTANT_COLOR、GL_ONE_MINUS_CONSTANT_COLOR、GL_CONSTANT_ALPHA 和 GL_ONE_MINUS_CONSTANT_ALPHA。

8.4 双源混合

   双源混合是指一种混合模式,其中片段着色器将两种颜色输出到同一输出缓冲区。为此,两个输出必须都指向相同的缓冲区索引,但具有一个特殊参数,该参数引用它是颜色 0 还是颜色 1。这可以在 GLSL 中使用布局限定符来完成:

layout(location = 0, index = 0) out vec4 outputColor0;
layout(location = 0, index = 1) out vec4 outputColor1;

   这将 outputColor0 写入缓冲区 0 的颜色 0,而 outputColor1 写入缓冲区 0 的颜色 1。每个缓冲区可以有自己的一组两种颜色。

   或者,可以使用此函数在链接程序对象之前绑定输出:

 void glBindFragDataLocationIndexed(uint program​, uint colorNumber​, uint index​, const char * name​);

   program 是程序对象,colorNumber 是缓冲区索引,index 是颜色编号(0 或 1),name 是输出变量的字符串名称。

   在片段着色器中,通过指定(通过上述任一方法)至少一个输出值将为其中一个目标缓冲区的 1 着色来激活双源混合。当着色器的双源混合处于活动状态时,可写入的颜色缓冲区数不再GL_MAX_DRAW_BUFFERS,而是GL_MAX_DUAL_SOURCE_DRAW_BUFFERS。此与实现相关的常量表示使用双源混合时片段着色器可以输出到的绘制缓冲区数。

   注意:在几乎所有 OpenGL 实现和硬件中,GL_MAX_DUAL_SOURCE_DRAW_BUFFERS 都是 1。这同样适用于 3.x 和 4.x 硬件。出于所有实际目的,如果使用双源混合,则只能写入一个缓冲区。
   混合方程中的源颜色 S 始终为颜色 0。颜色 1 只能用作参数。使用颜色 1 的参数为 GL_SRC1_COLOR、GL_SRC1_ALPHA、GL_ONE_MINUS_SRC1_COLOR 和 GL_ONE_MINUS_SRC1_ALPHA。

相关推荐

  1. openGL4.x手册13色彩混合blend

    2024-04-07 09:20:02       16 阅读
  2. openGL4.x手册09】转换反馈

    2024-04-07 09:20:02       18 阅读
  3. openGL4.x手册07】几何着色器

    2024-04-07 09:20:02       17 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-04-07 09:20:02       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-07 09:20:02       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-07 09:20:02       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-07 09:20:02       18 阅读

热门阅读

  1. c#编程基础学习之方法

    2024-04-07 09:20:02       29 阅读
  2. Python爬虫入门指南

    2024-04-07 09:20:02       18 阅读
  3. Redis入门--头歌实验使用Redis构建自动补全组件

    2024-04-07 09:20:02       16 阅读
  4. jvm基础

    2024-04-07 09:20:02       17 阅读
  5. 234.回文链表

    2024-04-07 09:20:02       16 阅读
  6. Kafka分区数扩容 Flink未发现新分区

    2024-04-07 09:20:02       20 阅读
  7. vite打包失败 - out of memory

    2024-04-07 09:20:02       18 阅读
  8. Jetson 换国内源

    2024-04-07 09:20:02       15 阅读
  9. SSL VPN

    SSL VPN

    2024-04-07 09:20:02      13 阅读
  10. 阿里云服务器F5负载均衡设置说明

    2024-04-07 09:20:02       16 阅读
  11. 大语言模型LLM《提示词工程指南》学习笔记02

    2024-04-07 09:20:02       16 阅读