• D3D10/11中的遮挡查询的使用


          在D3D10/11中,有D3D10_QUERY/D3D11_QUERY接口,通过QUERY接口,我们可以查询GPU的一些状态,比如GPU的时间戳信息(Timestamp)[这个常用来做performance分析],或者遮挡查询信息等等。我们通过directx sdk中的例子来看看在D3D10/11中,如何使用遮挡查询。源文件目录:SDK root\Samples\C++\Direct3D10\DrawPredicated

         首先看看场景中包含哪些物体:6个望远镜(望远镜是高模,mesh数目比较多),望远镜中间有个灯塔形状的物体,再就是立方体表示的城市模型,另外还有还有一个没有显示的物体,就是望远镜的包围盒(低模),当我们勾选了Render Occluders后,就可以看到该包围盒。

    image

         

    image

         

           从D3D11教程管线的介绍中我们知道,当D3D把Draw传给GPU时候,通常要经过Command Processor-Vertex shader-PA(体元装配)-RS(光栅化)-Pixel shader-color buffer,这几个阶段(不考虑GS和 Tessllation)。

          一个三角形,经过一个很长的渲染管线,最终会在屏幕上显示出来,要是像上图中的望远镜一样,它在我们的视野中,还好,如果像下图一样,我们眼前是一堵墙,后面的物体根本看不到,但是这些高模的望远镜,VS和PS还是要做,会消耗很多的GPU时间,如果我们使用遮挡查询预测的功能,对高模的望远镜,给其配备一个贴身的低模包围盒,通过查询包围盒的遮挡情况,如果包围盒在当前帧中,所有采样(在深度测试时候,是以sample为单位,看以看下关于msaa的教程)都z fail,则查询

    D3D10_QUERY_OCCLUSION_PREDICATE返回false,如果有任何一个采样z pass则返回true,在返回false的情况下,意味着包围盒在当前帧中,完全不可见,那么包围盒当中的望远镜,当然也是完全不可见,这时在渲染望远镜时,我们可以启动预测功能,就是根据包围盒的的遮挡查询结果来渲染,在gpu硬件层次,在command processor中,它就会丢弃该draw,不会做vs和ps,这样就可以有效的提高FPS。比如下面二图,启用prediction的情况下,FPS是460帧,没有启用的情况下,只有261。

    image

    image

    代码的实现也很简单:

    首先要定义预测变量

    ID3D10Predicate*                    g_pPredicate[NUM_MICROSCOPE_INSTANCES] = {NULL};

    因为场景中有6个望远镜,所以通过一个数组来表示所有预测变量,

    在程序初始化时候,会创建这些遮挡查询预测:

    // 创建预测

    D3D10_QUERY_DESC qdesc;
    qdesc.MiscFlags = D3D10_QUERY_MISC_PREDICATEHINT;
    qdesc.Query = D3D10_QUERY_OCCLUSION_PREDICATE;
    for( int i = 0; i < NUM_MICROSCOPE_INSTANCES; i++ )
    {
        V_RETURN( pd3dDevice->CreatePredicate( &qdesc, &g_pPredicate[i] ) );
    }

    渲染包围盒和望远镜时候,要保持他们渲染的前后顺序

    // 渲染望远镜的包围盒

    for( int i = 0; i < NUM_MICROSCOPE_INSTANCES; i++ )
    {
        D3DXMATRIX mMatRot;
        D3DXMATRIX mWVP;
        D3DXMatrixRotationY( &mMatRot, i * ( D3DX_PI / 3.0f ) );
        mWVP = mMatRot * mWorldViewProj;
        g_pmWorldViewProj->SetMatrix( ( float* )&mWVP );

       // 渲染包围盒mesh,注意被一个预测变量包在中间

        //而且用g_pRenderOccluder渲染时,包围盒并不会在屏幕上显示出来,而是通过alpha blending丢掉的它的渲染结果,但是深度信息会被保存在memory中,以便下面渲染望远镜时候,使用它的z pass信息进行预测。

        if( g_bUsePredication )
        {
            g_pPredicate[i]->Begin();
            g_OccluderMesh.Render( pd3dDevice, g_pRenderOccluder );
            g_pPredicate[i]->End();
        }
    }

    // 渲染包围盒后再渲染望远镜,注意预测功能开启与关闭的代码。

    for( int i = 0; i < NUM_MICROSCOPE_INSTANCES; i++ )
    {
        D3DXMATRIX mMatRot;
        D3DXMATRIX mWVP;
        D3DXMatrixRotationY( &mMatRot, i * ( D3DX_PI / 3.0f ) );
        mWVP = mMatRot * mWorldViewProj;
        g_pmWorldViewProj->SetMatrix( ( float* )&mWVP );

        if( g_bUsePredication )
        {
            pd3dDevice->SetPredication( g_pPredicate[i], FALSE );
        }

        g_HeavyMesh.Render( pd3dDevice, g_pRenderTextured, g_pDiffuseTex );

        if( g_bUsePredication )
        {
            pd3dDevice->SetPredication( NULL, FALSE );
        }

  • 相关阅读:
    [CentOS5]安装VirtualBox
    [Java]一则自定义的XStream转换器,主要用于POJO XML反序列化为Map/List
    [CentOS5]开启vsftpd中本地用户的上传权限
    [CSS]强制TD不换行
    [CentOS5]快速关闭SeLinux
    [vba]获取PPT幻灯片中的所有标题
    [VBA]批量转换xls为csv
    [OTHER]玩具的报复 绿化版 注册表
    [CentOS]在vsftpd中为本地用户指定默认目录
    递归读取输出无限分类目录
  • 原文地址:https://www.cnblogs.com/mikewolf2002/p/2836422.html
Copyright © 2020-2023  润新知