zoukankan      html  css  js  c++  java
  • DirectX12 3D 游戏开发与实战第七章内容(下)

    利用Direct3D绘制几何体(续)

    学习目标

    1. 学会一种无须每帧都要刷新命令队列的渲染流程,由此来优化程序的性能

    2. 了解另外两种跟签名参数类型:根描述符和根常量

    3. 探索如何在程序中生成和绘制常见的几何体,如栅格、圆台和球体

    4. 研究如何通过动态顶点缓冲区来更新CPU中的顶点数据,并且向GPU中上传顶点新的位置信息

    7.6、 细探根签名

    在前面我们已经介绍过跟签名,它定义了在绘制调用之前,需要绑定到渲染流水线上的资源,以及这些资源如何映射到着色器的输入寄存器中。

    7.6.1 、根参数

    根签名是由一系列根参数组成的,到目前为止,我们只创建过只含有一个描述符表的根参数。实际上,根参数有三个类型可以选择:

    1. 描述符表:描述符表引用的是描述符堆中的一块连续范围,用于确定要绑定的资源
    2. 根描述符:通过直接设置根描述符就可以指示要绑定的资源,无需将它存在描述符堆中。但是,只有常量缓冲区的CBV,缓冲区的SRV/UAV才能使用根描述符进行绑定
    3. 根常量:借助根常量即可直接绑定一系列32位的常量值

    考虑到性能的原因,一个根签名最好不要放置超过64DWORD的根参数,下面是三种根参数的空间占用情况:

    1. 描述符表:1DWORD
    2. 根描述符:2DWORD
    3. 根常量:每个常量32位,占1DWORD

    在代码中,我们需要通过填写CD3DX12_ROOT_PARAMETER结构体来描述根参数,CD3DX12_ROOT_PARAMETER是对结构体D3D12_ROOT_PARAMETER进行的扩展,并增加一些辅助初始化函数而得到的

    typedef struct D3D12_ROOT_PARAMETER
    {
        //用于指示根参数的类型(描述符表,根常量或者根描述符)
        D3D12_ROOT_PARAMETER_TYPE ParameterType;
        //描述根参数的结构体
        union 
            {
            D3D12_ROOT_DESCRIPTOR_TABLE DescriptorTable;
            D3D12_ROOT_CONSTANTS Constants;
            D3D12_ROOT_DESCRIPTOR Descriptor;
            };
        //指定此根参数在着色器程序中的可见性
        D3D12_SHADER_VISIBILITY ShaderVisibility;
    }D3D12_ROOT_PARAMETER;
    

    7.6.2、描述符表

    通过填写D3D12_ROOT_PARAMERTER结构体中的成员DescriptorTable,即可将根参数的类型定义为描述符表(Descriptor Tabel)

    typedef struct D3D12_ROOT_DESCRIPTOR_TABLE
    {
        //D3D12_DESCRIPTOR_RANGE类型数组的元素个数
        UINT NumDescriptorRanges;
        //指向D3D12_DESCRIPTOR_RANGE类型数组的指针
        const D3D12_DESCRIPTOR_RANGE *pDescriptorRanges;
    }D3D12_ROOT_DESCRIPTOR_TABLE;
    

    通过上述的结构体,我们可以指定一个D3D12_DESCRIPTOR_RANGE类型的数组:

    typedef struct D3D12_DESCRIPTOR_RANGE
    {
        //此范围中的描述符类型
        D3D12_DESCRIPTOR_RANGE_TYPE RangeType;
        //此范围内描述符的数量
        UINT NumDescriptors;
        //此描述符范围要绑定的基准着色器寄存器
        UINT BaseShaderRegister;
        //此描述符范围要绑定的寄存器空间
        UINT RegisterSpace;
        //此描述符范围距离描述符表起始地址的偏移量
        UINT OffsetInDescriptorsFromTableStart;
    }D3D12_DESCRIPTOR_RANGE;
    

    接下来我们举个例子:用3个CBV、2个SRV和1个UAV创建一个描述符表

    //用3个CBV、2个SRV和1个UAV来创建一个描述符表
    CD3DX12_DESCRIPTOR_RANGE descRange[3];
    descRange[0].Init(D3D12_DESCRIPTOR_RANGE_TYPE_CBV, 3, 0, 0, 0);
    descRange[1].Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 2, 0, 0, 3);
    descRange[2].Init(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 1, 0, 0, 5);
    CD3DX12_ROOT_PARAMETER slotRootParameter[1];
    slotRootParameter[0].InitAsDescriptorTable(3, descRange, D3D12_SHADER_VISIBILITY_ALL);
    

    7.6.3、根描述符

    通过填写结构体D3D12_ROOT_PARAMETER中的成员Descriptor,即可将根参数类型定义为根描述符(Root Descriptor)

    typedef struct D3D12_ROOT_DESCRIPTOR
    {
        //指定要绑定的着色器寄存器
        UINT ShaderRegister;
        //指定要绑定的着色器寄存器空间
        UINT RegisterSpace;
    }D3D12_ROOT_DESCRIPTOR;
    

    和描述符表需要在描述符中设置对应的描述符句柄不同,要配置描述符,我们只需要绑定资源的虚拟地址即可

    //计算常量缓冲区的大小
    UINT objCBByteSize = d3dUtil::CalcConstantBufferByteSize(sizeof(ObjectConstants));
    //资源的虚拟地址
    D3D12_GPU_VIRTUAL_ADDRESS cbAddress = objectCB->GetGPUVirtualAddress();
    //偏移到缓冲区中此物体常量的地址
    cbAddress += i*objCBByteSize;
    cmdList->setGraphicsRootVConstnatBufferView(0, objCBAddress);
    

    7.6.4、根常量

    通过填写结构体D3D12_ROOT_PARAMETER的成员Constants,即可进一步将根参数类型定义为根常量(Root Constant)

    typedef struct D3D12_ROOT_CONSTANTS
    {
    	//指定绑定的寄存器
        UINT ShaderRegister;
        //指定绑定的寄存器空间
        UINT RegisterSpace;
        //根参数所需要的32位常量个数
        UINT Num32BitValues;
    }D3D12_ROOT_CONSTANTS;
    

    根参数的使用示例就不展示了。

    7.6.5、 更复杂的根签名示例

    考虑一下着色器所需要的下列资源的情景:

    Texture2D gDiffuseMap : register(t0);
    
    cbuffer cbPerObject : register(b0)
    {
        float4x4 gWorld;
        float4x4 gTexTransform;
    }
    
    cbuffer cbPass : register(b1)
    {
        float4x4 gView;
        float4x4 gInvView;
        float4x4 gProj;
        float4x4 gInvProj;
        float4x4 gViewProj;
        float4x4 gInvViewProj;
        float3 gEvePosW;
        float cbPerObjectPad1;
        float2 gRenderTargetSize;
        float2 gInvRenderTargetSize;
        float gNearZ;
        float gFarZ;
        float gTotalTime;
        float gDeltaTime;
        float4 gAmbientLight;
    }
    
    cbuffer cbMaterial : register(b2)
    {
        float4 gDiffuseAlbedo;
        float3 gFresne1R0;
        float gRoughness;
        float4x4 gMatTransform;
    }
    

    此着色器对应的根签名描述:

    //描述符范围,给描述符表使用
    CD3DX12_DESCRIPTOR_RANGE texTable;
    texTable.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0);
    
    CD3DX12_ROOT_PARAMETER slotRootParameter[4];
    //性能提示:按变更频率由高到低进行排列
    slotRootParameter[0].InitAsDescriptorTable(1, &texTable, D3D12_SHADER_VISIBILITY_PIXEL);
    slotRootParameter[1].InitAsConstantBufferView(0);
    slotRootParameter[2].InitAsConstantBufferView(1);
    slotRootParameter[3].InitAsConstantBufferView(2);
    CD3DX12_ROOT_SIGNATURE_DESC rootSigDesc(4, slotRootParameter, 0, nullptr,
            D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT);
    

    7.6.6、根参数的版本控制

  • 相关阅读:
    洛谷 P2580 于是他错误的点名开始了(Trie)
    AcWing 142. 前缀统计(Trie)
    Codeforces Round #646 (Div. 2) E. Tree Shuffling(贪心/树形DP)
    Django form表单|form组件常用字段、校验
    AJAX | json、上传文件、SweetAlert插件
    Django中间件
    Django的Cookie、Session和自定义分页
    Django的ORM操作-FQ-事物
    django-模板引擎进阶
    django-视图函数进阶
  • 原文地址:https://www.cnblogs.com/yaya12138/p/11831774.html
Copyright © 2011-2022 走看看