码迷,mamicode.com
首页 > 其他好文 > 详细

DirectX11笔记6:混合blend

时间:2015-11-28 14:56:01      阅读:275      评论:0      收藏:0      [点我收藏+]

标签:

所谓混合,目的就是解决一些需要叠加处理的材质问题,书中有个很好的例子:雾。

当然也有其它的用法,比如把2个不同材质叠加,产生各种神奇的效果(参见9.5.2节)。

混合的代码操作:

按照一贯的逻辑,我们在D3D里创建一个东西都是要填一大堆结构体,然后使用一个函数初始化,再在渲染步骤中进行进一步处理。这里一样。。。。

使用CreateBlendState初始化对混合的描述:

virtual HRESULT STDMETHODCALLTYPE CreateBlendState( 
            /* [annotation] */ 
            _In_  const D3D11_BLEND_DESC *pBlendStateDesc,
            /* [annotation] */ 
            _Out_opt_  ID3D11BlendState **ppBlendState)

 

这个没什么好多说的,第一个参数是一个描述用的结构体,第二个参数用于返回。

主要是看第一个结构体:

typedef struct D3D11_BLEND_DESC {
  BOOL                           AlphaToCoverageEnable;
  BOOL                           IndependentBlendEnable;
  D3D11_RENDER_TARGET_BLEND_DESC RenderTarget[8];
} D3D11_BLEND_DESC;

 

书中有解释,第一个参数表示是否使用一个叫做alpha-to-coverage的多重采样技术,现在先不用设为false,第二个参数表示是否使用多目标同时渲染(这是啥。。。)这里设为false,那么只能使用RenderTarget[0] 进行渲染。

换句话说,前两个参数现在以我的技术来说,没啥软用。

第三个参数又是一个结构体:

typedef struct D3D11_RENDER_TARGET_BLEND_DESC {
  BOOL           BlendEnable;
  D3D11_BLEND    SrcBlend;
  D3D11_BLEND    DestBlend;
  D3D11_BLEND_OP BlendOp;
  D3D11_BLEND    SrcBlendAlpha;
  D3D11_BLEND    DestBlendAlpha;
  D3D11_BLEND_OP BlendOpAlpha;
  UINT8          RenderTargetWriteMask;
} D3D11_RENDER_TARGET_BLEND_DESC;

 

这是我们主要讨论的内容:

https://msdn.microsoft.com/en-us/library/windows/desktop/ff476200        

可以看msdn的解释。

  BlendEnable  默认false,设为true时表示使用混合

  SrcBlend,DestBlend与SrcBlendAlpha,DestBlendAlpha都是枚举类型D3D11_BLEND的成员指定混合系数。

  BlendOP与BlendOPAlpha是D3D11_BLEND的成员,指定了混合的操作符

先看混合的数学方程:

C = Csrc ⊗ Fsrc ? Cdst ⊗ Fdst

这里的Csrc指的是我们正在处理的那个像素的颜色,Cdes指的是已经处理好了,放在后台缓冲区的颜色(这里会有一个深度的问题,先不考虑)。在不开启混合的情况下,我们正在处理的颜色会覆盖掉后台的颜色。当使用混合时,后台的颜色与现在的颜色会通过上面的式子产生一个新的颜色

先看混合系数Fsrc与Fdst就是SrcBlend,DestBlend的枚举体定义:

typedef enum D3D11_BLEND { 
  D3D11_BLEND_ZERO              = 1,
  D3D11_BLEND_ONE               = 2,
  D3D11_BLEND_SRC_COLOR         = 3,
  D3D11_BLEND_INV_SRC_COLOR     = 4,
  D3D11_BLEND_SRC_ALPHA         = 5,
  D3D11_BLEND_INV_SRC_ALPHA     = 6,
  D3D11_BLEND_DEST_ALPHA        = 7,
  D3D11_BLEND_INV_DEST_ALPHA    = 8,
  D3D11_BLEND_DEST_COLOR        = 9,
  D3D11_BLEND_INV_DEST_COLOR    = 10,
  D3D11_BLEND_SRC_ALPHA_SAT     = 11,
  D3D11_BLEND_BLEND_FACTOR      = 14,
  D3D11_BLEND_INV_BLEND_FACTOR  = 15,
  D3D11_BLEND_SRC1_COLOR        = 16,
  D3D11_BLEND_INV_SRC1_COLOR    = 17,
  D3D11_BLEND_SRC1_ALPHA        = 18,
  D3D11_BLEND_INV_SRC1_ALPHA    = 19
} D3D11_BLEND;

 

这里我引用他人的翻译,地址:http://shiba.hpe.sh.cn/jiaoyanzu/WULI/Article1563

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 = (1as,1as,1as)且F =1as
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个参数指定(9.4节)。也就是说,我们可以将一个颜色指定为混合系数;在修改混合状态前,该颜色一直有效。
D3D11_BLEND_INV_BLEND_FACTOR:F = (1-r,1-g,1-b)且F = 1-a,其中,颜色(r,g,b,a)由ID3D11DeviceContext::OMSetBlendState方法的第2个参数指定(9.4节)。也就是说,我们可以将一个颜色指定为混合系数;在修改混合状态前,该颜色一直有效。

 

////

//

然后是操作符的定义了,操作符在数学式子中用?表示,结构中体就是BlendOP

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,    //取小的
  D3D11_BLEND_OP_MAX           = 5     //取大的
} D3D11_BLEND_OP;

 

//////

最后还有一个元素:

RenderTargetWriteMask,这个参数对于写入的类型进行限制比如禁止RED颜色写入,可以是多个标志位的组合,如下:

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;

 

 

然后我的创建代码:

HRESULT DrawFunction::CreateBlending(void)
{
    HRESULT hr = S_OK;//ret
    // 设置Blend描述
    D3D11_BLEND_DESC blendDesc;
    ZeroMemory(&blendDesc, sizeof(blendDesc));
    blendDesc.AlphaToCoverageEnable = FALSE;
    blendDesc.IndependentBlendEnable = FALSE;
    blendDesc.RenderTarget[0].BlendEnable = TRUE;
    blendDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
    blendDesc.RenderTarget[0].DestBlend = D3D11_BLEND_ONE;
    blendDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_SUBTRACT;
    blendDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
    blendDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ONE;
    blendDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_SUBTRACT;
    blendDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
    hr = dev->CreateBlendState(&blendDesc, &pBlendStateSub);

    blendDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
    blendDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
    blendDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA;
    blendDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
    hr = dev->CreateBlendState(&blendDesc, &pBlendStateAlpha);

    return hr;
}

 

 

最后可以用OMSetBlendState设置,启用/关闭混合。

void OMSetBlendState(
  [in]       ID3D10BlendState *pBlendState,
  [in] const FLOAT            BlendFactor[4],
  [in]       UINT             SampleMask
);

 

主要是第一个参数,设为NULL表示关闭混合(设为默认状态?)

 

 

 

其它的看一下我上传的简单的demon

工程文件下载

 

DirectX11笔记6:混合blend

标签:

原文地址:http://www.cnblogs.com/Windogs/p/5002688.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!