一、D3D初始化
1.纹理格式
-
纹理的用途:1) 存储图像数据; 2) 存储3D向量(如法线贴图);
-
纹理格式:
只有存储在DXGI_FORMAT枚举类型中描述的特定格式的数据元素才能用于组成纹理。
1.DXGI_FORMAT_R32G32B32_FLOAT:每个元素由3个32位浮点数分量构成。
2.DXGI_FORMAT_R16G16B16A16_UNORM:每个元素由4个16位分量构成,每个分量都被映射到 [0, 1] 区间。
3.DXGI_FORMAT_R32G32_UINT:每个元素由2个32位无符号整数分量构成。
4.DXGI_FORMAT_R8G8B8A8_UNORM:每个元素由4个8位无符号分量构成,每个分量都被映射到 [0, 1] 区间。
5.DXGI_FORMAT_R8G8B8A8_SNORM:每个元素由4个8位有符号分量构成,每个分量都被映射到 [−1, 1] 区间。
6.DXGI_FORMAT_R8G8B8A8_SINT:每个元素由4个8位有符号整数分量构成,每个分量都被映射到 [−128, 127] 区间。
7.DXGI_FORMAT_R8G8B8A8_UINT:每个元素由4个8位无符号整数分量构成,每个分量都被映射到 [0, 255] 区间。
2.交换链和页面翻转
-
后台缓冲区:也叫离屏纹理,将画面先绘制到后台缓冲区可防止画面闪烁。存储的是下一帧的数据。
-
前台缓冲区:存储的是当前显示在屏幕上的图像数据。
当后台缓冲区中的数据绘制完成之后,两种缓冲区的角色互换,后台缓冲区变为前台缓冲区呈现新一帧的画面,而前台缓冲区则为了显示下一帧数据,转为后台缓冲区。前后台缓冲的这种互换操作称为呈现。
- 交换链
前台缓冲区和后台缓冲区构成了交换链。在Direct3D中用IDXGISwapChain接口来表示。个接口不仅存储了前台缓冲区和后台缓冲区两种纹理,而且还提供了修改缓冲区大小(IDXGISwapChain::ResizeBuffers)和呈现缓冲区内容(IDXGISwapChain::Present)的方法。
3.深度缓冲
深度缓冲区(depth buffer)这种纹理资源存储的并非图像数据,而是特定像素的深度信息。深度值的范围为0.0~1.0。深度缓冲区中的元素与后台缓冲区内的像素呈一一对应关系(即后台缓冲区中第[插图]行第[插图]列的元素对应于深度缓冲区内第[插图]行第[插图]列的元素)。所以,如果后台缓冲区的分辨率为[插图],那么深度缓冲区中就应当有[插图]个深度元素。
深度缓冲区也是一种纹理,所以一定要用明确的数据格式来创建它。深度缓冲可用的格式包括以下几种。
1.DXGI_FORMAT_D32_FLOAT_S8X24_UINT:该格式共占用64位,取其中的32位指定一个浮点型深度缓冲区,另有8位(无符号整数)分配给模板缓冲区(stencil buffer),并将该元素映射到[0, 255]区间,剩下的24位仅用于填充对齐(padding)不作他用。
2.DXGI_FORMAT_D32_FLOAT:指定一个32位浮点型深度缓冲区。
3.DXGI_FORMAT_D24_UNORM_S8_UINT:指定一个无符号24位深度缓冲区,并将该元素映射到[0, 1]区间。另有8位(无符号整型)分配给模板缓冲区,将此元素映射到[0, 255]区间。
4.DXGI_FORMAT_D16_UNORM:指定一个无符号16位深度缓冲区,把该元素映射到[0, 1]区间。
一个应用程序不一定要用到模板缓冲区。但一经使用,则深度缓冲区将总是与模板缓冲区如影随形,共同进退。
4.资源与描述符
问题:数据如何从CPU到GPU的?
-
资源:GPU渲染所需要的数据。
-
描述符:描述符可以视为一种对送往GPU的资源进行描述的轻量级结构。
GPU渲染时需要将渲染所需的资源绑定到渲染流水线上,而资源是通过描述符绑定到渲染流水线上的。
为什么我们要额外使用描述符这个中间层呢?
究其原因,GPU资源实质都是一些普通的内存块。由于资源的这种通用性,它们便能被设置到渲染流水线的不同阶段供其使用。一个常见的例子是先把纹理用作渲染目标(即Direct3D的绘制到纹理技术),随后再将该纹理作为一个着色器资源(即此纹理会经采样而用作着色器的输入数据)。不管是充当渲染目标、深度/模板缓冲区还是着色器资源等角色,仅靠资源本身是无法体现出来的。而且,我们有时也许只希望将资源中的部分数据绑定至渲染流水线,但如何从整个资源中将它们选取出来呢?再者,创建一个资源可能用的是无类型格式,这样的话,GPU甚至不会知道这个资源的具体格式。
**总结:**描述符就是用来描述资源的用途、大小等信息,告诉GPU如何使用资源。
**注意:**视图(view)与描述符(descriptor)是同义词。“视图”虽是Direct3D先前版本里的常用术语,但它仍然沿用在Direct3D12的部分API中。
- 描述符的类型
每个描述符都有一种具体类型,此类型指明了资源的具体作用。本书常用的描述符如下。
1.CBV/SRV/UAV描述符分别表示的是常量缓冲区视图(constant buffer view)、着色器资源视图(shaderresource view)和无序访问视图(unordered access view)这3种资源。
2.采样器(sampler,亦有译为取样器)描述符表示的是采样器资源(用于纹理贴图)。
3.RTV描述符表示的是渲染目标视图资源(render targetview)。
4.DSV描述符表示的是深度/模板视图资源(depth/stencilview)。
5.描述符堆
描述符堆中存有一系列描述符(可将其看作是描述符数组),本质上是存放用户程序中某种特定类型描述符的一块内存。
我们能用多个描述符来引用同一个资源。例如,可以通过多个描述符来引用同一个资源中不同的局部数据。而且,前文曾提到过,一种资源可以绑定到渲染流水线的不同阶段。因此,对于每个阶段都需要设置独立的描述符。例如,当一个纹理需要被用作渲染目标与着色器资源时,我们就要为它分别创建两个描述符:一个RTV描述符和一个SRV描述符。类似地,如果以无类型格式创建了一个资源,又希望该纹理中的元素可以根据需求当作浮点值或整数值来使用,那么就需要为它分别创建两个描述符:一个指定为浮点格式,另一个指定为整数格式。
创建描述符的最佳时机为初始化期间。由于在此过程中需要执行一些类型的检测和验证工作,所以最好不要在运行时(runtime)才创建描述符。