Blending(融合)

    Src Pixesl: 源像素 : 指的是当前光栅化产生的值

    Dst Pixels 目标像素.指的是先前渲染存储在RT中的值

    可以用来实现那些效果,诸如水,玻璃 以及其他的,(后面在说)

    在光栅化ij 像素的时候,如果没有开启混合,那么新值将覆盖旧值(深度测试通过),如果开始混合,那么将通过D3D11_BLEND_DESC 的设置来融合新值和旧值,然后将融合后的值写入,让我们来看下这个DESC

typedef struct D3D11_BLEND_DESC {

BOOL AlphaToCoverageEnable;

BOOL IndependentBlendEnable;

D3D11_RENDER_TARGET_BLEND_DESC RenderTarget[8];

} D3D11_BLEND_DESC;

    抛去前两个项不讲,因为我们可以同时绑定多个RT,所以RT的DESC是个数组,用来纷纷对应, IndependentBlendEnable项根据名字便可以得知,当其设置为true时,不同的RT使用对应的RT_DESC,而设置为false,便只会使用RenderTarget[0], D3D11_RENDER_TARGET_BLEND_DESC 会详细指定如何融合

    

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;

    第二个项和第三个项用来设置源像素和目标像素的系数(权重),第四个项用来指定两个分别计算出来的值将如何计算的(一般的是D3D11_BLEND_OP_ADD ),最终颜色便是这样计算的

        OutputPixel = ( SourceColor.rgba * SrcBlend ) __BlendOp__ ( DestColor.rgba * DestBlend )

你可以看见alpha是另外计算的,计算方式同上

    那么D3D11_BLEND到底有那些系数了:

        D3D11_BLEND_ZERO /D3D11_BLEND_ONE 故名思意

        D3D11_BLEND_SRC_COLOR = (Rs, Gs, Bs, As) (注意,括号里是颜色值)

        既然有SRV_COLOR,那么也有对应 的INV_SRC,系数为1 – 对应的项,即: (1 - Rs, 1 - Gs, 1 - Bs, 1 - As),也有对应的DST_COLOR,INV_DST_COLOR

        那么还有SRC_ALPHA,INV_SRC_ALPHA,还有对应的DST_ALPHA

    还有一些比较特殊的就不写了

(一般的,我们很少需要DST的ALPHA,因为一般的算法只需要有SRC的ALPHA即可完成)

    有那些操作:

        相加,相减(dst-src),反向相减(src-dst),{最小和最大(这个时候忽略系数,直接对颜色操作)

(你可以为颜色和alpha指定不同的操作,否则两个op毫无存在意义)

    至于创建,所有的创建接口都在ID3D11Device哦,函数实在没什么好介绍的

至于AlphaToCoverageEnable 暂时设置为false

RenderTargetWriteMask 你可以用来控制颜色的写入,几个枚举量是enable_red,green,blue,alpha,你可以对他们使用 | 运算符

至于绑定一个BlendState,调用DeviceContext的接口即可(这函数可以接受系数,用来特定的系数计算,具体见D3D11_BLEND_BLEND_FACTOR 或者 D3D11_BLEND_INV_BLEND_FACTOR)

下面的代码创建,以及完成绑定

D3D11_BLEND_DESC transparentDesc = { 0 };

    //transparentDesc.AlphaToCoverageEnable = false; 默认为false

    //transparentDesc.IndependentBlendEnable = false; 默认为false

    transparentDesc.RenderTarget[0].BlendEnable = true;

    transparentDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;

    transparentDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;

    transparentDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;

    transparentDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;

    transparentDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;

    transparentDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;

    transparentDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;

    ID3D11BlendState* TransparentBS;

    ID3D11Device->CreateBlendState(&transparentDesc, &TransparentBS));

    float blendFactors[] = { 0.0f, 0.0f, 0.0f, 0.0f };

    ID3D11DeviceContext->OMSetBlendState(TransparentBS, blendFactor, 0xffffffff);

 

实际应用时,我们需要统一管理这些状态,这是很必要的,而且要避免状态的切换(这个也许说的不对)

题外话:

    渲染状态大概有以下:

        世界,观察,投影矩阵,光源,纹理绑定,纹理寻址和过滤方式,深度测试,融合(blend),

    有意思的是,路过在提交图元之间,我们忘记设置某方面的状态,上一图元的设置便会泄露到下一图元.这是个重要的暗示,因为切换状态总是需要代价的

 

    下一篇文章将实现一些具体效果

你可能感兴趣的:(Blend)