不得不说,这个是目前为止最为复杂的一个程序,不光是因为包含有很多的Pass,而且添加了很多的RenderTarget。每个Pass的功能倒是比较容易理解,但是要理清每个RenderTarget的功能就要费上一番功夫。因为本例中使用了7个RenderTarget(So Crazy),下面我们来说说每个RenderTarget的功能。

      该程序一共使用了如图所示的RenderTarget,

    

         其中 RenderTargetOriginal 表面大小等于ViewPort,

         RenderTargetSmallTemp, Glow1, Glow2, Glow2A表面大小等于128×128,

         Glow3和Glow3A大小等于64×64;

         HDR Glare的绘制流程用语言比较难描述,于是我做了一幅图,一目了然。

 

      关于最后一步的alpha混合,所采用的是D3DBLENDOP_ADD.

      这是一个非常好的Alpha混合练习,如果对Alpha混合不了解,尝试一下改变StateBlock中的Alpha项的值,Alpha这块是我的弱项,因为我没有写过这方面的DEMO,只是看过相关资料。

      D3DRS_ALPHABLENDENABLE:Alpha混合选项;

      D3DRS_ALPHATESTENABLE:Alpha测试选项;

      如果 D3DRS_ALPHATESTENABLE设置为FLASE(提前是 D3DRS_ALPHABLENDENABLE为TRUE),则ScrPixel不经过任何测试,直接与DestPixel进行混合;如果D3DRS_ALPHATESTENABLE设置为TRUE,这时就要进行Alpha测试了,我们就需要一个函数及一个掩码,即D3DRS_ALPHAFUNC(缺省值为D3DCMP_LESSEQUAL)及D3DRS_ALPHAREF(0x0),需要将ScrPixel的α与D3DRS_ALPHAREF值进行比较,比较成功(比较函数由D3DRS_ALPHAFUNC值来定),则接受该像素进行进一步混合,否则拒绝该像素混合。

      假设我们通过了Alpha测试(包含 D3DRS_ALPHATESTENABLE设置为FLASE,也可认为是通过了测试),我们就需要对ScrPixel和DestPixel进行混合了。

     the blend operator can be one of the following:     

  • D3DBLENDOP_ADD: Sets the blending equation to:

    OutputPixel= SourcePixel SourceBlendFactor + DestPixel DestBlendFactor

  • D3DBLENDOP_SUBTRACT: Sets the blending equation to:

    OutputPixel = SourcePixel SourceBlendFactor -DestPixel DestBlendFactor

  • D3DBLENDOP_REVSUBTRACT: Sets the blending equation to:

    OutputPixel = DestPixel DestBlendFactor- SourcePixel SourceBlendFactor

  • D3DBLENDOP_MIN: Sets the blending equation to:

    OutputPixel = min(SourcePixel SourceBlendFactor, DestPixel DestBlendFactor)

  • D3DBLENDOP_MAX: Sets the blending equation to:

    OutputPixel = max(SourcePixel SourceBlendFactor, DestPixel DestBlendFactor);

 

         我们会发现我们还缺少SourceBlendFactorDestBlendFactor,可以通过设置D3DBLEND来改变我们所需要的混合权重,一般设置为如下:

         D3DBLEND_SRCALPHA——Blend factor is (As, As, As, As).
         D3DBLEND_INVSRCALPHA——Blend factor is ( 1 - As, 1 - As, 1 - As, 1 - As).
         好,以上是对Alpha混合进行一个回忆,现在我们来看在该例子中Alpha混合是如何进行的。
         我们在最后一个Pass中计算三个RenderTarget的颜色之和,并将它们与BufferBack混合(注意:alpha混合是在Pixel Shader之后)。
         代码如下:
 1 sampler Texture0;
 2 sampler Texture1;
 3 sampler Texture2;
 4 float Glow_Factor1;
 5 float Glow_Factor2;
 6 float Glow_Factor3;
 7 
 8 float SourceAlpha;
 9 
10 float4 ps_main(float2 Tex  : TEXCOORD0) : COLOR0
11 {   
12    return  
13      float4((tex2D(Texture0,Tex).xyz)*Glow_Factor1,SourceAlpha) +
14      float4((tex2D(Texture1,Tex).xyz)*Glow_Factor2,0) +
15      float4((tex2D(Texture2,Tex).xyz)*Glow_Factor3,0);    
16 }

      SourceAlpha在程序中取值为1。我们认为此时三个纹理混合在一起的RenderTarget为ScrPixel,而BufferBack现在为DestPixel,正好程序设置的是需要进行α混合,但不需要进行α测试,我们直接对源像素及目标像素进行混合,由于混合方法是D3DBLENDOP_ADD,我们采取如下公式:

       OutputPixel= SourcePixel SourceBlendFactor + DestPixel DestBlendFactor

       StateBlock中对SourceBlendFactor 设置为D3DBLEND_SCRALPHA,D3DBLEND_SRCALPHA: blendFactor = (as, as, as, as);

                              DestBlendFactor设置为D3DBLEND_ONE,D3DBLEND_ONE: blendFactor = (1, 1, 1, 1);

  我们注意到ScrPixel blendFactor = (as, as, as, as) = (1,1,1,1)。如下图所示,因为,PREVIEW下的纹理的Alpha通道为白色,所以 blendFactor = (as, as, as, as) = (1,1,1,1)。

     

      而DestPixel的 blendFactor = (1, 1, 1, 1)也等于(1,1,1,1),虽然它具备非1的alpha通道,但是我们并不使用它的alpha通道,因为在StateBlock中权重被设置为了D3DBLEND_ONE将如下图:

      

 

      起初我有一个疑问,目标像素跟源像素的Blendfactor都为(1,1,1,1)了,混合结果岂不是很亮???

      后来发现混合结果只是比DestPixel亮了一些,原因在于:

      return  float4((tex2D(Texture0,Tex).xyz)*Glow_Factor1,SourceAlpha) +  float4((tex2D(Texture1,Tex).xyz)*Glow_Factor2,0) +  float4((tex2D(Texture2,Tex).xyz)*Glow_Factor3,0);   

      语句中的Glow_Factor取值只有0.15左右,总共加起来,ScrPixel的亮度也不足以其任何一个成员原先的一半,正是这三个变量抑制了ScrPixel的亮度,使得最终混合图像不是我想象的那样。

      看来唯有实践才能知道最终是什么结果.
      写代码时容易犯的错误:

      1. 最后一个Pass中混合纹理时三个纹理采样,Mipmap,Maxfliter及Minfliter均设置为D3DTEXF_LINER,Glow3对画面影响最严重,若果不设置为D3DTEXF_LINER,会出现马赛克 :)

      2. Render to texture时一定要注意:     

1   Out.texCoord.x = 0.5 * (1 + Pos.x - 1/128);
2   Out.texCoord.y = 0.5 * (1 - Pos.y - 1/128);

  后边的1/128千万不要写成1.0/128.0,要不然画面会向右偏移(我用的是XP系统),这个现象目前尚未搞明白为什么 :(     

      //End......

     

        

posted on 2013-08-08 01:33  infinityward  阅读(384)  评论(0编辑  收藏  举报