本篇博客给读者介绍混合,见下图所示, 我们首先绘制地形,然后绘制木箱,然后将地形和木箱像素放在后面的缓冲区上。 我们使用混合将水面绘制到后面的缓冲区,以便水像素与地形混合,并在后面缓冲区上放置像素,使地形和木箱通过水显示。 从现在起,我们将研究混合技术,这些技术允许我们将当前光栅化的像素(所谓的源像素)与先前光栅化到后缓冲区的像素(所谓的目标像素)混合(组合)。 除了上面我们提到的,这种技术使我们能够渲染半透明物体,如水和玻璃。

为了便于学习,我们特别提到后缓冲区作为渲染目标, 但是,稍后我们将展示我们可以渲染到“屏幕外”渲染目标。 混合适用于这些渲染目标,目标像素是先前光栅化到这些屏幕外渲染目标的像素值。下面先介绍混合方程。

混合方程

设Csrc是我们当前光栅化的第i个像素(源像素)的像素着色器的颜色输出,并且让Cdst是当前在后缓冲器(目标像素)上的第i个像素的颜色。 如果没有混合,Csrc将覆盖Cdst(假设它通过深度/模板测试)并成为第i个后缓冲区像素的新颜色。 但是通过混合,Csrc和Cdst被混合在一起以获得将覆盖Cdst的新颜色C(即,混合颜色C将被写入后缓冲器的第i个像素)。 Direct3D使用以下混合方程来混合源像素和目标像素颜色:

颜色Fsrc(源混合因子)和Fdst(目标混合因子)可以是上述公式中描述的任何值,它们允许我们以各种方式修改原始源像素和目标像素,允许实现不同的效果, ⊗运算符意味着定义的颜色向量的分量乘法; 运算符可以是任何二元运算符。
上述混合方程仅适用于颜色的RGB分量, alpha组件实际上由一个单独的类似方程式处理:

等式基本相同,但混合因子和二元运算可能不同, 将RGB与alpha分离的动机很简单,因此我们可以独立处理它们,使用不同地方式处理它们,这会出现更多种可能性。
与混合RGB组件相比,混合alpha组件的频率要低得多, 这主要是因为我们不关心后缓冲区alpha值,如果我们有一些需要目标alpha值的算法,则后缓冲区alpha值才是重要的。

混合操作

混合方程中使用的二元运算符可以是以下之一:

在最小/最大操作中忽略混合因子。
这些相同的运算符也适用于alpha混合方程, 此外,我们可以为RGB和alpha指定不同的运算符。 例如,可以添加两个RGB术语,但减去两个alpha术语。

最近添加到Direct3D的一个功能是使用逻辑运算符而不是上面的传统混合方程来混合源颜色和目标颜色。 可用的逻辑运算符如下:

typedef
enum D3D12_LOGIC_OP
{D3D12_LOGIC_OP_CLEAR   = 0,D3D12_LOGIC_OP_SET   = ( D3D12_LOGIC_OP_CLEAR + 1 ) ,D3D12_LOGIC_OP_COPY   = ( D3D12_LOGIC_OP_SET + 1 ) ,D3D12_LOGIC_OP_COPY_INVERTED   = ( D3D12_LOGIC_OP_COPY + 1 ) ,D3D12_LOGIC_OP_NOOP   = ( D3D12_LOGIC_OP_COPY_INVERTED + 1 ) ,D3D12_LOGIC_OP_INVERT   = ( D3D12_LOGIC_OP_NOOP + 1 ) ,D3D12_LOGIC_OP_AND   = ( D3D12_LOGIC_OP_INVERT + 1 ) ,D3D12_LOGIC_OP_NAND   = ( D3D12_LOGIC_OP_AND + 1 ) ,D3D12_LOGIC_OP_OR   = ( D3D12_LOGIC_OP_NAND + 1 ) ,D3D12_LOGIC_OP_NOR   = ( D3D12_LOGIC_OP_OR + 1 ) ,D3D12_LOGIC_OP_XOR   = ( D3D12_LOGIC_OP_NOR + 1 ) ,D3D12_LOGIC_OP_EQUIV   = ( D3D12_LOGIC_OP_XOR + 1 ) ,D3D12_LOGIC_OP_AND_REVERSE   = ( D3D12_LOGIC_OP_EQUIV + 1 ) ,D3D12_LOGIC_OP_AND_INVERTED   = ( D3D12_LOGIC_OP_AND_REVERSE + 1 ) ,D3D12_LOGIC_OP_OR_REVERSE   = ( D3D12_LOGIC_OP_AND_INVERTED + 1 ) ,D3D12_LOGIC_OP_OR_INVERTED   = ( D3D12_LOGIC_OP_OR_REVERSE + 1 )
} D3D12_LOGIC_OP;

请注意,我们不能同时使用传统的混合和逻辑运算符混合, 只能挑选一个或另一个。 另请注意,为了使用逻辑运算符混合,渲染目标格式必须支持 - 它应该是UINT变体的格式,否则将收到如下错误:

D3D12 ERROR: ID3D12Device::CreateGraphicsPipelineState: The render target format at slot 0 is format (R8G8B8A8_UNORM). This format does not support logic ops. The Pixel Shader output signature indicates this output could be written, and the Blend State indicates logic op is enabled for this slot. [ STATE_CREATION ERROR #678: CREATEGRAPHICSPIPELINESTATE_OM_RENDER_TARGET_DOES_NOT_SUPPORT_LOGIC_OPS]
D3D12 WARNING: ID3D12Device::CreateGraphicsPipelineState: Pixel Shader output ‘SV_Target0’ has type that is NOT unsigned int, while the corresponding Output Merger RenderTarget slot [0] has logic op enabled. This happens to be well defined: the raw bits output from the shader will simply be interpreted as UINT bits in the blender without any data conversion. This warning is to check that the application developer really intended to rely on this behavior. [
STATE_CREATION WARNING #677: CREATEGRAPHICSPIPELINESTATE_PS_OUTPUT_TYPE_MISMATCH]

混合因子

通过为源和目标混合因子设置不同的组合以及不同的混合运算符,可以实现许多不同的混合效果。 我们将在后面说明一些组合,但我们需要尝试其他组合以了解它们的作用。 以下列表描述了适用于Fsrc和Fdst的基本混合因子, 有关其他一些高级混合因子,请参阅SDK文档中的D3D12_BLEND枚举类型。 设Csrc =(rs,gs,bs),Asrc = as(从像素着色器输出的RGBA值),Cdst =(rd,gd,bd),Adst = ad(已存储在渲染目标中的RGBA值), F是Fsrc或Fdst而F是Fsrc或Fdst,我们有:

D3D12_BLEND_ZERO: F = (0, 0, 0) and F = 0
D3D12_BLEND_ONE: F = (1, 1, 1) and F = 1
D3D12_BLEND_SRC_COLOR: F = (rs, gs, bs)
D3D12_BLEND_INV_SRC_COLOR: Fsrc = (1 − rs, 1 − gs, 1 − bs)
D3D12_BLEND_SRC_ALPHA: F = (as, as, as) and F = as
D3D12_BLEND_INV_SRC_ALPHA: F = (1 − as, 1 − as, 1 − as) and F = (1 − as)
D3D12_BLEND_DEST_ALPHA: F = (ad, ad, ad) and F = ad
D3D12_BLEND_INV_DEST_ALPHA: F = (1 − ad, 1 − ad, 1 − ad) and F = (1 − ad)
D3D12_BLEND_DEST_COLOR: F = (rd, gd, bd)
D3D12_BLEND_INV_DEST_COLOR: F = (1 − rd, 1 − gd, 1 − bd)
D3D12_BLEND_SRC_ALPHA_SAT: F = (a′s, a′s, a′s) and F = a′s

其中a =clamp(as,0, 1)
D3D12_BLEND_BLEND_FACTOR:F =(r,g,b)和 F = a,其中颜色(r,g,b,a)被提供给ID3D12GraphicsCommandList :: OMSetBlendFactor方法的第二个参数。 这允许我们指定要直接使用的混合因子颜色,但是,在更改混合状态之前,它是恒定的。

D3D12_BLEND_INV_BLEND_FACTOR:F =(1-r,1-g,1-b)和F = 1-a,其中颜色(r,g,b,a)由ID3D12GraphicsCommandList :: OMSetBlendFactor方法的第二个参数提供, 这允许我们指定要直接使用的混合因子颜色; 但是,在您更改混合状态之前,它是恒定的。

所有上述混合因子都适用于RGB混合方程, 对于alpha混合等式,不允许以_COLOR结尾的混合因子。

Clamp函数定义如下:

我们可以使用以下函数设置混合因子颜色:

void ID3D12GraphicsCommandList::OMSetBlendFactor(const FLOAT BlendFactor[ 4 ]);
传递空指针会恢复默认的混合因子(1,1,1,1)。

混合状态

我们已经讨论过混合运算符和混合因子,但是我们在哪里用Direct3D设置这些值? 与其他Direct3D状态一样,混合状态是PSO的一部分。 到目前为止,我们一直在使用默认的混合状态,它禁用混合:

D3D12_GRAPHICS_PIPELINE_STATE_DESC opaquePsoDesc;
ZeroMemory(&opaquePsoDesc, sizeof(D3D12_GRAPHICS_PIPELINE_STATE_DESC));
…
opaquePsoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);

要配置非默认混合状态,我们必须填写D3D12_BLEND_DESC结构。 D3D12_BLEND_DESC结构的定义如下:

typedef struct D3D12_BLEND_DESC {BOOL AlphaToCoverageEnable;  // Default: FalseBOOL IndependentBlendEnable;  // Default: FalseD3D11_RENDER_TARGET_BLEND_DESC RenderTarget[8];
} D3D11_BLEND_DESC;

1、AlphaToCoverageEnable:指定true以启用alpha-to-coverage,这是一种在渲染树叶或栅栏纹理时非常有用的多重采样技术。 指定false以禁用alpha-to-coverage。 Alpha-to-coverage需要启用多重采样(即,使用多重采样创建背面和深度缓冲区)。
2、IndependentBlendEnable:Direct3D支持同时渲染多达八个渲染目标。 当此标志设置为true时,表示可以对每个渲染目标执行不同的混合(不同的混合因子,不同的混合操作,混合禁用/启用等)。 如果此标志设置为false,则表示将按照D3D12_BLEND_DESC :: RenderTarget数组中第一个元素所描述的相同方式混合所有渲染目标。 多个渲染目标用于高级算法; 现在,假设我们一次只渲染到一个渲染目标。
3、RenderTarget:一个包含8个D3D12_RENDER_TARGET_BLEND_DESC元素的数组,其中第i个元素描述了如何为第i个同时渲染目标进行混合。 如果IndependentBlendEnable设置为false,则所有渲染目标都使用RenderTarget [0]进行混合。
D3D12_RENDER_TARGET_BLEND_DESC结构的定义如下:

typedef struct D3D12_RENDER_TARGET_BLEND_DESC
{BOOL BlendEnable; // Default: FalseBOOL LogicOpEnable; // Default: FalseD3D12_BLEND SrcBlend; // Default: D3D12_BLEND_ONED3D12_BLEND DestBlend; // Default: D3D12_BLEND_ZEROD3D12_BLEND_OP BlendOp; // Default: D3D12_BLEND_OP_ADDD3D12_BLEND SrcBlendAlpha; // Default: D3D12_BLEND_ONED3D12_BLEND DestBlendAlpha; // Default: D3D12_BLEND_ZEROD3D12_BLEND_OP BlendOpAlpha; // Default: D3D12_BLEND_OP_ADDD3D12_LOGIC_OP LogicOp;   // Default: D3D12_LOGIC_OP_NOOPUINT8 RenderTargetWriteMask; // Default: D3D12_COLOR_WRITE_ENABLE_ALL
} D3D12_RENDER_TARGET_BLEND_DESC;

1、BlendEnable:指定true以启用混合,指定false以禁用它。 请注意,BlendEnable和LogicOpEnable不能都设置为true; 可以使用常规混合或逻辑运算符混合。
2、LogicOpEnable:指定true以启用逻辑混合操作, 请注意,BlendEnable和LogicOpEnable不能都设置为true,可以使用常规混合或逻辑运算符混合。
3、SrcBlend:D3D12_BLEND枚举类型的成员,它指定RGB混合的源混合因子Fsrc。
4、DestBlend:D3D12_BLEND枚举类型的成员,它指定RGB混合的目标混合因子Fdst。
5、BlendOp:D3D12_BLEND_OP枚举类型的成员,用于指定RGB混合运算符。
6、SrcBlendAlpha:D3D12_BLEND枚举类型的成员,它指定用于Alpha混合的目标混合因子Fsrc。
7、DestBlendAlpha:D3D12_BLEND枚举类型的成员,它指定用于Alpha混合的目标混合因子Fdst。
8、BlendOpAlpha:D3D12_BLEND_OP枚举类型的成员,指定alpha混合运算符。
9、LogicOp:D3D12_LOGIC_OP枚举类型的成员,指定用于混合源颜色和目标颜色的逻辑运算符。
10、RenderTargetWriteMask:以下一个或多个标志的组合:

typedef enum D3D12_COLOR_WRITE_ENABLE {D3D12_COLOR_WRITE_ENABLE_RED   = 1,D3D12_COLOR_WRITE_ENABLE_GREEN  = 2,D3D12_COLOR_WRITE_ENABLE_BLUE  = 4,D3D12_COLOR_WRITE_ENABLE_ALPHA  = 8,D3D12_COLOR_WRITE_ENABLE_ALL   = ( D3D12_COLOR_WRITE_ENABLE_RED | D3D12_COLOR_WRITE_ENABLE_GREEN | D3D12_COLOR_WRITE_ENABLE_BLUE | D3D12_COLOR_WRITE_ENABLE_ALPHA )
} D3D12_COLOR_WRITE_ENABLE;

这些标志控制在混合后写入后缓冲区中的哪些颜色通道? 例如,我们可以通过指定D3D12_COLOR_WRITE_ENABLE_ALPHA禁用对RGB通道的写入,并仅写入Alpha通道。 这种灵活性对于高级技术非常有用。 禁用混合时,将使用从像素着色器返回的颜色,而不应用写入蒙版。
混合不是免费的,并且需要额外的每像素工作,因此只有在需要时才启用它,并在完成后将其关闭。
以下代码显示了创建和设置混合状态的示例代码:

// Start from non-blended PSO
D3D12_GRAPHICS_PIPELINE_STATE_DESC transparentPsoDesc = opaquePsoDesc;D3D12_RENDER_TARGET_BLEND_DESC transparencyBlendDesc;
transparencyBlendDesc.BlendEnable = true;
transparencyBlendDesc.LogicOpEnable = false;
transparencyBlendDesc.SrcBlend = D3D12_BLEND_SRC_ALPHA;
transparencyBlendDesc.DestBlend = D3D12_BLEND_INV_SRC_ALPHA;
transparencyBlendDesc.BlendOp = D3D12_BLEND_OP_ADD;
transparencyBlendDesc.SrcBlendAlpha = D3D12_BLEND_ONE;
transparencyBlendDesc.DestBlendAlpha = D3D12_BLEND_ZERO;
transparencyBlendDesc.BlendOpAlpha = D3D12_BLEND_OP_ADD;
transparencyBlendDesc.LogicOp = D3D12_LOGIC_OP_NOOP;
transparencyBlendDesc.RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;
transparentPsoDesc.BlendState.RenderTarget[0] = transparencyBlendDesc;
ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&transparentPsoDesc, IID_PPV_ARGS(&mPSOs["transparent"])));

与其他PSO一样,我们应该在应用程序初始化时创建它们,然后根据需要使用ID3D12GraphicsCommandList :: SetPipelineState方法在它们之间切换。

D3D12渲染技术之混合相关推荐

  1. D3D12渲染技术之渲染管线

    渲染管线指的是通过虚拟相机看到的内容生成2D图像的整个步骤序列,在博客D3D12渲染技术概述中介绍过渲染管线,本篇博客具体讲解各个模块的作用,先看下图所示: Input Assembler Stage ...

  2. D3D12渲染技术之初始化流程

    掌握了矩阵向量运算后,接下来我们要做的事情利用D3D12图形库API编程,也就是我们通常说的初始化D3D12,D3D12的初始化工作与以前的D3D9是完全不一样的,D3D12做了大幅的升级.但是每个D ...

  3. D3D12渲染技术之创建和启用纹理

    纹理在任何引擎都有使用,它其实就是为模型提供的纹理材质,既然我们介绍的是D3D12,那就从dds文件介绍说起. 加载DDS文件 Microsoft提供了轻量级源代码来加载DDS文件: https:// ...

  4. D3D12渲染技术之常量缓冲区

    常量缓冲区是GPU资源(ID3D12Resource),其数据内容可以在着色器程序中引用,正如我们将在博客中学到的,纹理和其他类型的缓冲区资源也可以在着色器程序中引用.顶点着色器具有以下代码: cbu ...

  5. D3D12渲染技术之绘制网格

    在前几篇博客中,我们主要关注渲染管道的概念和数学方面. 反过来,从本篇博客开始重点介绍配置渲染管道,定义顶点和像素着色器以及将几何图形提交到渲染管道以进行绘制所需的Direct3D API接口和方法. ...

  6. D3D渲染技术之混合案例

    在本篇内容中,我们将介绍用于获得特定效果的一些混合因子组合, 在这些示例中,我们仅查看RGB混合, Alpha混合的处理方式类似. 无颜色写入 假设我们想要保持原始目标像素的原样,而不是覆盖它或将其与 ...

  7. D3D12渲染技术之根签名

    我们在前面的博客中介绍了根签名, 根签名定义在发出绘制调用之前需要将哪些资源绑定到管道以及这些资源如何映射到着色器输入寄存器, 需要绑定哪些资源取决于当前着色器程序所期望的资源, 创建PSO时,将验证 ...

  8. D3D12渲染技术之编译Shader

    很多人只知道写Shader,但是并不了解DX或者OpenGL是如何编译Shader的,我们写的Shader是一种文本文件,它可以被DX或者OpenGL读取,说明它们提供了接口编译Shader.3D引擎 ...

  9. D3D12渲染技术之顶点着色器

    相信大家以前用过D3D9的或是编写过Shader的对顶点着色器都比较了解,现在我们回顾一下: cbuffer cbPerObject : register(b0) {float4x4 gWorldVi ...

最新文章

  1. spring security 自定义认证登录
  2. Java虚拟机的功能
  3. 距离剩者为王,服饰企业还要跨过很多道坎
  4. 《C++游戏开发》十八 角色在障碍物中智能行走的实现
  5. redhat6搭建ftp
  6. mysql性能调优与架构设计 51cto_MySQL 数据库性能优化之表结构优化
  7. 实战 | 手把手教你设计优惠券前后台
  8. 【vim入门笔记】基本操作与插件安装
  9. Unity轻松制作俯视角游戏插件TopDown Engine
  10. Linux上的视频播放及MPV播放器与SVP4插帧
  11. 【win10专业版】3dmax卸载不干净如何解决
  12. 应用统计学之——average和mea…
  13. 分享一个开源免费、功能强大的视频播放器库
  14. 11.14-11.21
  15. c语言中除法除以1000与1e3,北京航空航天大学C语言b第二讲(第三、四章)数据类型、运算符与表达式和最简单的C程序设计.ppt...
  16. java ocx,Eclipse使用ActiveX控件(OCX)开发Java程序
  17. 德卡T10-F多功能读卡器|读写机外接密码小键盘在医保领域的应用与性能攻略
  18. TabLayout的指示器和文字的边距
  19. 关于曲面方程的法向量的求法
  20. 如何酷酷的找回迅雷私人空间的密码

热门文章

  1. 罗昭锋 文献管理与信息分析一
  2. 如果host1要传送文件到服务器,南京晓庄学院思科网络网上作业
  3. 大四做毕业设计,是一种怎样的感受?
  4. 上网本终于可以休息了,我的脱机下载利器 数帅D600
  5. 7-17 找最贵的书和最便宜的书
  6. 9.物体的几何表示——分形几何
  7. Carthage 教程:开始
  8. 人脸识别-Haar级联
  9. 多项式A除以B(PTA)
  10. win10网上邻居看不到别的共享电脑怎么样办