原文: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. css3之文本text-overflow 与 word-wrap, word-break

    CSS3 Text Overflow属性 CSS3文本溢出属性指定应向用户如何显示溢出内容 语法: text-overflow:clip | ellipsis 但是text-overflow只是用来说 ...

  2. reac-native + typescript 的环境搭建

    一. RN-TS环境搭建 . 安装RN脚手架 yarn add create-react-native-app -g yarn global add typescript . 创建项目文件夹 crea ...

  3. DOS批处理脚本

    先概述一下批处理是个什么东东.批处理的定义,至今我也没能给出一个合适的----众多高手们也都没给出----反正我不知道----看了我也不一定信服----我是个菜鸟,当然就更不用说了:但我想总结出一个“ ...

  4. hiveUDF的使用

    在此自己总结下UDF的用法 1.首先最简单的UDF(普通用java扩充函数的方式,大多数简便函数可以用这个函数来实现,返回单个字段),其加强版UDGF据说对map一类数据类型有更好兼容,实现上略复杂 ...

  5. C++中如何实现像Java中接口功能--C++抽象类(纯虚函数,虚函数)

    在Java中定义个接口,之后可以定义不同的类来实现接口,如果有个函数的参数为这个接口的话,就可以对各自的类做出不同的响应. 如: interface animal { public void info ...

  6. shell下时间日期的加减乘除运算

    首先我们先来说说什么是shell下的时间戳: 自1970年1月1日(00:00:00 UTC/GMT)以来的秒数.它也被称为Unix时间戳(Unix Timestam.Unix epoch.POSIX ...

  7. fcc筆記

    在 JavaScript 中所有的变量都是大小写敏感的JavaScript提供七种不同的data types(数据类型),它们是undefined(未定义), null(空), boolean(布尔型 ...

  8. JavaSE_06_Collection、泛型

    1.Collection集合 1.1 集合概述 数组的长度是固定的.集合的长度是可变的. 数组中存储的是同一类型的元素,可以存储基本数据类型值.集合存储的都是对象.而且对象的类型可以不一致.在开发中一 ...

  9. ES5-ES8 数组拥有的方法

    1.判断是否是数组 Array.isArray( arg ) 有兼容性 2.toString 数组转字符串 arr.toString(); 3.join 数组每一项间的拼接 arr.join(); S ...

  10. Delphi 设计模式:《HeadFirst设计模式》Delphi7代码---观察者模式之WeatherReport[转]

      1   2{<HeadFirst设计模式>之观察者模式 }   3{ 主题与观察者                    }   4{ 编译工具 :Delphi7.0          ...