原文: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. eclipse下项目复制改名注意事项

    当在Eclipse下复制Web工程时 1.需要修改复制后新工程源码文件下 .settings 文件夹下的org.eclipse.wst.common.component中的内容为本工程名,明细如图:

  2. DROOLS通过URL访问changset

    package droolsRule; import java.net.Authenticator; import java.net.PasswordAuthentication; import ka ...

  3. [编织消息框架][JAVA核心技术]数值与逻辑分离

    为什么要分离? 业务需求是不停地变,如果把条件写进代码里,当用户需求变时要改代码发版本更新才能生效,这过程无疑是漫长的 就算是在开发期,不停的变开发者精力耗光在沟通,小修改上,无法专注逻辑部分 分离的 ...

  4. 基于Skyline与ArcGIS Server的二三维联动功能实现

    基于Skyline与ArcGIS Server的二三维联动功能实现主要利用WEB技术.ArcGIS for JavaScript.Skyline 二次开发以及ArcGIS 10.1 桌面工具. 利用A ...

  5. Java程序员面试题收集(6)

    <!————————————————————————————基础题122道,代码题19道————————————————————————————> JAVA相关基础知识1.面向对象的特征有 ...

  6. 使用powerDesigner绘制类图

    使用powerDesigner绘制类图 因为后面要理清楚spring中类与类之间关系,我们来看看如何使用powerDesigner绘制类图 你要去下载powerDesiger,一路下一步安装好 打开, ...

  7. 字符串匹配算法之kmp算法

    kmp算法是一种效率非常高的字符串匹配算法,是由Knuth,Morris,Pratt共同提出的模式匹配算法,所以简称KMP算法 算法思想 在一个字符串中查找另一个字符串时,会遇到如下图的情况 我们通常 ...

  8. 2016年省赛 G Triple Nim

    2016年省赛 G Triple Nimnim游戏,要求开始局面为先手必败,也就是异或和为0.如果n为奇数,二进制下最后一位只有两种可能1,1,1和1,0,0,显然异或和为1,所以方案数为0如果n为偶 ...

  9. Redis源码解析:17Resis主从复制之主节点的部分重同步流程及其他

    本文主要讲解主节点部分重同步的实现,以及主从复制中的其他功能.本文是Redis主从复制机制的最后一篇文章. 主节点在收到从节点发来的PSYNC命令之前,主节点的部分重同步流程,与完全重同步流程是一样的 ...

  10. MySQL系列(八)--数据库分库分表

    在互联网公司或者一些并发量比较大的项目,虽然有各种项目架构设计.NoSQL.MQ.ES等解决比较高的并发访问,但是对于数据库来说,压力 还是太大,这时候即使数据库架构.表结构.索引等都设计的很好了,但 ...