原文:DirectX11笔记(三)--Direct3D初始化2

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010333737/article/details/78447294


  本篇文章将对初始化Direct3D的各个步骤进行详细的讲解, 在文章中只会引用必要的代码, 在文章最后会附带一个完整的代码链接, 希望学习D3D的你能在浏览完本篇内容之后参考示例代码, 构建好自己D3D程序的基础.


一 总览: 初始化Direct3D的步骤

  1. 创建ID3D11Device和ID3D11DeviceContext接口
  2. 检查所支持的4X MSAA的质量等级
  3. 描述交换链的特征
  4. 创建交换链
  5. 创建render target视图
  6. 创建一个深度模板缓冲和视图
  7. 绑定视图到渲染管线
  8. 设置视口( viewport )

二 创建设备( ID3D11Device )和上下文( ID3D11DeviceContext )

  这是初始化Direct3D的第一步, 所谓的设备和上下文实际是ID3D11DeviceID3D11DeviceContext这两个接口, 它们在D3D的接口中处于领导地位, 是显卡在软件层面的控制器.

  ID3D11Device : 检查支持的特性, 分配资源等

  ID3D11DeviceContext : 设置渲染状态, 绑定资源到图形管线, 发送渲染指令等

// 创建设备和上下文
/**
* pAdapter: 显示适配器, 为空时使用主显示适配器
* DriverType: 一般情况下都应该使用D3D_DRIVER_TYPE_HARDWARE
* Software: 因为上一个参数表明我们使用硬件, 这个参数一般都应该为null
* Flags: D3D11_CREATE_DEVICE_DEBUG用于调试, D3D11_CREATE_DEVICE_SINGLETHREADED如果能保证只有单线程这会提升效率, 但是多线程操作便会失败
* pFeatureLevels: 特征等级数组
* FeatureLevels: 特征等级的数量
* SDKVersion: D3D11_SDK_VERSION
* ppDevice: 返回的设备指针
* pFeatureLevel: 返回的第一个支持的特征等级
* ppImmediateContext: 返回的立即的上下文指针
*/
HRESULT D3D11CreateDevice(
IDXGIAdapter *pAdapter,
D3D_DRIVER_TYPE DriverType,
HMODULE Software,
UINT Flags,
CONST D3D_FEATURE_LEVEL *pFeatureLevels,
UINT FeatureLevels,
UINT SDKVersion,
ID3D11Device **ppDevice,
D3D_FEATURE_LEVEL *pFeatureLevel,
ID3D11DeviceContext **ppImmediateContext
);

  这是创建设备和上下文的一种方法, 但是在例子中我会使用另外一个接口D3D11CreateDeviceAndSwapChain, 在创建设备和上下文的同时创建交换链, 这个接口的参数和上文说明的基本一致, 只不过多出了交换链的部分.


三 检查所支持的4倍MSAA质量等级

  创建设备之后我们可以检查他支持的4倍MSAA质量等级, 所有的D3D设备都会支持所有格式的4倍MSAA, 所以检查出的质量等级始终应该大于0.

  ( 例子中并没有使用MSAA )

UINT m4xMsaaQuality;
HR(md3dDevice->CheckMultisampleQualityLevels(
DXGI_FORMAT_R8G8B8A8_UNORM, 4, & m4xMsaaQuality));
assert(m4xMsaaQuality > 0 );

四 交换链

描述交换链

  为了创建交换链, 我们先要创建一个交换链描述. 我们使用一个名为DXGI_SWAP_CHAIN_DESC的结构的实例来描述交换链.

/**
* BufferDesc: 描述back buffer
* 描述back buffer: MSAA的采样数
* BufferUsage: 一般为DXGI_USAGE_RENDER_TARGET_OUTPUT
* BufferCount: back buffer的数量
* OutputWindow: 渲染窗口的句柄
* Windowed: true: 窗口模式, false: 全屏模式
* SwapEffect: 一般为DXGI_SWAP_EFFECT_DISCARD, 让硬件使用最高效的方法.
*/
typedef struct DXGI_SWAP_CHAIN_DESC {
DXGI_MODE_DESC BufferDesc;
DXGI_SAMPLE_DESC SampleDesc;
DXGI_USAGE BufferUsage;
UINT BufferCount;
HWND OutputWindow;
BOOL Windowed;
DXGI_SWAP_EFFECT SwapEffect;
UINT Flags;
} DXGI_SWAP_CHAIN_DESC; // 之前的 DXGI_MODE_DESC 声明如下
typedef struct DXGI_MODE_DESC
{
UINT Width;
UINT Height;
DXGI_RATIONAL RefreshRate;
DXGI_FORMAT Format; // back buffer像素格式
DXGI_MODE_SCANLINE_ORDER ScanlineOrdering;
DXGI_MODE_SCALING Scaling;
} DXGI_MODE_DESC;

  例子中我们一般只会使用基础的, 常用的, 公用的属性值, 最具体的细节还是需要查阅文档.

创建交换链

  一个交换链的接口IDXGISwapChain 需要通过一个IDXGIFactory实例的CreateSwapChain方法创建.

/**
* pDevice: ID3D11Device 指针
* pDesc: DXGI_SWAP_CHAIN_DESC 指针
* ppSwapChain: 返回的交换链指针
*/
HRESULT IDXGIFactory::CreateSwapChain(
IUnknown *pDevice,
DXGI_SWAP_CHAIN_DESC *pDesc,
IDXGISwapChain **ppSwapChain
);

五 同时创建设备, 上下文和交换链

  之前所说的创建交换链的方法有些麻烦, 需要额外使用一些DXGI的东西, 由于我们的例子中并不使用 MSAA , 所以在这里我使用D3D11CreateDeviceAndSwapChain一同创建设备, 上下文, 交换链. 这个接口相当于上面所说的两个接口的整合, 具体的参数可以去文档查找.

六 创建Render Target视图

  在前一篇文章里我们提到过, D3D不会直接将资源绑定到渲染管线的某个阶段, 而是创建一个资源视图并将这个视图与渲染管线绑定. 为了将back buffer和渲染管线的输出合并阶段绑定, 所以我们会创建这个Render Target视图.

ID3D11Texture2D* pBackBuffer = NULL;
hr = g_pSwapChain->GetBuffer( 0,
__uuidof( ID3D11Texture2D ),
( LPVOID* )&pBackBuffer
);
hr = g_pd3dDevice->CreateRenderTargetView(
pBackBuffer, NULL,
&g_pRenderTargetView
);
pBackBuffer->Release();

  通过上面的方法我们会创建出RenderTargetView. 可以看出, 其实我们所说的back buffer就是一张2D纹理. 利用我们之前创建的交换链可以获取到这张纹理, 然后就可以让g_pd3dDevice使用它创建Render Target视图.


七 创建深度模板缓冲和视图

创建深度模板缓冲

  深度模板缓冲之前也已经有过说明, 他是也一张2D纹理, 存储着深度信息. 为了创建这张纹理, 我们首先需要有一个2D纹理的描述D3D11_TEXTURE2D_DESC.

/**
* BindFlags: 表明纹理资源被绑定到渲染管线的什么阶段, 对于深度模板缓冲, 应该是D3D11_BIND_DEPTH_STENCIL
* CPUAccessFlags: 表明CPU将如何访问资源, 但是深度模板缓冲只有GPU会进行读写, 所以这里可以填0
* MiscFlags: 对深度模板缓冲没有影响, 所以也填0
*/
typedef struct D3D11_TEXTURE2D_DESC {
UINT Width;
UINT Height;
UINT MipLevels;
UINT ArraySize;
DXGI_FORMAT Format;
DXGI_SAMPLE_DESC SampleDesc;
D3D11_USAGE Usage;
UINT BindFlags;
UINT CPUAccessFlags;
UINT MiscFlags;
} D3D11_TEXTURE2D_DESC; g_pd3dDevice->CreateTexture2D(
&descDepth, NULL,
&g_pDepthStencil
);

  创建好描述之后, 我们便可以使用这个描述利用CreateTexture2D接口创建纹理, 这个纹理就是深度模板缓冲.

创建深度模板视图

  创建方法和创建RenderTargetView相似, 这里使用CreateDepthStencilView创建深度模板视图. 深度模板视图也有对应的描述D3D11_DEPTH_STENCIL_VIEW_DESC来说明视图信息, 详细信息可以文档查阅, 这里不再多做说明.

D3D11_DEPTH_STENCIL_VIEW_DESC descDSV;
ZeroMemory(&descDSV, sizeof(descDSV));
descDSV.Format = descDepth.Format;
descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
descDSV.Texture2D.MipSlice = 0;
hr = g_pd3dDevice->CreateDepthStencilView(
g_pDepthStencil,
&descDSV,
&g_pDepthStencilView
);

八 绑定视图到渲染管线

  我们创建的视图就是为了让他们成为渲染管线的渲染目标和深度模板缓冲. 经过这步绑定, 我们就可以实现这一需求: 将两个视图绑定到渲染管线的输出合并阶段, 使渲染管线可以使用相应资源.

g_pImmediateContext->OMSetRenderTargets(
1, &g_pRenderTargetView,
g_pDepthStencilView
);

  第一个参数是RenderTargetView的数目, 我们只使用一个, 但是D3D本身支持多个. 第二个参数之所以要加”&”是因为他表示的其实是RenderTargetView数组的第一个元素( 可以支持多个嘛~ ), 第三参数就是深度模板视图.


九 设置视口( Viewport )

  我们一般都会把场景画到整个back buffer中, 但是我们也不能排除需要将场景画到back buffer一部分的可能性. 这个”back buffer的一部分“便是所谓的视口Viewport.

  我们使用一个结构体D3D11_VIEWPORT来说明视口的信息.

typedef struct D3D11_VIEWPORT {
FLOAT TopLeftX;
FLOAT TopLeftY;
FLOAT Width;
FLOAT Height;
FLOAT MinDepth;
FLOAT MaxDepth;
} D3D11_VIEWPORT;

  这里需要注意的是 D3D 的深度缓冲的取值范围是[0, 1], MinDepth和MaxDepth在没有特别需求的时候应该设置为这些值.

  最后我们会通过ID3D11DeviceContextRSSetViewports 方法设置视口.


示例代码

DirectX11笔记(三)--Direct3D初始化2的更多相关文章

  1. DirectX11笔记(三)--Direct3D初始化代码

    原文:DirectX11笔记(三)--Direct3D初始化代码 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u010333737/article ...

  2. DirectX11笔记(二)--Direct3D初始化1之基本概念

    原文:DirectX11笔记(二)--Direct3D初始化1之基本概念 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u010333737/art ...

  3. DirectX11笔记(十一)--Direct3D渲染7--RENDER STATES

    原文:DirectX11笔记(十一)--Direct3D渲染7--RENDER STATES 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u010 ...

  4. DirectX11笔记(六)--Direct3D渲染2--VERTEX BUFFER

    原文:DirectX11笔记(六)--Direct3D渲染2--VERTEX BUFFER 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u0103 ...

  5. DirectX11笔记(七)--Direct3D渲染3--INDICES AND INDEX BUFFERS

    原文:DirectX11笔记(七)--Direct3D渲染3--INDICES AND INDEX BUFFERS 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.cs ...

  6. DirectX11笔记(五)--Direct3D渲染1--VERTICES AND INPUT LAYOUTS

    原文:DirectX11笔记(五)--Direct3D渲染1--VERTICES AND INPUT LAYOUTS 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.c ...

  7. DirectX11笔记(十)--Direct3D渲染6--PIXEL SHADER

    原文:DirectX11笔记(十)--Direct3D渲染6--PIXEL SHADER 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u01033 ...

  8. DirectX11笔记(九)--Direct3D渲染5--CONSTANT BUFFERS

    原文:DirectX11笔记(九)--Direct3D渲染5--CONSTANT BUFFERS 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u0 ...

  9. DirectX11笔记(八)--Direct3D渲染4--VERTEX SHADER

    原文:DirectX11笔记(八)--Direct3D渲染4--VERTEX SHADER 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u0103 ...

随机推荐

  1. 路飞学城-Python爬虫集训-第三章

    这个爬虫集训课第三章的作业讲得是Scrapy 课程主要是使用Scrapy + Redis实现分布式爬虫 惯例贴一下作业: Python爬虫可以使用Requests库来进行简单爬虫的编写,但是Reque ...

  2. NFS和mount常用参数详解 本文目录

    NFS和mount常用参数详解   本文目录 NFS权限参数配置 mount挂载参数 原始驱动程序的挂载选项. 新驱动程序的挂载选项. 怎样改变已经挂载的NTFS卷的权限? 怎样自动挂载一个NTFS卷 ...

  3. 跟我一起安装vmware

    第一步查看我们的电脑配置 我是windows10,下面的方法是windows10来安装vmware 第二步双击下图文件 (1) 2)弹出如下图,点击下一步即可. (3)一直点击下一步(期间会同意,勾选 ...

  4. Android 开发 AudioRecord音频录制

    前言 Android SDK 提供了两套音频采集的API,分别是:MediaRecorder 和 AudioRecord,前者是一个更加上层一点的API,它可以直接把手机麦克风录入的音频数据进行编码压 ...

  5. Apache SOLR and Carrot2集成

    1.环境 下载软件 名称 地址 solr-integration-strategies-gh-pages.zip https://github.com/carrot2/solr-integration ...

  6. Flannel部署

    目录 Flannel CNI集成 配置Docker使用Flannel 1.为Flannel生成证书 [root@linux-node1 ~]# cd /usr/local/src/ssl/ [root ...

  7. Django中间件分析

    SessionMiddleware 浏览器会发送包含SESSION_COOKIE_NAME的的Cookie 中间件从django_session中按照SESSION_COOKIE_NAME取出存入的s ...

  8. Laravel 错误处理

    错误提示:cURL error 60: SSL certificate problem: unable to get local issuer certificate 解决方案:修改文件,重启队列即可 ...

  9. Web交互增强

    刚刚google了一下这个概念,在其他的领域已经存在了这个概念,但是web方面还是没有被人提及的,所以我在这里第一次声明web方面的交互增强 交互增强 (interaction enhance) 相对 ...

  10. Java 如何在线打开编辑word文档?

    在一般的OA项目中经常会遇到在线处理Office文档的需求,先下载文件,编辑保存后再选择文件上传的方式太过原始,在如今早已是Office Online的时代,没有用户能接受这种蹩脚的操作方式. 虽然微 ...