DirectX11 混合方程

混合方程

1. 什么是混合?

考虑下图。我们从地形和板条箱开始渲染场景,先绘制地形,再绘制板条箱,使地形和板条箱的像素依次存入后台缓冲区。然后使用混合(blending),将水体绘制到后台缓冲区,使水体像素和后台缓冲区中的地形、板条箱像素融为一体。通过一方式,我们可以透过水体看到地形和板条箱。本章我们主要讲解混合技术,它可以将当前的光栅化像素(也称为源像素)与后台缓冲区中的像素(也称为目标像素)混合(融合)在一起。该技术通常用于渲染半透明物体,比如水和玻璃。

DirectX11 混合方程_第1张图片
(半透明的水面)

注意:为了叙述方便,当我们提到后台缓冲时,指的是渲染目标。但是,我们也可以绘制到一个“离屏,off screene”渲染目标中。混合作用在这些渲染目标的方式是相同的,目标像素的值就是之前光栅化后的离屏渲染目标中的值。

2. 什么是混合方程?

设Csrc为当前正在进行光栅化处理的第ij个像素(源像素)的颜色,Cdst为后台缓冲区中的第ij个像素(目标像素)的颜色。当不使用混合时,Csrc会覆盖Cdst的值(假设该值已通过深度/模板测试)并成为后台缓冲区中的第ij个像素的新颜色。但是当使用混合时,Csrc和Cdst会被组合为一个新颜色C并覆盖Cdst的值(即,混合颜色C会成为后台缓冲区中的第ij个像素的新颜色)。Direct3D使用如下混合方程混合源像素和目标像素颜色:

Fsrc(源混合系数)和Fdst(目标混合系数)可以是下一节描述的任何一个值,它们按照各种不同的方式调整源像素和目标像素的比例,实现各种不同的混合效果。运算符⊗是定义在5.3.1节中定义的颜色的分量乘法;运算符⊞可以是9.2节描述的任何一个二进制运算符。

上述混合方程只负责处理颜色的RGB分量。alpha分量要由另外一个方程来处理:

这里写图片描述

该方程与前一个方程基本相同,只是使用的混合系数和二进制运算符有些区别。我们将RGB和alpha分开的原因非常简单,就是为了独立地、按照不同的方式处理它们。

注意:我们很少混合alpha分量,多数情况下,我们只是对RGB分量进行混合。尤其是在本书中,我们从不混合源alpha值和目标alpha值,虽然alpha值会参与我们的RGB混合操作。这主要是因为我们暂时用不到后台缓冲区中的alpha值。只有当某些算法需要使用目标alpha值时,后台缓冲区中的alpha值才有用。

3. 混合操作有哪些?

混合方程中的二进制运算符⊞可取以下各值之一:

typedef enum D3D11_BLEND_OP
{
    D3D11_BLEND_OP_ADD = 1,            C = Csrc ⊗ Fsrc + Cdst ⊗ Fdst
    D3D11_BLEND_OP_SUBTRACT = 2,      C = Cdst ⊗ Fdst - Csrc ⊗ Fsrc
    D3D11_BLEND_OP_REV_SUBTRACT = 3, C = Csrc ⊗ Fsrc - Cdst ⊗ Fdst
    D3D11_BLEND_OP_MIN = 4,            C = min(Csrc , Cdst)
    D3D11_BLEND_OP_MAX = 5,            C = max(Csrc , Cdst)
} D3D11_BLEND_OP;

注意:在min/max操作中会忽略混合因子。

这些运算符也可用于alpha混合方程。注意,RGB混合方程和alpha混合方程可以使用不同的运算符。例如,当两组RGB值相加时,对应的两组alpha值可以相减:

这里写图片描述

4. 混合系数有哪些?

通过为源混合系数和目标混合系数指定不同的组合值,可以实现不同的混合效果。对于那些我们没有讲到的组合值,请读者自己做一些实验,看看它们可以产生哪些效果。下面的列表描述了基本的混合系数,它们都可以用于Fsrc和Fdst。对于一些额外的高级混合系数,请参阅SDK文档中的D3D11_BLEND枚举类型。设Csrc = (r,g,b)、Asrc = as(从像素着色器中输出的RGBA颜色)、Cdst = (rd,gd,bd )、Ad = ad(已经储存在渲染目标中的RGBA颜色),F既可以作为Fsrc也可以作为Fdst,F既可以作为Fsrc也可以作为Fdst,我们有:

  • D3D11_BLEND_ZERO:F = (0, 0, 0)且F = 0
  • D3D11_BLEND_ONE:F = (1, 1, 1) 且F = 1
  • D3D11_BLEND_SRC_COLOR:F = (rs ,gs ,bs )
  • D3D11_BLEND_INV_SRC_COLOR:F = (1 - rs ,1 - gs ,1 - bs )
  • D3D11_BLEND_SRC_ALPHA:F = (as ,as ,as )且F = as
  • D3D11_BLEND_INV_SRC_ALPHA:F = (1 − as,1 − as,1 − as)且F =1 − as
  • D3D11_BLEND_DEST_ALPHA:F = (ad ,ad ,ad )且F = ad
  • D3D11_BLEND_INV_DEST_ALPHA:F = (1 – ad,1 − ad,1 – ad)且F =1 – ad
  • D3D11_BLEND_DEST_COLOR:F = (rd ,gd ,bd )
  • D3D11_BLEND_INV_DEST_COLOR:F = (1 – rd ,1 – gd ,1 – bd )
  • D3D11_BLEND_SRC_ALPHA_SAT:F = (asʹ, asʹ, asʹ)且F = asʹ,其中,asʹ = clamp(as , 0, 1)
  • D3D11_BLEND_BLEND_FACTOR:F = (r,g,b)且F = a,其中,颜色(r,g,b,a)由ID3D11DeviceContext::OMSetBlendState方法的第2个参数指定(下一节会说)。也就是说,我们可以将一个颜色指定为混合系数;在修改混合状态前,该颜色一直有效。
  • D3D11_BLEND_INV_BLEND_FACTOR:F = (1-r,1-g,1-b)且F = 1-a,其中,颜色(r,g,b,a)由ID3D11DeviceContext::OMSetBlendState方法的第2个参数指定(9.4节)。也就是说,我们可以将一个颜色指定为混合系数;在修改混合状态前,该颜色一直有效。

注意:clamp函数的定义为:

DirectX11 混合方程_第2张图片

所有的这些混合系数都可用于RGB混合方程。但是,以“_COLOR”结尾的混合系数不可用于alpha混合方程。

你可能感兴趣的:(游戏开发,Direct3D,混合,directx11,混合方程)