DirectX12 3D 游戏开发与实战第七章内容(下)
利用Direct3D绘制几何体(续)
学习目标
学会一种无须每帧都要刷新命令队列的渲染流程,由此来优化程序的性能
了解另外两种跟签名参数类型:根描述符和根常量
探索如何在程序中生成和绘制常见的几何体,如栅格、圆台和球体
研究如何通过动态顶点缓冲区来更新CPU中的顶点数据,并且向GPU中上传顶点新的位置信息
7.6、 细探根签名
在前面我们已经介绍过跟签名,它定义了在绘制调用之前,需要绑定到渲染流水线上的资源,以及这些资源如何映射到着色器的输入寄存器中。
7.6.1 、根参数
根签名是由一系列根参数组成的,到目前为止,我们只创建过只含有一个描述符表的根参数。实际上,根参数有三个类型可以选择:
- 描述符表:描述符表引用的是描述符堆中的一块连续范围,用于确定要绑定的资源
- 根描述符:通过直接设置根描述符就可以指示要绑定的资源,无需将它存在描述符堆中。但是,只有常量缓冲区的CBV,缓冲区的SRV/UAV才能使用根描述符进行绑定
- 根常量:借助根常量即可直接绑定一系列32位的常量值
考虑到性能的原因,一个根签名最好不要放置超过64DWORD的根参数,下面是三种根参数的空间占用情况:
- 描述符表:1DWORD
- 根描述符:2DWORD
- 根常量:每个常量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、根参数的版本控制
略
DirectX12 3D 游戏开发与实战第七章内容(下)的更多相关文章
- DirectX12 3D 游戏开发与实战第七章内容(上)
利用Direct3D绘制几何体(续) 学习目标 学会一种无须每帧都要刷新命令队列的渲染流程,以此来优化性能 了解另外两种根签名参数类型:根常量和根描述符 探索如何在程序中生成和绘制常见的几何体:如栅格 ...
- DirectX12 3D 游戏开发与实战第五章内容
渲染流水线 学习目标: 了解用于在2D图像中表现出场景立体感和空间深度感等真实效果的关键因素 探索如何用Direct3D表示3D对象 学习如何建立虚拟摄像机 理解渲染流水线,根据给定的3D场景的几何描 ...
- DirectX12 3D 游戏开发与实战第六章内容
利用Direct3D绘制几何体 学习目标 探索用于定义.存储和绘制几何体数据的Direct接口和方法 学习编写简单的顶点着色器和像素着色器 了解如何用渲染流水线状态对象来配置渲染流水线 理解怎样创建常 ...
- DirectX12 3D 游戏开发与实战第四章内容(上)
Direct3D的初始化(上) 学习目标 了解Direct3D在3D编程中相对于硬件所扮演的角色 理解组件对象模型COM在Direct3D中的作用 掌握基础的图像学概念,例如2D图像的存储方式,页面翻 ...
- DirectX12 3D 游戏开发与实战第四章内容(下)
Direct3D的初始化(下) 学习目标 了解Direct3D在3D编程中相对于硬件所扮演的角色 理解组件对象模型COM在Direct3D中的作用 掌握基础的图像学概念,例如2D图像的存储方式,页面翻 ...
- DirectX12 3D 游戏开发与实战第三章内容
变换 学习目标 理解如何使用矩阵表示线性变换和仿射变换 学习对几何体进行缩放.旋转和平移的坐标变换 根据矩阵之间的乘法运算性质,将多个变换矩阵合并为一个单独的净变换矩阵 找寻不同坐标系之间的坐标转换方 ...
- DirectX12 3D 游戏开发与实战第十一章内容
仅供个人学习使用,请勿转载.谢谢! 11.模板 模板缓冲区(stencil buffer)是一种"离屏"(off-screen)缓冲区,我们可以利用它来实现一些效果.模板缓冲区.后 ...
- DirectX12 3D 游戏开发与实战第八章内容(下)
DirectX12 3D 游戏开发与实战第八章内容(下) 8.9.材质的实现 下面是材质结构体的部分代码: // 简单的结构体来表示我们所演示的材料 struct Material { // 材质唯一 ...
- DirectX12 3D 游戏开发与实战第八章内容(上)
8.光照 学习目标 对光照和材质的交互有基本的了解 了解局部光照和全局光照的区别 探究如何用数学来描述位于物体表面上某一点的"朝向",以此来确定入射光照射到表面的角度 学习如何正确 ...
随机推荐
- 【UE4 C++】Actor 与 Component —— 创建、销毁
Actor的生成与销毁 创建Actor实例 UClass* TSubclassOf<T> SpawnActor() UPROPERTY(EditAnywhere, Category = & ...
- 面试题系列:new String("abc")创建了几个对象
new String("abc")创建了几个对象 面试官考察点猜想 这种问题,考察你对JVM的理解程度.涉及到常量池.对象内存分配等问题. 涉及背景知识详解 在分析这个问题之前,我 ...
- rabbitmq生产者消息确认
在使用 RabbitMQ 的时候,有时候当我们生产者发送一条消息到 RabbitMQ 服务器后,我们 生产者想知道消息是否到达了 RabbitMQ 服务器上.这个时候我们应该如何处理? 针对上述问题, ...
- [火星补锅] 非确定性有穷状态决策自动机练习题Vol.3 T3 && luogu P4211 [LNOI2014]LCA 题解
前言: 这题感觉还是很有意思.离线思路很奇妙.可能和二次离线有那么一点点相似?当然我不会二次离线我就不云了. 解析: 题目十分清真. 求一段连续区间内的所有点和某个给出的点的Lca的深度和. 首先可以 ...
- stm32串口USART 硬件流控 --学习笔记
流控的概念源于 RS232 这个标准,在 RS232 标准里面包含了串口.流控的定义.大家一定了解,RS232 中的"RS"是Recommend Standard 的缩写,即&qu ...
- 【做题记录】CF1451E2 Bitwise Queries (Hard Version)
CF1451E2 Bitwise Queries (Hard Version) 题意: 有 \(n\) 个数( \(n\le 2^{16}\) ,且为 \(2\) 的整数次幂,且每一个数都属于区间 \ ...
- Shadertoy 教程 Part 2 - 圆和动画
Note: This series blog was translated from Nathan Vaughn's Shaders Language Tutorial and has been au ...
- Python | 实现pdf文件分页
不知道大家有没有遇到过这么一种情况,就比如一个pdf格式的电子书,我们经常浏览的是其中的一部分,而这电子书的页数很大,每当需要浏览时,就需要翻到对应的页码,就有点儿繁琐. 还有一些情况,比如,我们想分 ...
- MVC之三个单选按钮的切换选择
实现需求: 1.三个多选按钮中:只能同时选择限时抢购和分享金或者拼团特惠和分享金,其中限时抢购和拼团特惠不能同时选择.并且点击后显示,再次点击赢隐藏. 1 @*活动信息*@ 2 <div> ...
- Linux下文件的三种时间标记:访问时间、修改时间、状态改动时间 (转载)
在windows下,一个文件有:创建时间.修改时间.访问时间. 而在Linux下,一个文件也有三种时间,分别是:访问时间.修改时间.状态改动时间. 两者有此不同,在Linux下没有创建时间的概念,也就 ...