创建渲染目标视图
资源不能被直接绑定到一个管线阶段,所以我们必须为资源创建资源视图,然后把资源视图绑定到不同的管线阶段。尤其是在把后台缓冲区绑定到管线的输出合并器阶段时(使Direct3D可以在后台缓冲区上执行渲染工作),我们必须为后台缓冲区创建一个渲染目标视图(render target view)。
代码:
ID3D11RenderTargetView *mRenderTargetView;
ID3D11Texture2D *backBuffer;
mSwapChain->GetBuffer(0,__uuidof(ID3D11Texture2D),reinterpret_cast<void**>(&backBuffer));
md3dDevice->CreateRenderTargetView(backBuffer,0,&mRenderTargetView);
ReleaseCOM(backBuffer);
说明:
1.IDXGISwapChain::GetBuffer方法用于获取一个交换链的后台缓冲区指针。该方法的第一个参数表示所要获取的后台缓冲区的索引值(由于后台缓冲区的数量可以大于1,所以这里必须指定索引值)。在我们的演示程序中,我们只使用一个后台缓冲区,所以该索引值设为0。第二个参数是缓冲区的接口类型,它通常是一个2D纹理(ID3D11Texture2D)。第三个参数返回指向后台缓冲区的指针。
2.我们使用ID3D11Device::CreateRenderTargetView方法创建渲染目标视图。第一个参数指定了将要作为渲染目标的资源,在上面的例子中,渲染目标是后台缓冲区(即,我们为后台缓冲区创建了一个渲染第目标视图)。二个参数是一个指向D3D11_RENDER_TARGET_VIEW_DESC结构体的指针,该结构体描述了资源中的元素的数据类型。如果在创建资源时使用的是某种强类型格式(即,非弱类型格式),则该参数可以为空,表示以资源的第一个mipmap层次(后台缓冲区也只有一个mipmap层次)作为视图格式。第三个参数通过指针返回了创建后的渲染目标视图对象。
3.每调用一次IDXGISwapChain::GetBuffer方法,后台缓冲区的COM引用计数就会向上递增一次,这便是我们在代码片段的结尾处释放它(ReleaseCOM)的原因。
创建深度缓冲区及其视图
我们现在需要创建深度/模板缓冲区。深度缓冲区只是一个存储深度信息的2D纹理(如果使用模板,则模板信息也在该缓冲区中)。要创建纹理,我们必须填充一个D3D11_TEXTURE2D_DESC结构体来描述所要创建的纹理,然后再调用ID3D11Device::CreateTexture2D方法。该结构体的定义如下:
typedef struct D3D11_TEXTURE2D_DESC {
UINT Width;
UINT Height;
UINT MipLevels;
UINT ArraySize;
DXGI_FORMAT Format;
DXGI_SAMPLE_DESC SampleDesc;
D3D10_USAGE Usage;
UINT BindFlags;
UINT CPUAccessFlags;
UINT MiscFlags;
}D3D11_TEXTURE2D_DESC;
说明:
1.Width:纹理的宽度,单位为纹理元素(texel)。
2.Height:纹理的高度,单位为纹理元素(texel)。
3.MipLevels:多级渐近纹理层(mipmaplevel)的数量。多级渐近纹理将在后面的章节“纹理”中进行讲解。对于深度/模板缓冲区来说,我们的纹理只需要一个多级渐近纹理层。
4.ArraySize:在纹理数组中的纹理数量。对于深度/模板缓冲区来说,我们只需要一个纹理。
5.Format:一个DXGI_FORMAT枚举类型成员,它指定了纹理元素的格式。对于深度/模板缓冲区来说,它必须是4.1.5节列出的格式之一。
6.SampleDesc:多重采样数量和质量级别。
7.Usage:表示纹理用途的D3D11_USAGE枚举类型成员。有4个可选值:
D3D11_USAGE_DEFAULT 表示GPU(graphicsprocessingunit,图形处理器)会对资源执行读写操作。CPU不能读写这种资源。对于深度/模板缓冲区,我们使用D3D11_USAGE_DEFAULT标志值,因为GPU会执行所有读写深度/模板缓冲区的操作。
D3D10_USAGE_IMMUTABLE 表示在创建资源后,资源中的内容不会改变。这样可以获得一些内部优化,因为GPU会以只读方式访问这种资源。除了在创建资源时CPU会写入初始化数据外,其他任何时候CPU都不会对这种资源执行任何读写操作。
D3D10_USAGE_DYNAMIC 表示应用程序(CPU)会频繁更新资源中的数据内容(例如,每帧更新一次)。GPU可以从这种资源中读取数据,而CPU可以向这种资源中写入数据。
D3D10_USAGE_STAGING 表示应用程序(CPU)会读取该资源的一个副本(即,该资源支持从显存到系统内存的数据复制操作)。
8.BindFlags:指定该资源将会绑定到管线的哪个阶段。对于深度/模板缓冲区,该参数应设为D3D11_BIND_DEPTH_STENCIL。其他可用于纹理的绑定标志值还有:
D3D11_BIND_RENDER_TARGET:将纹理作为一个渲染目标绑定到管线上。 D3D11_BIND_SHADER_RESOURCE:将纹理作为一个着色器资源绑定到管线上。
9.CPUAccessFlags:指定CPU对资源的访问权限。如果CPU需要向资源写入数据,则应指定D3D11_CPU_ACCESS_WRITE。具有写访问权限的资源的Usage参数应设为D3D11_USAGE_DYNAMIC或D3D11_USAGE_STAGING。如果CPU需要从资源读取数据,则应指定D3D11_CPU_ACCESS_READ。具有读访问权限的资源的Usage参数应设为D3D11_USAGE_STAGING。对于深度/模板缓冲区来说,只有GPU会执行读写操作;所以,我们将该参数设为0,因为CPU不会在深度/模板缓冲区上执行读写操作。
10.MiscFlags:可选的标志值,与深度/模板缓冲区无关,所以设为0。
11.注意:推荐避免使用D3D11_USAGE_DYNAMIC和D3D11_USAGE_STAGING,因为有性能损失。
将视图绑定到输出合并器阶段
md3dImmediateContext->OMSetRenderTargets(1,&mRenderTargetView,mDepthStencilView);
说明:
第一个参数是我们将要绑定的渲染目标的数量;我们在这里仅绑定了一个渲染目标,不过该参数可以为着色器同时绑定多个渲染目标(是一项高级技术)。
第二个参数是我们将要绑定的渲染目标视图数组中的第一个元素的指针。
第三个参数是将要绑定到管线的深度/模板视图。
此外还可以设置视口,即有时我们只希望把3D场景渲染到后台缓冲区的一个子矩形区域中。如下图: