zoukankan      html  css  js  c++  java
  • 关于Depth Bounds Test (DBT)和在CE3的运用

    Depth Bounds Test (DBT)
    Depth Bounds Test(深度范围检测),是Nvdia GeForce 6系列以后显卡的特性(GPU Programming Guide GeForce 8 and 9 Series),并不是DirectX的特性。所以在例如Nsight和Pix的图形分析工具里,是看不到它的设置的。
     
    Depth Bounds Test的功能是允许程序员在blend render target前进行额外的像素Discard。这个扩展增加了一个新的逐个fragment 的测试,从逻辑上讲,它是在scissor test的后面,alpha test的前面,DBT会把保存在输入的fragment 坐标(xw,yw)位置的深度值,和用户定义的最大和最小深度值做比较,如果保存的深度值在用户定义的范围外的话,那么这个输入的fragment 会被discard掉,和alpha test不同的是,DBT并不依赖fragment在窗口空间的深度值。
    DBT并不依赖从Pixel Shader输出的深度值,而是根据之前保存在render target里的深度位置做判断
    • DBT的逻辑是在 scissor test 后面, alpha testing前面
    • min/max值被clamp在[0, 1]之间,非法值会被转为0
    • DBT会被打开,当下面条件都为真时
      • min < max
      • min > 1 并且 max<1
      • depth值在Shader里被使用
      关于API使用,以CE3为例的话
    void CD3D9Renderer::SetDepthBoundTest(float fMin,float fMax,bool bEnable)
    {
        if(bEnable)
        {
            m_pd3dDevice->SetRenderState(D3DRS_ADAPTIVETESS_X,MAKEFOURCC('N','V','D','B'));
            m_pd3dDevice->SetRenderState(D3DRS_ADAPTIVETESS_Z,*(DWORD*)&fMin);
            m_pd3dDevice->SetRenderState(D3DRS_ADAPTIVETESS_W,*(DWORD*)&fMax);
      }
        else// disable depth bound test
        {
            m_pd3dDevice->SetRenderState(D3DRS_ADAPTIVETESS_X,0);
        }
    }  

      DBT的主要用处有两个,一个例子是在OpenGL extension文档里的例子 可以用来优化stenciled shadow volume 的渲染

      例如,一栈带有衰减等光源,可以在XY窗口空间被边界为矩形,而传统的scissor test,可以把矩形内的 shadow volume 的fragment都discard掉,保证阴影是在光源的windows窗口XY范围外的。
      而stenciled 增长或减少的部分偏离scissor的fragment的时候就无关紧要了,因为光源的照明在scissor区域外的部分,已经可以确实是完全衰减消失的了。
     
      也就是说,scissor test可以把在渲染在scissor外面的 shadow volume fragments 直接discard掉,从而提高了性能,不再需要关注那些衰减的光源最终不会影像的像素。Scissor的优化,可以用在更新渲染用的stenciled shadow volumes的时候(增加或减少stencil buffer),和增加带衰减光源的照明分布的时候。
     
      使用DBT时,我们也可以使用类似的方法,计算出衰减光源的最终照明信息在窗口空间上的Z边界(zmin,zmax),除非像素的深度值在这个范围[zmin, zmax],否则光源的照明可以被预确定是和这个像素是无关的。或者说,被做照明处理的像素在衰减光源足够远的前方或后方,以至于光源在这个像素上的照明完全的衰减没了。而DBT恰好可以做这种测试。
     
      另外一个用处也就是像CE3这种延迟渲染中了,因为光照是转化到屏幕空间进行的,所以在对物体进行光照处理时,可以参考之前的写入的光照深度,屏幕空间上,不在光照深度范围内的像素都DBT裁剪掉。
     
      在CE3.4里,主要还是在一些平面空间处理里使用,这样可以省去alpha test步骤以及额外的像素填充
     

    生成SceneDiffuseAcc,使用DBT就可以省去天空部分像素判断和填充了
     
    生成AO
    CD3D9Renderer::GenerateAO
    1. SetDepthBoundTest(0.f,0.9999f,true);

      下雨效果
      CD3D9Renderer::FX_DeferredRainLayer()

    constVec4 vDepthBounds =CDeferredShading::Instance().GetLightDepthBounds(rainVolParams.m_vWorldPos, rainVolParams.m_fRadius);
    SetDepthBoundTest(max(vDepthBounds.x, fMinZ), min(vDepthBounds.z, fMaxZ),true);

    下雪效果
    CD3D9Renderer::FX_DeferredSnowLayer()

    constVec4 vDepthBounds =CDeferredShading::Instance().GetLightDepthBounds(snowVolParams.m_vWorldPos, snowVolParams.m_fRadius);
    SetDepthBoundTest(max(vDepthBounds.x, fMinZ), min(vDepthBounds.z, fMaxZ),true);

    延迟光照着色
    CDeferredShading::LightPass

    1. Vec4 pDepthBounds =GetLightDepthBounds( pDL );
      rd->SetDepthBoundTest( pDepthBounds.x, pDepthBounds.z,true);

      IBL的延迟着色
      CDeferredShading::DeferredCubemapPass

    1. Vec4 pDepthBounds =GetLightDepthBounds( pDL );
      rd->SetDepthBoundTest( pDepthBounds.x, pDepthBounds.z,true);

      屏幕空间反射
      CDeferredShading::ScreenSpaceReflectionPass 

    1. rd->SetDepthBoundTest(0.0f,0.9999f,true);

      CDeferredShading::DirectionalOcclusionPass()

    2. CDeferredShading::DirectionalOcclusionPass()

      阴影处理
      CDeferredShading::ShadowLightPasses()

    1. Vec4 pDepthBounds =GetLightDepthBounds(&light );
      rd->SetDepthBoundTest( pDepthBounds.x, pDepthBounds.z,true);

      为了在绘制里可以忽略天空部分
      void CDeferredShading::Render()

     
    LPV光照
    CRELightPropagationVolume::DeferredApply()
    if(CRenderer::CV_r_DeferredShadingDepthBoundsTest )
    {
        constVec4 pDepthBounds =CDeferredShading::Instance().GetLightDepthBounds( rRendSettings.m_pos, m_fDistance );
        rd->SetDepthBoundTest(pDepthBounds.x, pDepthBounds.z,true);// skip sky only for GI
    }

    修改方法也比较简单,关闭CV_r_DeferredShadingDepthBoundsTest,或在shader里添加clip来discard掉像素,或用alpha test替代,但这两种方法在移动平台上忌讳的,所以需要进一步测试才有结果了

  • 相关阅读:
    树分治
    实现自己的shell--MIT xv6 shell
    逆元打表
    Linux fork()函数
    三分:求解凸函数极值
    anti-nim 游戏
    nginx配置文件详解
    nginx之别名、location使用
    shell脚本编程基础知识点
    linux任务计划
  • 原文地址:https://www.cnblogs.com/TracePlus/p/4095873.html
Copyright © 2011-2022 走看看