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

本文详细讲解了初始化Direct3D的步骤,包括创建设备和上下文、检查4倍MSAA质量等级、创建交换链、Render Target视图、深度模板缓冲和视图,以及绑定视图到渲染管线、设置视口等,最后还附带了完整代码链接。
原文: DirectX11笔记(三)--Direct3D初始化2

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.youkuaiyun.com/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 方法设置视口.


示例代码

posted on 2019-05-07 14:24 NET未来之路 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/lonelyxmas/p/10825204.html

内容概要:本文系统介绍了算术优化算法(AOA)的基本原理、核心思想及Python实现方法,并通过图像分割的实际案例展示了其应用价值。AOA是一种基于种群的元启发式算法,其核心思想来源于四则运算,利用乘除运算进行全局勘探,加减运算进行局部开发,通过数学优化器加速函数(MOA)和数学优化概率(MOP)动态控制搜索过程,在全局探索与局部开发之间实现平衡。文章详细解析了算法的初始化、勘探与开发阶段的更新策略,并提供了完整的Python代码实现,结合Rastrigin函数进行测试验证。进一步地,以Flask框架搭建前后端分离系统,将AOA应用于图像分割任务,展示了其在实际工程中的可行性与高效性。最后,通过收敛速度、寻优精度等指标评估算法性能,并提出自适应参数调整、模型优化和并行计算等改进策略。; 适合人群:具备一定Python编程基础和优化算法基础知识的高校学生、科研人员及工程技术人员,尤其适合从事人工智能、图像处理、智能优化等领域的从业者;; 使用场景及目标:①理解元启发式算法的设计思想与实现机制;②掌握AOA在函数优化、图像分割等实际问题中的建模与求解方法;③学习如何将优化算法集成到Web系统中实现工程化应用;④为算法性能评估与改进提供实践参考; 阅读建议:建议读者结合代码逐行调试,深入理解算法流程中MOA与MOP的作用机制,尝试在不同测试函数上运行算法以观察性能差异,并可进一步扩展图像分割模块,引入更复杂的预处理或后处理技术以提升分割效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值