从0开始学Direct X12
回忆了一下自己学计算机的动机,果然还是想做游戏。写引擎看起来也够有挑战性够有意思。
游戏引擎离不开图形学API,现有的api我都没什么了解。
于是决定今天起开始系统学习。用作笔记,如果学习轨迹能帮助后来者,也是好的。
为什么要学习DirectX 12?
DirectX12, OpenGL, Vulkan, Metal, WebGL都是现在常用的low level图形API (Low level Graphics APIs)
其中OpenGL历史较久,API较旧,与现代GPU架构提供的接口有差距,比如它使用了一个全局的状态机(single global state machine)来表示状态。DirectX 12相比OpenGL更接近现代GPU架构。而且DirectX12、Vulkan和Metal。不过目前的Android机器大部分只兼容OpenGL ES,iOS则是Metal为主
Vulkan 目前来看,细节复杂,对于我这种初学者来说学习难度可能很大,暂且搁置。
加上DX12我能找到较多的资料,加上手上的计算平台也是windows的,所以最后就选择 DX12 作为上手了。
从理性来看,图形API该学都是要学的,
入门学习计划
计划先过一遍https://github.com/microsoft/DirectX-Graphics-Samples 下的sample作为实践。
结合Frank Luna 的 Introduction to 3D Game Programming with DirectX 12 作为教材
学习进度
书前三章概括:
线性代数复习+DirectX接口科普
一些备忘:
-
XMVECTOR
是DirectX12提供的vector类型,由4个float组成,本质是__m128
类型。 -
XM_CALLCONV
是DirectX用来帮助指定编译器用什么function call convention的修饰符(例如__fastcall
和__vectorcall
)。__fastcall
在调用函数传参时,32位windows会在pass__m128
时,把前三个__m128
类型的参数给直接传给SSE/SSE2的寄存器,剩下的参数压倒栈里,64位会直接都压进栈。而__vectorcall
会把前6个__m128
参数直接传给SSE/SSE2寄存器。传参给寄存器显然比直接压栈快。- 来源:https://docs.microsoft.com/en-us/windows/win32/dxmath/pg-xnamath-internals
- 注意
XMVECTOR
作为参数时,为了性能,需要让参数类型按照一定顺序排列:- FXMVECTOR 前三个参数类型
- GXMVECTOR 第四个
- HXMVECTOR 第五个第六个
- CXMVECTOR 之后更多
- 为什么是这样安排,暂时不了解,以后再来探索吧
-
叉积(cross product)的结果一般是右手系(right hand rule)的,就是如果你想计算$a\times b$,那么拿出右手食指对准a的方向,中指对准b的方向,结果会指向大拇指。(我自己老是忘是左手还是右手,2d是顺时针还是逆时针)
-
3d向量加一个维度变成齐次坐标,相关的矩阵变换(例如scale,translate,project)要会推导。
-
值得注意的是DirectX使用row vector 来做矩阵乘法,这个似乎和OpenGL是反着的,所以如果按照column vector来写变换矩阵的话,得到的会是目标matrix的转置:
$$\left[\begin{array}{llll} x^{\prime} & y^{\prime} & z^{\prime} & w^{\prime} \end{array}\right]=\left[\begin{array}{llll} x & y & z & w \end{array}\right]\left[\begin{array}{llll} m 11 & m 12 & m 13 & m 14 \\ m 21 & m 22 & m 23 & m 24 \\ m 31 & m 32 & m 33 & m 34 \\ m 41 & m 42 & m 43 & m 44 \end{array}\right]$$
书第四章:
未完待续。。。
暂时鸽掉