Direct3D11学习经历分享

来源:互联网 发布:mac 10.8 iphoto 编辑:程序博客网 时间:2024/04/30 23:04

今天突然看到CSDN博客不显示网易相册的图片了,大家如果敢兴趣的话到我的网易博客阅读哈。地址:

http://politician2012.blog.163.com/blog/static/207842452201272410452665/。欢迎各位与我进一步相互学习交流,我的常用邮箱是blackbutterfly66@hotmail.com。

 

研究D3D11已经有一段时间了,现在通过以前练习过的Demo总结回顾一下自己的学习历程,一方面与大家分享我自己的学习经历,并向大家推荐一本书《Pratical Rendering & Computation with Direct3D11》,同时也可以进一步巩固以前做过的东西,欢迎在图形学上有相同爱好的朋友与我进一步相互学习交流。

首先声明,本文中的所有Demo都必须在支持DirectX11的Windows 7及更高版本的系统上才可以正确运行,并且要求主机显卡支持性能等级为11的显卡,一些老显卡可能无法运行本文中的Demo,启动这些可执行文件只会看到白色窗口。

这里给出Demo的下载地址:Bin.rar。

是一个rar压缩包,由于使用SkyDrive共享文件外链(找不到其他在博客上共享文件的方式了,有其他方法的话,望不吝赐教,呵呵),下载下来的文件的文件名可能只是一个ID值,需要大家自行命名文件名及文件格式。

InitD3D11.exe

Direct3D11学习经历分享 - 铁血政客 - 铁血政客

图(1-1),初始化D3D11
简单测试D3D11App.dll为整个Demo解决方案提供的基础框架,该框架提供封装Demo窗口创建,消息处理及输入处理,初始化Direct3D11(包括检查显卡支持,创建D3D设备,创建渲染目标视图等),初始化CEGUI(因D3D11本身不支持直接渲染文本,故使用CEGUI来渲染FPS及其他文本信息,或者为将来创建UI)等功能,所有Demo都基于该框架而不必再做这些繁琐而又相同的处理,使得Demo可专注于图形渲染本身。
TextureArray.exe
Direct3D11学习经历分享 - 铁血政客 - 铁血政客
图(2-1),纹理数组实现火焰动画
Direct3D11学习经历分享 - 铁血政客 - 铁血政客
图(2-2),火焰动画的纹理帧
练习D3D11纹理数组的使用,与纹理数组资源视图对应的HLSL对象类型为Texture2DArray,使用纹理数组可一次性将多个纹理提交到缓存让着色器进行采样,从而在需要多个纹理的情况下大大提高渲染效率。上截图(2-2)中显示图像为构成火焰动画的所有帧,一共120个256X256大小的图像。在渲染前首先将这些纹理一次性提交到管线,然后使用一个常量缓存(cbuffer)来保存当前时间值,在每帧渲染的时候更新当前时间,然后根据动画帧率计算当前应该渲染的帧(即确定纹理数组的索引),最终进行纹理采样。
VertexSkinning.exe
Direct3D11学习经历分享 - 铁血政客 - 铁血政客
图(3-1),左边为骨骼模型某一时刻的姿态,右边为骨骼模型的绑定姿态
实现顶点蒙皮(也称作硬件蒙皮)。所谓蒙皮即骨骼模型的顶点根据它绑定到的骨头(Bone)的当前变换矩阵以及权值来计算该顶点在模型当前时刻下的位置及法线向量,鉴于许多图形学的初学者对骨骼模型和骨骼动画一头雾水,我们来简单阐述一下这两个概念,美工在使用3D Packet来创建每个骨骼模型时,都会先建立一个绑定姿态(Binding Pose),绑定姿态确定了整个模型的骨架(Skeleton)的所有骨头的初始几何变换矩阵Bi,同时确定模型所有顶点所绑定到的骨头,以及它们所绑定到的每一根骨头的权值,这个时候还会确定每个顶点的初始位置坐标Pi,因为模型的顶点是相对于其绑定的骨头进行平移或旋转的,因此不少人认为这个Pi是在骨头的局部空间(Local Space)中的,但其实这是很严重的错误理解,首先,每个顶点都有可能绑定到多根骨头,那么如果Pi是位于骨头的局部空间中的,那么它应该是哪根骨头的局部空间呢?因此顶点的Pi实际是位于整个模型的局部空间,那么顶点是如何跟随骨头做相对运动呢?答案就在绑定姿态本身,我们举个例子来探讨这个问题,假设一个顶点A的初始位置坐标为P0,它同时绑定到三根骨头分别为K1、K2、K3,它们的初始变换矩阵分别为B1、B2、B3,A在这个三根骨头上的绑定权值分别为w1、w2、w3,假设存在三个顶点坐标P1、P2、P3,分别位于K1、K2、K3的局部空间,且有如下关系:(下面的等式使用行向量乘方阵的约定,这也是D3D的计算约定)

P1 * B1 = P0;

P2 * B2 = P0;

P3 * B3 = P0;

W1 + w2 + w3 = 1.0;

所以有:P1 * B1 * w1 + P2 * B2 * w2 + P3 * B3 * w3 = P0;

再令B4、B5、B6分别为B1、B2、B3的逆矩阵,我们有:

P1 = P0 * B4;

P2 = P0 * B5;

P3 = P0 * B6;

我们假设在t时刻K1、K2、K3的当前变换矩阵(根据骨头相对其父母骨头(即父母节点)的相对偏移和相对旋转(一般在程序中使用四元数表示旋转)计算而来,别忘了骨架其实是一个树形结构,这个概念这里不再赘述)分别为B1t、B2t、B3t,则顶点在t时刻的位置坐标Pt为:

P1 * B1t * w1 + P2 * B2t * w2 + P3 * B3t * w3 = Pt

即:P0 * B4 * B1t * w1 + P0 * B5 * B2t * w2 + P0 * B6 * B3t * w3 = Pt

我们可以令B1f、B2f、B3f分别为t时刻K1、K2、K3的最终变换矩阵,则有:

B1f = B4 * B1t;

B2f = B5 * B2t;

B3f = B6 * B3t;

所以有:P0 * B1f * w1 + P0 * B2f * w2 + P0 * B3f * w3 = Pt

因此我们在CPU中计算出整个骨架的所有骨头的最终变换矩阵之后,将这些矩阵传送到图形管线,对于本Demo具体的说就是传送到顶点着色器的常量缓存中,然后在顶点着色器中计算模型的每个顶点的位置和法线向量。

       写到这里发现光介绍骨骼模型的概念就占据了很大篇幅呢,呵呵。限于时间关系,对于骨骼动画的概念我就不再用更多的语言来描述了,有兴趣的朋友可以看下下面的截图(3-2),对想要更深入理解骨骼动画的朋友我推荐读Ogre引擎关于骨骼动画那一块的代码,截图(3-2)正是对Ogre引擎骨骼动画相关代码的总结。
Direct3D11学习经历分享 - 铁血政客 - 铁血政客
图(3-2)骨骼动画概念图
本Demo的圆锥一共有6根骨头,使用简单的几何旋转来使得圆锥像尾巴一样摆动,程序为这个摆动动作创建了一个简单的骨骼动画。
BezierSurface.exe
Direct3D11学习经历分享 - 铁血政客 - 铁血政客
图(4-1),D3D11嵌饰麦比乌斯带
练习D3D11的新管线阶段——嵌饰系统(Tessellation System,简写为TS),TS包含三个管线阶段:Hull Shader Stage(可编程)、Tessellator Stage(固定管线阶段)、Domain Shader Stage。这三个管线阶段的内容较多,而且相对复杂,有兴趣的朋友可以参考DirectX SDK文档。该Demo实际上是DX SDK的一个例程(SimpleBezier11),只不过这里自己练习了一遍(要知道刚接触TS的时候要弄清楚这个Demo也不是件容易的事^_^),这里渲染的是贝塞尔曲面的麦比乌斯带(Mobius Strip),如果研究过NURBS(非常常用的数学建模方法,对图形学有兴趣的话推荐阅读《The Nurbs Book 2》)的话,大家可能会发现TS的功能几乎就是在实现NURBS的数学理论。
DetailTessellation.exe
Direct3D11学习经历分享 - 铁血政客 - 铁血政客
   图(5-1)
Direct3D11学习经历分享 - 铁血政客 - 铁血政客
图(5-2)
Direct3D11学习经历分享 - 铁血政客 - 铁血政客
图(5-3)
进一步练习TS。本Demo使用TS来实现动态连续层次细节(CLOD, continuous Level Of Detail),该Demo也是再次练习DX SDK的例程(DetailTessellation11)。从上面截图(5-2)和(5-3)可以看出,当摄像机离场景远的时候,使用低的嵌饰细节。
CurvedPNTriangles.exe

Direct3D11学习经历分享 - 铁血政客 - 铁血政客

图(6-1),原始三角形网格

Direct3D11学习经历分享 - 铁血政客 - 铁血政客
图(6-2),低嵌饰细节网格
Direct3D11学习经历分享 - 铁血政客 - 铁血政客
图(6-3),高嵌饰细节网格
使用TS曲面化普通的三角形网格,以便将简单的三角形模型网格更平滑的渲染。PN的意思为Point和Normal即点和法线向量,该算法是在每个三角形的每条边上计算两个新顶点位置、并以及三角形中心计算一个新的顶点位置,同时还为每条边计算一个新的法线向量,让这些原有的位置及法线向量加上新的位置和法线大致成为一个三次表面上的点及法线,具体的算法大家有兴趣的话可以参考《Practical Rendering & Computation with Direct3D11》(本文后面有对这本书的简要概述)第九章,每个三角形总共要计算7个新的位置及3个新的法线向量,而计算这些新的位置和法线向量所需要的数据就是每个三角形原有的顶点坐标及法线向量,因此这非常适合使用GPU的大规模并行计算(Massively Parallel Computation),我们知道Direct3D11引入了通用计算目的(GPGPU,general purpose GPU)的新的着色器即“计算着色器(Compute Shader)”,我们知道GPU的架构本来是就为了便于并行计算的,因此这里使用计算着色器来计算每个三角形的7个新位置和3个法线向量可以充分利用GPU的并行计算性能,以减少CPU的负担。上截图(6-1)、(6-2)、(6-3)分别是原始三角形模型、低嵌饰细节模型、高嵌饰细节模型。
ComputeShader.exe
Direct3D11学习经历分享 - 铁血政客 - 铁血政客
图(7-1)
Direct3D11学习经历分享 - 铁血政客 - 铁血政客
图(7-2)
使用计算着色器来计算地形的平坦度。我们将地形的高度图分成m x n个四边形Patch(Patch是D3D11嵌饰系统的概念,这里不累述),每个Patch的大小为p x q个像素,当我们在嵌饰每个四边形Patch的时候,需要计算Patch的四个边嵌饰因子(SV_TessFactor)及两个内部嵌饰因子(SV_InsideTessFactor),这两个数值决定了嵌饰细节。我们知道在引入LOD的地形渲染中往往会带来恼人的Pop问题,这是因为在地形中几何复杂度高的区域及几何复杂度低的区域使用了相同的LOD,几何复杂度低的区域从高LOD到低LOD不会发生明显的形状变化,但几何复杂度高的区域的区域则能看出明显的形状变化。因此,如果我们可以预先得知地形中不同区域的几何复杂度的话,我们可以在渲染几何复杂度高的区域使用高的细节,在渲染几何复杂度低的区域使用低的细节,这样可大大削弱Pop现象。
         因为地形不同区域的几何复杂度是独立的,在本Demo中,我们预先使用Compute Shader来计算每个Patch的几何复杂度,我们首先通过无序访问视图(Unordered Access View,UAV)将一个D3D11的标准缓存(D3D11的缓存资源中的一种,该资源在着色器中可以像数组一样被访问,本Demo中该资源的HLSL资源类型为Buffer<float>)绑定到计算着色器,并将计算结果保存到该标准缓存中,然后通过资源着色器视图(Shader Resource View,SRV)将该缓存绑定到外壳着色器(Hull Shader),在外壳着色器中读取每个Patch的几何复杂度(也就是每个Patch的平坦程度),并最终计算每个Patch的嵌饰因子,这样可以充分利用GPU的并行计算能力,从而减少CPU的负担。本Demo渲染的地形使用红色绘制高嵌饰细节的Patch,绿色绘制低嵌饰细节的Patch,中间由红—>黄—>绿过渡。从截图(7-2)我们可以看到,即便距离摄像机较近的眼前平坦区域使用低嵌饰细节,而距离摄像机较远的山坡却使用高的嵌饰细节,使用该Demo漫游一下场景会发现地形Pop现象几乎不被感觉到。
ImageProcess.exe
Direct3D11学习经历分享 - 铁血政客 - 铁血政客
图(8-1),原始图像
Direct3D11学习经历分享 - 铁血政客 - 铁血政客
图(8-2),直接高斯过滤
Direct3D11学习经历分享 - 铁血政客 - 铁血政客
图(8-3),优化的分离高斯过滤
  使用计算着色器来进行高斯模糊。在很多后期处理中(如HDR)常用到一项模糊技术——高斯模糊(Gaussian Blur)。高斯模糊需要对图像的每个像素进行处理,将每个像素的周围最近像素与一组数据进行卷积(信号处理的概念啦,简单的说就是乘积累加),这组数据就是所有周围像素到被处理的像素的距离的平方代入高斯方程得到的结果然后再进行归一化(如果忘记了高斯方程可以翻查概率论的相关书籍^_^),例如如果我们要对每个像素进行7 x 7的高斯模糊,则需要对以该像素为中心的周围7 x 7像素块与下面一组数据进行卷积:
{

    // Sigma为根号2时,通过高斯方程计算得到的权值

    {0.000904706, 0.00315773, 0.00668492, 0.00858361, 0.00668492, 0.00315773, 0.000904706},

    {0.00315773, 0.0110216, 0.0233327, 0.0299597, 0.0233327, 0.0110216, 0.00315773},

    {0.00668492, 0.0233327, 0.0493952, 0.0634248, 0.0493952, 0.0233327, 0.00668492},

    {0.00858361, 0.0299597, 0.0634248, 0.081439, 0.0634248, 0.0299597, 0.00858361},

    {0.00668492, 0.0233327, 0.0493952, 0.0634248, 0.0493952, 0.0233327, 0.00668492},

    {0.00315773, 0.0110216, 0.0233327, 0.0299597, 0.0233327, 0.0110216, 0.00315773},

    {0.000904706, 0.00315773, 0.00668492, 0.00858361, 0.00668492, 0.00315773, 0.000904706}

};
 

Direct3D11学习经历分享 - 铁血政客 - 铁血政客

图(8-4),权值的对称性

       直接对每个像素代入卷积计算当然可以得到正确的结果,但是这种方法可以被优化,如果我们先横向进行高斯模糊,然后再纵向进行高斯模糊,且每次高斯模糊的数据为:

{

        0.030078323f, 0.104983664f, 0.222250419f, 0.285375187f, 0.222250419f, 0.104983664f, 0.030078323f

}

我们可以很容易的看出这组数据与上一组的关系,即第一个数值是上一组数据的第一行或第一列的和,其他类似。显然这组数据的和也为1.现在我们来证明分离高斯模糊(即先横向,再纵向)与直接高斯模糊的结果是一致的。 下面省略高斯方程的系数,因为在进行除法的时候系数会被消掉,针对一行像素,我们令:

A = exp(-(dx1 ^ 2) / (2 * σ ^ 2));

B = exp(-(dx2 ^ 2) / (2 * σ ^ 2));

C = exp(-(dx3 ^ 2) / (2 * σ ^ 2));

D = 1.0f;

E = 2 * (A + B + C) + D;

a = A / E;  b = B / E;  c = C / E;  d = D / E;

其中dx为某像素到该行像素中心的距离。再针对一列像素,令:

F = exp(-(dy1 ^ 2) / (2 * σ ^ 2));

G = exp(-(dy2 ^ 2) / (2 * σ ^ 2));

H = exp(-(dy3 ^ 2) / (2 * σ ^ 2));

I = 1.0f;

J = 2 * (F + G + H) + I;

e = F / J;   f = G / J;   g = H / J;  h = I / J;

其中dy为某像素到该列像素中心的距离。由于对称性,我们有:

a = e;        b = f;         c = g;         d = h;

现在我们针对在所在行的权值为a,在所在列的权值为f的那个像素T来讨论,显然T为我们当前要进行高斯模糊的那个像素的最终颜色所提供的百分比为:a * f;

a * f = A * G / (E * J) = exp(-(dx1 ^ 2 + dy2 ^ 2) / (2 * σ ^ 2)) / (E * J);

我们可以进一步证明E * J就是在计算开始那组数据时所要除的分母,但由于计算繁琐,这里就不再一步步证明了。因此我们可以证明a * f的结果即为在进行直接高斯模糊模糊时的其中一个权值,由此可证直接高斯模糊的结果与分离高斯模糊的结果一致。使用直接高斯模糊计算一个像素最终颜色的算法复杂度为7 x 7 = 49,而使用分离高斯模糊计算一个像素最终颜色的算法复杂度为7 + 7 = 14,因此使用分离高斯模糊可以大大减少计算量。

         截图(8-1)为本Demo要进行模糊的原始图像,截图(8-2)为使用直接高斯模糊所得的图像,截图(8-3)为使用分离高斯模糊所得的图像,从图(8-2)和(8-3)可以看出,这两种方法所得的结果完全一致。

FluidSimulation.exe

Direct3D11学习经历分享 - 铁血政客 - 铁血政客
图(9-1)
使用计算着色器来模拟水面波浪。该波浪模型如下图(9-2)所示:

Direct3D11学习经历分享 - 铁血政客 - 铁血政客

图(9-2)

其中每个顶点为一个水柱,每个水柱有8根虚拟的管道连接到相邻的8个水柱,水柱中的水可以通过这些管道流到相邻的水柱,顶点的高度由水柱的水量表示,关于该模型这里不做过多的阐述,有兴趣可参考《Pratical Rendering & Computation with Direct3D11》第十二章。

ParticleSystem.exe

Direct3D11学习经历分享 - 铁血政客 - 铁血政客
图(10-1)
纯GPU维护的粒子系统。该粒子系统在一个点向四周以相同的初始速率发射粒子,所有粒子受到另一个点(黑洞)的引力,当粒子距离黑洞小于一定距离或者它的生命周期结束时,粒子湮灭。本Demo使用两个计算着色器来负责粒子的创建,以及粒子的状态更新。整个流程如下图(10-2)所示:

Direct3D11学习经历分享 - 铁血政客 - 铁血政客

图(10-2)

两个状态缓存都为“附加/消费”结构化缓存(Append / Consume StructuredBuffer),由于CPU不向GPU提供顶点数据,这里使用实例化GPU生成图元的渲染模式,即DrawInstancedIndirect,并且使用几何着色器(Geometry Shader)为每个粒子创建公告牌。

ParaboloidMap.exe

Direct3D11学习经历分享 - 铁血政客 - 铁血政客
图(11-1)

  

实现双抛物面环境映射。对于三维空间中的抛物面方程:

z = -0.5 * (x ^ 2 + y ^ 2) + 0.5;

Direct3D11学习经历分享 - 铁血政客 - 铁血政客

图(11-2)

如图(11-2)所示,我们可以证明在z >= 0的整个半空间中的任意向量,都可以由垂直向下的入射向量(0.0, 0.0, -1.0),经过抛物面反射而得到,图(11-2)中I为入射向量的反向量(0.0, 0.0, 1.0),N为抛物面某点上的法线向量,R为入射向量在该点上的反射向量,很显然我们有:

N = I + R;

通过对抛物面上任一点求偏导数,得到该点上两条等值线的切向量,这两个切向量的叉乘即位该点上的法线向量,经过简单的数学推导,图(11-2)中抛物面上的任一点P(x, y, z)的法线向量为:

N = (x, y, 1);

因此,如果我们把从原点到单位半空间S = {P; P = (x, y, z); x, y, z ∈ [0, 1]}中的任意一点的向量作为反射向量,假设为P0 = (x0, y0, z0),即R0 = P0 – 0 = (x0, y0, z0),那么我们可以在抛物面上找到一个点Q,使得R0在Q上的入射向量为(0.0, 0.0, -1.0),这样我们就把单位半空间中的任意点映射到了平面上的一个单位圆上,且P0在单位圆上对应的点的坐标即为Q点上的法线向量的x,y坐标,我们再将单位圆映射到单位纹理坐标中,这个过程就是抛物面环境映射的基本原理,具体实现大家有兴趣的话可以查看《Pratical Rendering & Computation with Direct3D11》第十三章,或者在网上查找相关资料。

ParallelSplitShadowMaps.exe

Direct3D11学习经历分享 - 铁血政客 - 铁血政客
图(12-1)

实现平行分割阴影映射。阴影贴图是图形学中常用的阴影技术,因其比模板阴影更高效而更加普及,但基本的阴影贴图映射有其缺陷,即当摄像机靠近场景中模型的阴影时,会发现阴影失真,这是因为把看到的整个场景区域的阴影信息全部保存到一张纹理贴图中,但由于场景往往很大,这样导致了阴影信息的丢失,我们可以通过增加阴影贴图的分辨率来减缓这个问题,但显然这会造成更大的开销,甚至是不可行的。本Demo用到的“平行分割阴影映射”可以解决这个问题,基本思想就是把摄像机视景体(Frustum)平行分割成多个块,然后为每个块创建独立的阴影贴图,具体技术信息大家有兴趣的话可以参考《GPU Gems 3》Part II,Chapter 10,上面介绍了详细的技术细节,而且还提供了源代码。

         本Demo将摄像机的视景体平行分割为3块,图(12-1)右侧从上到下显示了由远到近三个分块的阴影信息。

TessellationIsland.exe

使用D3D11嵌饰系统渲染有趣的海岛场景。

Direct3D11学习经历分享 - 铁血政客 - 铁血政客
图(13-1)

图(13-1)显示岩壁渲染结果,从图中可以看出岩壁的斑驳不平,表现还是很丰富的。这里面用到了多张Bump Map来实现这种效果,还有地表的纹理过渡也很自然。

Direct3D11学习经历分享 - 铁血政客 - 铁血政客
图(13-2)
Direct3D11学习经历分享 - 铁血政客 - 铁血政客
图(13-3)
图(13-2)和图(13-3)显示了水面的渲染效果,近看水面的真实度还可以接受,但远看效果就不那么好了,这点我使用PixWin.exe工具来调试水面渲染的像素着色器好久都没能发现原因,本Demo是照着Nvidia SDK 11的一个示例Island11来做的,但怎么也做不出人家那样的水面的渲染效果,搞得我实在自惭形秽,呵呵,下面两张截图为Island11的渲染效果。
Direct3D11学习经历分享 - 铁血政客 - 铁血政客
图(13-4)
Direct3D11学习经历分享 - 铁血政客 - 铁血政客
图(13-5)
因为本Demo只是简单的根据Patch到摄像机的距离来调整嵌饰因子,所以从远处看地表的细节不如Island11那么丰富(如果大家打开Island11的WireFrame渲染模式就会发现它三角形数量相当惊人)。虽然效果不及人家,但在实现的时候也花费了大量精力,从下图(13-6)看出,本Demo渲染整个场景所用到的各种着色器就有二十多个。

Direct3D11学习经历分享 - 铁血政客 - 铁血政客

图(13-6),渲染场景所用到的着色器

Direct3D11学习经历分享 - 铁血政客 - 铁血政客
图(13-7)
   后记,本Demo来设计之初,本想使用的波浪模型为海洋学的统计模型,但苦于那个快速傅里叶变换实现不出来,使用直接的离散傅里叶变换计算居然也不得到正确的结果,可能是我数学基础不够扎实,理解错了数学公式,所本Demo的波浪仅仅是一个高度图的简单应用,不过大家有兴趣的话可以研究这两篇学术论文:《Simulating Ocean Water》(Jerry Tessendorf, 2001)、《Deep-Water Animation and Rendering》(Lasse Staff Jensen, Robert Golias, 2004),如果哪位朋友实现了这个波浪模型,请一定别忘了与我分享哦,呵呵。

在本文结束前,我还想向想要学习Direct3D11的朋友推荐一本书,就是前面多次提及的《Pratical Rendering & Computation with Direct3D11》,不过建议在有了一定的图形学和着色器编程基础之后再去看,当然英文阅读能力是少不了了,这本书对Direct3D11介绍得非常详尽和系统,对于Direct3D11这样的新技术来说,这本书堪称是经典了,呵呵。

各Demo的输入操作说明(没有的表示不接受输入):

TextureArray.exe

         按下鼠标左键,旋转木箱,鼠标滚轮前进和后退摄像机。

BezierSurface.exe

         按下鼠标左键,旋转麦比乌斯带,鼠标滚轮前进和后退摄像机。

DetailTessellation.exe

         'W','S','A','D'键上下左右平移摄像机,按下鼠标右键旋转摄像机,'0'键开启和关闭Wireframe。

CurvedPNTriangles.exe

         按下鼠标左键,旋转飞船,鼠标滚轮前进和后退摄像机,'+'键增加嵌饰细节,'-'键降低嵌饰细节,'0'键开启和关闭Wireframe。

ComputeShader.exe

         'W','S','A','D'键上下左右平移摄像机,按下鼠标右键旋转摄像机,'0'键开启和关闭Wireframe。

ImageProcess.exe

         'P'键切换原始图像、直接高斯模糊图像、分离高斯模糊图像。

FluidSimulation.exe

         'W','S','A','D'键上下左右平移摄像机,按下鼠标右键旋转摄像机。

ParallelSplitShadowMaps.exe

         'W','S','A','D'键上下左右平移摄像机,按下鼠标右键旋转摄像机,'0'键开启和关闭Wireframe。

TessellationIsland.exe

                'W','S','A','D'键上下左右平移摄像机,按下鼠标右键旋转摄像机,'0'键开启和关闭Wireframe。
原创粉丝点击