创建混合状态

1. 如何在DirectX11中创建混合状态?

我们已经讨论了混合运算符和混合系数,但是还没有说该如何在Direct3D中使用些值。这些混合参数要通过ID3D11BlendState接口来控制。
我们可以通过填充一个D3D11_BLEND_DESC结构体并调用ID3D11Device::CreateBlendState方法来创建该接口:

HRESULT ID3D11Device::CreateBlendState(const D3D11_BLEND_DESC *pBlendStateDesc,ID3D10BlendState **ppBlendState);

1.pBlendStateDesc:指向D3D11_BLEND_DESC结构体的指针,该结构体用于描述所要创建的混合状态。

2.ppBlendState:返回创建后的混合状态接口。

2. 混合状态描述结构体D3D11_BLEND_DESC如何填充?

D3D11_BLEND_DESC结构体的定义如下:

typedef struct D3D11_BLEND_DESC {BOOL AlphaToCoverageEnable; // 默认值:FalseIndependentBlendEnable       // 默认值:FalseD3D11_RENDER_TARGET_BLEND_DESC RenderTarget[8];
} D3D11_BLEND_DESC;

1.AlphaToCoverageEnable:当设为true时,表示启用alpha-to-coverage功能。它是一种多重采样技术,在渲染植物的叶子或铁丝网纹理时非常有用。当设为false时,表示禁用 alpha-to-coverage功能。使用alpha-to-coverage需要开启多重采样(即,后台和深度缓冲创建时需要开启多重采样)。在第11章有一个使用alpha-to-coverage的示例。

2.IndependentBlendEnable:Direct3D 11支持同时绘制到8个渲染目标。当这个标志设置为true时,表示可以在不同的渲染目标上进行不同的混合处理(不同的混合因子、混合操作,混合开启/关闭等)。如果设置为false,则表示所有渲染目标都使用D3D11_BLEND_DESC::RenderTarget数组中第一个元素的混合状态,多重渲染目标用于高级的算法,目前为止,我们一次只使用一个渲染目标。

3.RenderTarget:包含8个D3D11_RENDER_TARGET_BLEND_DESC元素的数组,第i个元素描述了第i个多重渲染目标的混合方式。如果IndependentBlendEnable设置为false,则所有的渲染目标都使用RenderTarget[0]进行混合。

3. 渲染目标混合描述D3D11_RENDER_TARGET_BLEND_DESC如何创建?

这个描述填写我们上一节介绍过的混合方程。D3D11_RENDER_TARGET_BLEND_DESC结构体的定义如下:

typedef struct D3D11_RENDER_TARGET_BLEND_DESC{BOOL BlendEnable;        // 默认值:FalseD3D11_BLEND SrcBlend; // 默认值:D3D11_BLEND_ONED3D11_BLEND DestBlend; // 默认值Default:D3D11_BLEND_ZEROD3D11_BLEND_OP BlendOp; // 默认值:D3D11_BLEND_OP_ADDD3D11_BLEND SrcBlendAlpha; // 默认值:D3D11_BLEND_ONED3D11_BLEND DestBlendAlpha; // 默认值:D3D11_BLEND_ZEROD3D11_BLEND_OP BlendOpAlpha; // 默认值:D3D11_BLEND_OP_ADDUINT8 RenderTargetWriteMask; // 默认值:D3D11_COLOR_WRITE_ENABLE_ALL
}D3D11_RENDER_TARGET_BLEND_DESC;

1.BlendEnable:当设为true时,表示启用混合功能;当设为false时,表示禁用混合功能。

2.SrcBlend:D3D11_BLEND枚举类型成员,用于为RGB混合指定源混合系数Fsrc。

3.DestBlend:D3D11_BLEND枚举类型成员,用于为RGB混合指定目标混合系数Fdst。

4.BlendOp:D3D11_BLEND_OP枚举类型成员,用于指定RGB混合运算符。

5.SrcBlendAlpha:D3D11_BLEND枚举类型成员,用于为alpha混合指定源混合系数Fsrc。

6.DestBlendAlpha:D3D11_BLEND枚举类型成员,用于为alpha混合指定目标混合系数Fdst。

7.BlendOpAlpha:D3D11_BLEND_OP枚举类型成员,用于指定alpha混合运算符。

8.RenderTargetWriteMask:一个或多个下列标志值的组合:

typedef enum D3D11_COLOR_WRITE_ENABLE
{D3D11_COLOR_WRITE_ENABLE_RED = 1,D3D11_COLOR_WRITE_ENABLE_GREEN = 2,D3D11_COLOR_WRITE_ENABLE_BLUE = 4,D3D11_COLOR_WRITE_ENABLE_ALPHA = 8,D3D11_COLOR_WRITE_ENABLE_ALL =(D3D11_COLOR_WRITE_ENABLE_RED|D3D11_COLOR_WRITE_ENABLE_GREEN|D3D11_COLOR_WRITE_ENABLE_BLUE | D3D11_COLOR_WRITE_ENABLE_ALPHA)
} D3D11_COLOR_WRITE_ENABLE;

这些标志值用于控制混合之后将哪些颜色分量写入后台缓冲区。例如,通过D3D11_COLOR_WRITE_ENABLE_ALPHA可以屏蔽RGB通道,只将alpha值写入后台缓冲区。这一功能在实现某些高级技术时非常有用。当禁用混合时,由像素着色器返回的颜色会被屏蔽掉。

4. 如何绑定混合状态?

要将混合状态对象绑定到管线的输出合并器阶段,我们可以调用:

void ID3D11DeviceContext::OMSetBlendState(ID3D11BlendState *pBlendState,const FLOAT BlendFactor,UINT SampleMask);

1.pBlendState:混合状态对象的指针。

2.BlendFactor:用于描述RGBA颜色向量的浮点数组。当混合因子指定为D3D11_BLEND_BLEND_FACTOR或D3D11_BLEND_INV_BLEND_FACTOR时,Direct3D将以该颜色向量作为混合系数。

3.SampleMask:多重采样最多可以支持32个采样源。这个32位整数用于启用和禁用采样源。例如,当第5个二进制位设为0时,表示屏蔽第5个采样源。当然,如果实际使用的多重采样源数量少于5个,那么屏蔽第5个采样源是没有什么实际意义的。当应用程序只使用一个采样源时,该参数只有第1个二进制位有效(参见练习1)。通常,该参数以0xffffffff作为默认值,表示不屏蔽任何采样源。

与其他状态块相同,这里有一个默认的混合状态(禁用混合);如果以空值来调用OMSetBlendState方法,它就会将混合状态恢复为默认值。注意,混合会在每个像素上执行额外的计算工作,所以我们只有在用到混合时才启用它,用完之后应该立即关闭。

5. DirectX11中创建和设置混合状态示例代码

下面是创建和设置混合状态的一个例子:

D3D11_BLEND_DESC blendDesc = {0};
transparentDesc.AlphaToCoverageEnable = false;
transparentDesc.IndependentBlendEnable = false;transparentDesc.RenderTarget[0].BlendEnable = true;
transparentDesc.RenderTarget[0].SrcBlend = D3D10_BLEND_SRC_ALPHA;
transparentDesc.RenderTarget[0] = D3D11_BLEND_INV_SRC_ALPHA;
transparentDesc.RenderTarget[0] = D3D11_BLEND_OP_ADD;
transparentDesc.RenderTarget[0] = D3D11_BLEND_ONE;
transparentDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
transparentDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
transparentDesc.RenderTarget[0].RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL;ID3D11BlendState* TransparentBS;
HR(device->CreateBlendState(&transparentDesc, &TransparentBS));
...
float blendFactor[] = {0.0f, 0.0f, 0.0f, 0.0f};
md3dImmediateContect->OMSetBlendState(TransparentBS, blendFactor, 0xffffffff);

与其他状态块接口一样,我们应该在应用程序初始化时创建它们,然后根据需要在些状态接口之间进行切换。

6. 可以在Effect文件中创建和设置混合状态吗?

混合状态对象也可以在effect文件中创建和设定:

BlendState blend
{// 第一个渲染目标的混合状态BlendEnable[0] = TRUE;SrcBlend[0] = SRC_COLOR;DestBlend[0] = INV_SRC_ALPHA;BlendOp[0] = ADD;SrcBlendAlpha[0] = ZERO;DestBlendAlpha[0] = ZERO;BlendOpAlpha[0] = ADD;RenderTargetWriteMask[0] = 0x0F;// 第二个渲染目标的混合状态BlendEnable[1] = True;SrcBlend[1] = One;DestBlend [1] = Zero;BlendOp[1] = Add;SrcBlendAlpha[1] = Zero;DestBlendAlpha[1] = Zero;BlendOpAlpha[1] = Add;RenderTargetWriteMask[1] = 0x0F;
};technique11 Tech
{pass P0{...// 在这个pass中使用“混合”。SetBlendState(blend,float4(0.0f,0.0f,0.0f,0.0f),0xffffffff);}
}

在混合状态对象中指定的这些值与在C++结构体中指定的值基本相同,只是省去了一些前缀。例如,在effect文件中我们指定SRC_COLOR,而不是 D3D11_BLEND_SRC_COLOR。

DirectX11 创建混合状态相关推荐

  1. DirectX11 With Windows SDK--11 混合状态

    文章目录 前言 混合等式 混合等式 混合状态 混合运算符的设置 混合因子的设置 ID3D11Device::CreateBlendState方法--创建混合状态 ID3D11DeviceContext ...

  2. DirectX11 混合状态

    DirectX11混合状态 1. 什么是混合状态? 在D3D11中,"混合"发生在像素着色器阶段的下一阶段,即Output Merger Stage.整个场景在全部经历过像素着色器 ...

  3. Flutter进阶—创建有状态控件

    Flutter进阶-构建布局实例展示了如何创建以下布局. 当应用程序首次启动时,这颗实心星标是红色的,表明这个景点曾经被收藏过.实心星标旁边的人数表明,有66人喜欢这个景点.现在需要完成一个任务,点击 ...

  4. 《混合云计算》——2.2 结合服务创建混合云环境

    本节书摘来自异步社区<混合云计算>一书中的第2章,第2.2节,作者: [美]Judith Hurwitz , Marcia Kaufman , Dr. Fern Halper , Dani ...

  5. 创建链路状态状态数据包

               路由器一旦建立了相邻关系,即可创建链路状态数据包 (LSP),其中包含与该链路相关的链路状态信息.(LSP包含链路类型.IP地址.子网掩码.开销) 将链路状态数据包泛洪到邻居: ...

  6. Ionic+Capacitor 创建混合APP

    一.介绍 Capacitor是由ionic团队开发的一款跨平台移动应用构建工具,可轻让我们轻松的构建Android.iOS.Electron和Web应用程序. 其前身为Apache Cordova和A ...

  7. 学习基础设施管理工具 Terraform 的基本用法,包括资源创建、状态管理

    Terraform 简介 Terraform 是一个基础设施管理工具,用于创建.管理和部署基础设施资源.它提供了一种简单的方式来定义基础设施的状态,并在不同的云平台上管理资源.它支持多个云平台,包括 ...

  8. xmind贴纸_如何使用彩色背景或大贴纸创建Facebook状态

    xmind贴纸 If you've been on Facebook recently, you've probably noticed that statuses are starting to l ...

  9. 【Linux】子进程的创建、状态

    fork() :创建子进程 我们都知道,一个可执行程序加载到内存中,就叫做进程,进程执行对应的代码.可以看得出,我们是在执行一个进程,如果想要在该进程中再创建一个进程呢,该如何进行分流. 这时了解一下 ...

最新文章

  1. 帝国重新生成html,帝国CMS实现提交评论后自动重新生成内容页
  2. CoreAnimation动画
  3. 科技下的仓库,数据库
  4. JavaScript_原型和继承(2017-03-15)
  5. 一个不错的js制作的右键菜单
  6. 10、游标(Cursor)的定义及使用
  7. Document is invalid: no grammar found. at (null:3:8)
  8. JAVA中ByteArrayInputStream和ByteArrayOutputStream详解
  9. 利用perl一键生成符合LEFse差异分析的Table表
  10. 如何使用Transformers和Tokenizers从头开始训练新的语言模型
  11. Linux命令:ln -s
  12. 解一元二次方程(包括虚根)
  13. 为什么网页无法正常显示
  14. 深度学习常用评价指标
  15. CentOS 安装相关
  16. SSH无密码登录失败之DSA算法问题
  17. IE11 全新的F12开发者工具
  18. 过客--三星 s6 edge 照相机出故障了
  19. 哪些专科学校计算机师资好,计算机专科学校排名前十(最出名的10所计算机学院)...
  20. 话务量单位erl (爱尔兰)

热门文章

  1. Zspace(笔触灯光打开和关闭)
  2. 什么是前端什么是后端?什么是前台后台
  3. 【使用stripTrailingZeros()函数将BigDecimal去0变为科学计数法7E+1】
  4. java计算机毕业设计桔子酒店客房管理系统源码+数据库+系统+lw文档+mybatis+运行部署
  5. DBA数据库管理员要求
  6. 2022 国赛postgresql
  7. Android studio编译日志输出中文出现乱码 (如apk为中文命名时候)解决
  8. 同济大学计算机网络期末考试题,完整word版,同济大学计算机网络考试题及答案,推荐文档...
  9. Alice Trival Tech Support
  10. 一年有可能学完大学计算机吗,如何用一年时间,学完麻省理工大学4年33门课程?...