zoukankan      html  css  js  c++  java
  • Chapter8-Making Your Day Brighter之Your First HDR Shader: The Glare!

          不得不说,这个是目前为止最为复杂的一个程序,不光是因为包含有很多的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......

         

            

  • 相关阅读:
    setTimeout 理解
    Git 使用规范流程
    JavaScript异步编程 ( 一 )
    javaScript模块化一
    javascript 知识点坑
    javaScript闭包
    函数式编程
    JavaScript的68个技巧一
    MySql 隐式转换
    MySQL优化
  • 原文地址:https://www.cnblogs.com/infintyward/p/3244888.html
Copyright © 2011-2022 走看看