【DirectX】March 2018 Progress Report
手撸了第六章的5个例子(box/hills/skull/shapes/waves),顺便大致过了一遍第七章:因为光(Light)在《Unity-shader入门精要》已经看过了,而且我觉得那个说的更好(
总之先输出一点
Rendering pipeline in GPU
渲染管线大致分解为以下几个主要阶段:
[输入装配(IA)阶段]
Input Assembelr Stage
[顶点着色器(VS)阶段]
Vertex Shader Stage
[细分着色器]
Hull Shader Stage (外壳着色器阶段)
Tessellator Stage (曲面细分)
Domain Shader Stage (域着色器)
[几何着色器(GS)阶段]
Geometry Shader Stage
(Stream Output Stage)(流输出)
[裁剪阶段]
[光栅化(RS)阶段]
Rasterizer Stage
[像素着色器(PS)]
Pixel Shader Stage
[和输出合并器(OM)阶段]
Output Merger Stage
…
举例来说基本上你看到函数名字是以IA开头的,就是在进行输入装配阶段。细分着色器属于高阶阶段,目前我还木有遇到细分处理的例子。
WavesDemo
用Demo做例子,这里skull及之后的例子才用到了光栅化。最后一个例子WavesDemo由两部分组成,z=f(x, y)的山谷和波动的水面网格。
先不管update函数直接看draw
|
|
mTech是fx文件(HLSL,包含VS和PS)编译后赋值的私有ID3DX11EffectTechnique*
成员
mVB和mIB(根据对象取别名)是私有函数BuildGeometryBuffers
(根据对象取别名)的最终产物(存放顶点和索引缓冲,这是三角形带的一种表示方法)
draw函数依赖于md3dImmediateContext
这个上下文环境(和以前写WebCanvas类似),按照流程很明显的就是 IA->IA(VS/PS)->IA(GS)->IA(RS)->DrawIndexed 尽管顺序略有不同,但是基本上包含了所有阶段需要的参数。细分着色器中部分是DirectX11的新特性,目前还没有用到
接着看update部分(即mainloop),这里涉及到动画处理,如果涉及过设计模式会好理解很多,这是典型的序列型模式
update的前面部分是把球坐标转换成直角坐标,来构筑mView(最终worldViewProj = world*view*proj
,记得这个公式),中后部分用于处理水面动画,Waves对象使用了设计模式中更新方法,设计一个update的方法,把mainloop中的deltatime作为参数传入子部件的update中,以保持同步的时间步长,后面的一个for主要是将waves同步的数据更新到mVB中,先来看看waves的update是如何设计的:
|
|
典型的双缓冲,避免同时读写同一块内存。这里注意到三个mk参数,找到其赋值的init函数
|
|
理论上水波模型一般使用正弦函数,这里用了近似的函数组合来模拟,水波的某一点取决于上一帧的状态和周围四格的状态。
将 speed=3.25, damping=0.4, dx=0.8 带入得:
mK1 = ( 0.4 * dt - 2.0 ) / ( 0.4 * dt + 2.0 )
mK2 = ( 4.0 - 132.0 * dt * dt ) / ( 0.4 * dt + 2.0 )
研究了一会之后,我只能说这是经验公式,这样只有前两个水波比较明显(由函数图像可得)