教程地址
Tutorial 3: Initializing DirectX 11
学习记录
在之前的文章中,我们简单的将我们的框架下的 CInput
填充了以下,实现了 CKeyboard
和 CMouse
两个基础类。输入貌似就可以暂时这样了,现在我们来看输出。也就是我们 CSystem
类下的另一个 CGraphics
。这篇文章中要实现的是对于 D3D 系统函数的封装,将其命名为 CDirect3D
。
更新 CDirect3D
之后我们的框架如下:
之前我们实现了很多个类,但是都算是很简单的。而这一篇就比较复杂了,我们之前写过 dx 的初始化代码,也是大致清楚都需要做什么,先来看看这个类的声明。
1 | class CDirect3D { |
嗯,看着确实很绝望了,这个类包括了大量的变量定义与函数声明。不过这里边的大部分的变量我们都见过(IDXGISWapChain
,ID3D11Device
等等),剩下的几个例如深度模板的变量我们在 OpenGL 中也是见过的(如果你没有学过,请忽略这个或者翻一下 OpenGL 的学习笔记)。
那么来看看这个类的实现吧,首先在构造函数里我们初始化这几个指针变量为空。
1 | CDirect3D::CDirect3D() { |
现在来看看我们的 Initialize()
函数,这将是我们这个类中最重要的函数。
The screenWidth and screenHeight variables that are given to this function are the width and height of the window we created in the SystemClass.
Direct3D will use these to initialize and use the same window dimensions.
The hwnd variable is a handle to the window. Direct3D will need this handle to access the window previously created.
The fullscreen variable is whether we are running in windowed mode or fullscreen. Direct3D needs this as well for creating the window with the correct settings.
The screenDepth and screenNear variables are the depth settings for our 3D environment that will be rendered in the window.
The vsync variable indicates if we want Direct3D to render according to the users monitor refresh rate or to just go as fast as possible. ——(教程原文中对于 initialize 方法的参数的描述)
在 Initialize()
中,我们首先声明了初始化我们成员变量所需要的一些东西。在我们初始化 D3D 之前,我们从显卡 / 显示器上获得刷新率,这样我们可以根据不同的计算机屏幕刷新率不同实现自适应。
1 | IDXGIFactory* factory; |
可以看到我们调用了两次 GetDisplayModeList
,第一次为 numModes
赋值,之后我们有了显示模式的个数之后可以创建数组,之后才会将数组也传入进去用来保存显示模式列表。最后,我们遍历数组并且匹配我们所传入进来的 width
和 height
。最终得到合适的 numerator
和 denominator
值,用于我们最后在创建交换链的时候赋值。
1 | // Get the adapter (video card) description. |
做完这些后,我们再来获得显卡的内存,保存在 mVideoCardMemory_
里。当我们得到了这些数据后,就可以开始创建交换链那些东西了(我们之前做过的)。
先释放掉刚才为了获得显卡显示器数据创建的指针对象。
1 | // Release the display mode list. |
之后,初始化交换链描述:
1 | DXGI_SWAP_CHAIN_DESC swapChainDesc; |
初始化完了之后就可以直接创建了,然后是创建 RenderTargetView
这些。
1 | // Set the feature level to DirectX 11. |
现在我们来创建深度缓冲描述,用它来创建深度缓冲,并且附加一个深度模板。
1 | // Initialize the description of the depth buffer. |
完成这个,我们来创建一个 Raster :
1 | rasterDesc.AntialiasedLineEnable = false; |
Now that the render targets are setup we can continue on to some extra functions that will give us more control over our scenes for future tutorials.
First thing is we’ll create is a rasterizer state. This will give us control over how polygons are rendered.
We can do things like make our scenes render in wireframe mode or have DirectX draw both the front and back faces of polygons.
By default DirectX already has a rasterizer state set up and working the exact same as the one below but you have no control to change it unless you set up one yourself.
我们自定义光栅化可以使得我们实现更多的效果。
最后,创建 ViewPort
以及初始化那几个矩阵(可以看到我们并没有 ViewMatrix
,这个准备封装在摄像机类里 CCamera
)。
1 | // Setup the viewport for rendering. |
终于,我们的初始化方法结束了(好长),可以看到是非常麻烦的。幸好我们实际编程中是不会去专注于这里。
解决了初始化,剩下的就简单的多了。Shutdown
方法中我们将 delete
掉成员变量指针。
1 | void CDirect3D::Shutdown() { |
在 BeginScene
和 EndScene
中我们实现缓冲清空(颜色和深度)和交换。
1 | void CDirect3D::BeginScene(const float r, const float g, const float b , const float a) const { |
剩下的方法则是简单的赋值了:
1 | ID3D11Device* CDirect3D::GetDevice() const { |
终于,我们实现了 CDirect3D
类。现在来修改 CSystem
使得它调用 CDirect3D
。比如初始化或者删除,还有在 Render()
方法的修改:
1 | bool CGraphics::Initialize(const int screenWidth, const int screenHeight, const HWND hwnd) { |
这里,我们的 Initialize
需要增加 rgba
的参数。
这一篇很长,写的时候也比较乱,之后若是有时间的话可能会进行修改。实现框架并不是我们最终的目的,在这个过程中我们介绍它的实现的过程才是最终需要学习的内容。