DirectX大局观认知
一说到要讲DirectX,估计又有朋友会说, 某某游戏引擎多好啊,直接去学游戏引擎不就得了, 干嘛学这图形API ( DirectX 或OpenGL )啊。我想真诚的告诉书本前的你, 如果你希望自己的游戏编程技术有所大成,请学好图形API 之后再去碰游戏引擎,学好图形API 以及计算机图形学相关知识了你可以自己去开发游戏引擎,过早接触游戏引擎只会让你在游戏开发之路上成为扶不起的阿斗。
1.1.1 DirectX的目前地位
1.1.2 DirectX 的两种不同含义
对于游戏开发者, 一般提到DirectX 就是指DirectX SDK 。DirectX SDK 作为开发包, 里面关于DirectX 开发相关的工具与资源应有尽有, 也包括了DirectX Runtime 。我们后面提到DirectX一般都指的是DirectX SDK 。
1.1.3 DirectX 的几套开发方案
- 采用COM 接口的方式。
- 采用.NET 类库的方式。
1.1.4 图形API 体系认知
虽然DirectX 在家用市场全面领先,但在专业高端绘图领域, OpenGL 是不能被取代的主角。
2009 年10 月22 日,微软公司正式发布Windows 7, DirectX 11 集成在Windows 7 中同步登场,但其实DirectX 11 只是DirectX 10 的加强版,而不是对9.0C 和10.0/10.1 的彻底革新。下面我们分别简单概述一下DirectX 与OpenGL 。
1.1.5 微软的宠儿一一DirectX
DirectX 并不是一个单纯的图形API,它是由微软公司开发的用途广泛的APl ,它包含有Direct Graphics(Direct 3D Direct Draw)、Direct Input 、Direct Play 、Direct Sound 、Direct Show 、Direct Setup、Direct Media Objects 等多个组件,提供了一整套的多媒体接口方案。只是其在3D 图形方面的优秀表现,让它的其他方面显得暗淡无光。
微软比较明智,为众厂家推出了一个共同的应用程序接口——DirectX , 并赋予它“硬件设备无关性”的特性。只要这个游戏是依照DirectX 来开发的,不管你是什么显卡、声卡、统统都能玩,而且还能发挥更佳的效果。当然,前提是你的显卡、声卡的驱动程序也必须支持DirectX。
这样就很容易理解了,总结起来就是, DirectX 的出现就是为各种品牌的硬件提供了一个共同的硬件驱动标准。
1.1.6 不甘做备胎一一OpenGL
OpenGL 的历史可以追溯到上个世纪90 年代初,标准诞生之后它一直占据主导地位。微软的DirectX出现的时间比OpenGL 来得晚,但就在最近数十年, OpenGL 因发展迟缓而被DirectX 反超。
首先,我们做一个概念性的总结, DirectX 是一个功能强大的统一的API 接口,而OpenGL 是一个高级图形库。
DirectX 与OpenGL 这对死对头在高性能游戏开发领域一直以来的“世纪之斗”,作为游戏开发业界老生常谈的话题, 一直是大家乐此不疲地谈论的对象。在深入学习DirectX 之前,我们有必要通过这一节来专门分析一下两者的优劣,看一看为什么我们Windows 游戏编程最好学DirectX ,而不是OpenGL。
经常玩电脑游戏的各位都应该有这样的体会,我们安装一款游戏后, 经常会报错缺少某dll 而无法进入,但只要我们更新到最新版本的DirectX 运行环境( runtime ),基本上就可以正常进行游戏了,这是因为市面上绝大多数游戏都是基于DirectX 的。对游戏开发了解有限的玩家基本上都会知道DirectX 是他们玩游戏必须安装的,但知道OpenGL 的却寥寥无几。
毋庸置疑, DirectX 占据着游戏市场绝对的优势,据估计目前市面上几乎所有的电脑游戏都是基于DirectX 而开发的。
关于跨平台, 这是OpenGL 对比DirectX 绝对的优势。这算是OpenGL 最近几年在移动互联网的浪潮中的最大机遇了, 由于最近几年移动开发市场的迅猛发展, Android 和iOS 需要一款专业的图形库, 跨平台的OpenGL 无疑是最好的选择。
DirectX 仅能用于Windows 系列平台,包括Windows 、Windows Phone 、Windows Mobile 、Windows CE 系列以及XBOX、
DirectX 包含图形、声音、输入、网络等模块, 包含开发一款游戏所需的全部工具, 全能性明显。
OpenGL 只是图形函数库。只能用于图形处理,用于开发游戏时的输入、声音、网络等方面还需配合其他函数库。比如声音方面我们就经常配合采用OpenAL。
DirectX 并不是图形库, Direct3D 才是图形库。所以严格意义上来说, Direct3D 与OpenGL 才是对等的一组比较, 这点大家需要弄清楚。
如果我们想进行Android、iOS, MacOS 、Linux 等平台的游戏开发或相关专业性的图形开发,或者喜欢跨平台的特性,选OpenGL。
首先我们复习一个概念, SDK一一SDK 的全称是Software Development Kit , 中文译为软件开发包。SDK 说白了就是一个开发所需资源的一个集合。不像之前的GDI 编程在Visual Studio 中无需任何配置就可以直接开始编写程序并运行出结果,想要进行Direct相关的开发,必须先下载好DirectX SDK 并进行DirectX 开发环境的配置。
1. 下载和安装DirectX SDK
首先, 需要从微软官方网站上下载最新版本的DirectX SDK , 截止本篇的文章时间,2017年10 月, 最新的DirectX SDK 版本为DirectX SDK June10 , 下载地址是:https://www.microsoft.com/en-us/download/details.aspx?id=6812 。大家可以Google 关键字
“ DirectX SDK ” 来得到微软官方网站提供的下载地址。
下载完成后得到一个名为DXSDK_Jun10.exe 的安装包, 然后双击此文件进行安装,安装过程非常简单, 除了要设定安装的目录, 其余的就是不断单击下一步了。
讲解过程中,安装目录我们设定的为D:\Program Files (x86)\Microsoft DirectX SDK (June 2010), 大家可以任意设定, 但要记好目录,下一步会用到这个安装目录的。
如果在【VC++目录】窗口出现的是“ VC++目录编辑功能己被否决”的情况。我们可以不采用上述的方案进入VC++目录,转而采用如下方案:
执行菜单栏中的【视图】→ 【属性管理器】, 在新出现的【属性管理器】工作区中,单击项目—>
添加的示意图如下:
#pragma comment(lib,"d3dx9.lib")
在本书的创作过程中,最新版本的DirectX SDK 为Microsoft DirectX SDK (June 2010)。这个版本的DirectX SDK 中集成了很多的组件,也移除了很多年迈的组件。
在介绍各个组件之前,我们需要知道的是, DirectX SDK 中的“ 带头大哥”是Direct3D ,而DirectX SDK (June 2010) 中的Direct3D 又集成了Direct3D 9、Direct3D 10、Direct3D 11, 即我们安装了这个版本的DirectX SDK ,可以开发出基于Direct3D 9 、Direct3D 10 或者Direct3D 11 的游戏程序。
而每一个大版本的Direct3D,往往根据实际功能更新的需要又分为一些小的版本,比如Direct3D 9 又分为DirectX 9.0、DirectX 9.0a 、DirectX 9.0b 、DirectX 9.0c 等多个版本。
10.4.1 新版DirectX SDK中现存的组件
1.4.2 新版DirectX SDK 中被移除的组件
1. DirectDraw
这个API 被移除可以说是2D 游戏开发方面最大的新闻了。
DirectDraw 曾经用于2D 图形的渲染,目前我们可以运用Direct2D 或者Direct3D 来进行2D 图形的绘制。在目前新版的DirectX SDK (June 2010)中已经完全被移除了, 所以我们没有再去了解它的必要。
2 . DirectPlay
3. DirectShow
4 . DirectMusic
5. DirectSound
DirectSound 是DirectX 中另一款被废弃的底层音频API ,现今被XAudio2 取代了。
1.4.3 关于当前2D游戏开发可用的图形API
看到DirectDraw 惨遭淘汰而它的接班人Direct2D 目前又资料太少技术不成熟,那么在这个空档之中我们该怎么办, 拿什么来进行2D游戏的开发呢?
最佳的答案是找图形绘制方面无所不能的Direct3D 帮忙。其实3D 就是在2D的基础上加了一个维度而己,这方面的典型代表就是Direct3D9 中非常好用一个接口ID3DXSprite ,它专门帮助我们用Direct3D 来渲染2D 子图形(Sprite),使得2D 游戏的开发手到擒来。
安装完DirectX 的SDK 后, 大家应该会有我们安装的SDK 到底有哪些内容的疑问吧,这一节我们将对DirectX SDK 安装路径下的文件进行一下分析。
- Developer Runtime:其中存放了DirectX 运行时的动态链接库相关文件,即这个文件夹中放了一箩筐和DirectX 运行相关的dll 文件, 比如说d3d9d.dll.
- Documentation:其中存放了DirectX 的官方文档,所有DirectX 开发知识的来源,知识的金山, 大宝库一座。我们通过D:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Documentation\DirectX9 路径下的directx_sdk.chm 和windows_graphics.chm来打开这些文档。其中windows_graphics.chm 是图形库相关的API (比如Direct3D9, Direct3D 11 , Direct2D 等等)的文档集合。而directx_sdk.chm 中是DirectX 中除图形库以外的API (比如Directlnput )的文档集合。
windows_graphics.chm 文档的截图
directx_sdk.chm 文档的截图
- Extras:里面放着一些额外的动态链接库,对于我们这个版本的DirectX SDK,只存放了DirectSound 的动态链接库dsound.dll 而已。
- Include : 里面存放了DirectX SDK 中所有的头文件,我们在上一小节配置开发环境时添加了这个文件夹,即把DirectX SDK 中所有的头文件添加到了Visual Studio 中。
- Lib:里面存放了DirectX SDK 中所有的库文件,我们在上一小节配置开发环境时添加了这个文件夹,即把DirectX SDK 中所有的库文件链接到了Visual Studio 中。
- Redist:里面存放了历史版本的DirectX SDK 中的一些API的动态链接库。
- Samples: 又一座大宝库!里面存放了DirectX SDK 中所有示例程序,如果你能看懂里面的所有代码并纳为己用,去世界上任何一家游戏公司做主程都够格了!
点进这个文件夹,即来到路径 D:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Samples,我们又可以看到3 个文件夹,如下图。
首先我们看看Media 文件夹, 里面存放着所有示例程序需要用到的图片、音频、3D 模型等素材资源。
然后是SampleBrowser 文件夹,这算是微软比较人性化的一项设计了,里面用一个图形界面程序把所有的示例程序的相关文档,以及最终程序运行文件放到了一个示例浏览器中,非常方便和赏心悦目。
双击D:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Samples\SampleBrowser 路径中的SampleBrowser.exe ,我们便可以打开这个示例浏览器。
DirectX 示例浏览器
我们可以任意选一个示例程序, 单击它的Executable 按钮,就可以运行这个示例程序,并弹出相关的讲解文档,比如说我们找到DirectX9 的LocalDeformablePRT这个示例程序, 单击64-bit Executable 按钮。
剩下的最后一个便是存放了所有示例程序源代码的文件夹了,我们可以清楚地看到这个文件夹命名为“ C++” 。看到没,存放所有
DirectX 官方示例程序的文件夹直接用C 来命名, 这说明这些示例程序都是用C 编写的,知道C 在游戏开发界的地位了吧。DirectX 配C ,目前高性能游戏开发界公认的绝配。
打开这个名为C 的文件夹,可以看到里面也分为众多的文件, 这里的Direct3D 就指的是Direct3D9 ,其他的文件夹存放的示例大体分的很明显, 有Direct3D10的、Direct3D11 的、DXUT 的等等。对于目前网络上匮乏的Direct3D11的资料, 官方的SDK 是不可多得的第一手资料, 但对于国内目前游戏开发界Direct3D11 几乎为0 的普及率来说,过几年这些新资料才会真正地发扬光大。
system:这个文件夹中存放了DirectX SDK 安装和卸载相关的文件,没什么特别的地方。
Utilities 这个文件夹中存放了DirectX SDK 相关的工具的执行文件和源代码,DirectX SDK中为我们提供了很多好用的工具,比如Audio Console 、DXCapsViewer、DxTex等数十款。
其中最直观的工具, 当属硬件查看工具DXCapsViewer。我们可以打开硬件查看工具DXCapsViewer 查看我们电脑的硬件信息, 如下图。
里面的对电脑硬件的剖析非常专业,大家可以自己运行一下,看看自己电脑尤其是显卡的性能与所支持功能。
为了让SDK 能更快更容易被使用者所掌握, SDK 的发布者往往会在SDK 发布的同时在SDK中附加很多的技术文档(Documentation )和示例程序( Samples )。这些技术文档相当于是这套SDK的百科全书和最权威最全面的教材,我们能通过它们快速地学习和掌握这套全新的SDK。而示例程序就是为我们准备的一些基于这些SDK 所提供的技术而写出来的程序,教我们如何动手编写基于了这套SDK 的程序,这些示例程序当然含有源代码供我们学习。任何一套SDK 中的示例程序的源代码都是非常珍贵的编程实战学习资源。
1.7.1 DirectX的几套版本简介
DirectX 9 , 一路走来,追捧者无数, 一手遮天, 是目前PC 游戏界的中流砾柱,占据着DirectX家族的绝大多数市场份额。
DirectX 10 ,这个悲剧的孩子由于搭载了坑爹的操作系统Windows Vista,生不逢时, 注定了它此生的坎坷和怀才不遇。
DirectX 11 ,这位才华横溢的孩子,在合适的时间出现在了合适的操作系统一一-Windows 7 上,它或许会在未来几年内取得不错的成绩, 但是目前而言,依旧是Direct3D9 的天下。而在国内,DirectX 11 的普及或许需要比国外更多的时间。
1.7.2 DirectX11 vs DirectX9 ,现阶段学哪个好?
1. 两者发行的英文书籍对比
基于DirectX 11 的入门书目前也就几本,进阶书籍几乎没有。而基于DirectX9 的入门书籍丰富,至少50 本,进阶书籍如《Game Programming Gems 》系列,《ShaderX 》系列。目前市面上主流的游戏编程的进阶书籍基本上都是基于DirectX9 的,非常丰富,真正去学恐怕一辈子都很难学完。
2 . 两者发行的中文教程对比
DirectX 11 目前的中文教程几乎等于没有。DirectX9 目前的中文教程丰富, 叫的出名字的至少有10 来本。
3 . 两者支持的游戏引擎对比
市面上数百款三维游戏引擎都支持Direct9,而且基本上这些引擎的萌芽时期陪伴在身边的就是DirectX9 ,所以他们的架构的体系或多或少都针对DirectX9 有一些专门的设计。
再说游戏引擎对DirectX11 的支持。有点惨淡, DirectX 11 发行至今近3 年时间, 去更新支持DirectX11 的引擎据作者了解的确不多,除了一些热门的商业引擎如虚幻3 之流去主动更新支持之外,其他的众多开源引擎真的就很少花大力气去更新与适应这款颠覆前作设计模式的新图形API了,就算是做了DirectX11 更新的一些引擎,也是部分功能上的支持, BUG 一大堆,用来做游戏开发差强人意, 效果和开发效率甚至不如DirectX9 。
所以,现阶段而言,如果你想深入学习与研究游戏引擎,最合适的还是掌握DirectX9。
互联网上DirectX11 英文资料系统的也就一个http://www.rastertek.com/tutdx11.html网站。中文资料几乎等于没有。
而互联网上关于DirectX9 的资料就无比丰富了,无论是中文还是英文的,互联网上教程和代码都不计其数。稍微Google/百度一下就够看了。
鉴于以上4 点,当今如果选择DirectX11 来学习,你会发现学到一定程度之后会尴尬地觉得进阶的学习资料非常地匮乏,几乎没有。甚至自己辛辛苦苦学了这么久的东西还没做出点像样的游戏Demo 出来,就搁浅了。然后就觉得迷茫与尴尬,最终还是退回到了DirectX9 的怀抱。
5 两者在技术与背景方面的对比
首先DirectX11 和DirectX9 相比,是技术架构的完全颠覆,这就说我们掌握了DirectX9 的API之后,要学DirectX11的话, 得从头开始。
但可惜的是, DirectX11 相对于DirectX9 来说并没有什么革命性的画质提高,并没有提供非常有诱惑力非升级不可的功能, 国内外的很多游戏厂商都不愿意投入人力和物力去进行这次API的升级。2013 年新发布的国内一流游戏大作《仙剑奇侠传五前传》和国外一流的游戏大作《鬼泣5 》依然采用的是技术成熟的Direct3D 9.0c 就是最好的证明。
鉴于目前国内游戏广商在DirectXI l 领域几乎为零的开发经验,从DirectX9 全面技术升级到DirectX 11,相当于丢弃原来打好的江山白手起家。所以目前没有l哪家国内的游戏厂商会去做这个吃力不讨好的尝试, 这就注定了DirectX11在国内坎坷的普及之路。
技术大牛们都知道,学IT 这一行,在于精而不在泛。往往不要去赶什么时髦, 学什么新技术,因为你是永远赶不上的。往往学那些最经典、适用面最广、市场占有率最高的东西, 再加上适当的新技术的学习,就能受用终身, 因为技术思想是一脉相承的。
最后言简意贩一句话,目前在国内想从事游戏开发行业或者轻松地开发出自己的三维游戏,请选择目前市场占有率最高的
主流API——DirectX 9 作为突破口。
顾名思义,从字面上就可以看出这两套方案的一些端倪出来。下面我们简单介绍一下Direct3D中两套渲染体系的特点和整体思路, 给大家一个大体印象。在介绍之前, 有一个必须先跟大家说清楚的事实,就是在DirectX 10 以及DirectX 11中,固定功能渲染流水线已经被移除了, 而可编程渲染流水线则得到了重用,这反映了一个明显的趋势。但是, 由于目前Direct3D9 依旧不可一世的市场占有率, 国内厂商对DirectX9 的热衷,所以目前固定功能渲染流水线依旧有学习的必要。而且固定功能流水线学习起来简单。先学习固定功能流水线,再学习可编程渲染流水线, 是当前学习游戏编程的最佳路途。下面我们分别介绍一下这两套DirectX9 中的渲染流水线体系:
1 . 固定功能流水线
第一套方案, 固定功能渲染流水线( fixed function render pipeline)。
顾名思义,固定功能渲染流水线从某种意义上来讲是固定的(fixed )。它有着自己的一套准则,关于光照, 关于矩阵变换。要进行一个完整而全面的渲染操作, 基本上都是按以下步骤进行的: 填充顶点数据,指定纹理坐标,设置材质,设置光照, 设置变换矩阵, 设置渲染状态,最终绘制图形。这里先给大家一个步骤上的概念, 后续文章中会详细给大家介绍的。很多时候,我们只需要遵守着这套固定的准则一步一步地进行相关代码的书写,就完全可以驾驭这种渲染方法了。我们使用固定功能渲染流水线进行画面的渲染,说穿了就是根据我们的需要,不断地通过Direct3D设备指针调用一些Direct3D 中预设的函数,比如用SetRenderState()设置各式各样的渲染状态,SetSarnplerState()设置各式各样的采样状态等等。至于场景的处理和绘制的内部过程我们无需插手, Direct3D 的引擎会根据我们设置的各种渲染状态, 自己来完成,非常地人性化。由于这种渲染方案在新版的Direct3D 中被移除, 所以很多时候我们只需稍微了解,在后面,我们会淡化固定功能流水线的使用。
2. 可编程渲染流水线
接着我们就来大概了解一下目前的渲染技术的趋势——可编程渲染流水线。
可编程渲染流水线( Programmable Render Pipeline)与固定功能流水线有着很大的不同,通常我们说的自己写shader 就是指的这套渲染体系,这是目前3D 编程的大趋势。从字面意义上来说,它是可编程的,很灵活,而不是固定的。这样我们就可以通过代码来实现那些在固定功能流水线中不太好实现的技术和效果,从而升华了我们的渲染技术。可编程渲染流水线中的核心,是着色器
( shader )。在Direct3D9中,我们主要关注的是顶点着色器(vertex shader )和像素着色器( pixel shader)。也就是说,我们为着色器编写一些规模较小的代码,然后在GPU 上进行编译和运行,这就是所谓的可编程渲染流水线的精髓。关于我们在可编程渲染流水线中使用的一种辅助C 的编程语言,是一种编译和运行在GPU ( Graphic Processing Unit )图形处理器之上的Direct3D 中独
有的着色器编程语言——HLSL ( High Level Shader Language , 高级着色器语言) 。
Direct3D 作为DirectX 的绝对主力, 是微软与OpenGL 在3D 图形领域抗衡的正面武器。每次DirectX 升级之时, 微软都会单独针对Direct3D 这款API 进行大量更新,使其拥有更强大的功能、更完善的使用体验。因为Direct3D 主攻3D 图形与3D 游戏,可谓DirectX 中撑场面的API ,自然我们在后续讲解中要将更多的重心放在它之上。
下面我们就来迈出介绍Direct3D 的第一步,讲解Direct3D 程序开发和运行密切相关的一些知识。
1. Direct3D 程序的体系结构
先来看一张结构图,这是Direct3D, GDI/GDI+与应用程序,显卡之间交互关系的一张简明扼要的结构图。
上图中, Win32 应用程序可以使用Direct3D 以及GDI/GDI+两套图形库完成与显卡的交互。当然,能与显卡交互的方式不只有这两种,方法多得是,这里我们只需要暂时知道有这两种就可以了。
我们可以看到,与Direct3D 和GDI/GDI+处于同一层次,也就是说,Direct3D 和GDI/GDI+都可以通过图形设备驱动程序接口(DDI )访问图形硬件,也就是显卡。但不同于GDI/GDI+这对“屌丝”设备的是, “高富帅” Direct3D 可是有一个牛逼闪闪的“后台”的,那就是硬件抽象层( HAL )。Direct3D 可以使用硬件抽象层( HAL )通过图形设备驱动程序接口( DDI )来访问显卡,从而可以
充分地发挥显卡的潜在性能,绘制出高性能高质量的精美图形来。
2. 关于硬件抽象层HAL
大多数基于Direcr3D API 设计开发的三维图形程序都运行于硬件抽象层( Hardware Abstraction Layer ),也就是HAL之上。使用HAL 的好处, 是既能充分利用系统硬件的加速功能,又隐藏了硬件相关的设备特性。这就是说, Direct3D 利用HAL 实现了设备无关的特性,通过Direct3D 可以编写出与设备无关的高效代码。硬件抽象层是由硬件制造商提供的特定于硬件的接口,Direct3D 利用该接口实现了对显示硬件的直接访问。所以,应用程序永远不需要访问HAL,直接与Direct3D API 打交道就可以了。HAL 可以是显卡的一部分,也可以是和显卡驱动程序相互关联的单独动态链接库( DLL) 。
HAL 仅仅是与设备相关的代码,对于硬件不支持的功能,它并不提供软件模拟。在DirectX 9.0中,针对同一种显示设备, HAL 提供3 种顶点处理模式:软件顶点处理、硬件顶点处理和混合顶点处理。还有,纯硬件设备是HAL 的变体,纯硬件设备类型仅支持硬件顶点处理。
如果我们的显卡支持Direct3D 的话, HAL 就存在于我们的计算机中,而需要运行DirectX 9.0开发的应用程序的话,我们的显卡驱动程序需要至少支持DirectX 7.0 版本以上的DDI 才可以,不过在如今支持DirectX 11 显卡烂大街的时代,这显然不会是什么问题。
3 . 关于参考光栅设备REF
万事还是有个特殊的,是吧。有时候, Direct3D 提供的某些功能不被我们的显卡支持, 但是我们偏偏想去使用这些功能的话,就可以使用一下Direct3D 的辅助设备,也就是参考光栅设备( Reference Rasterizer Device, REF )。这种REF 设备可以以软件运算的方式完全支持Direct3D API 。借助REF设备,我们可以在代码中使用那些不为当前硬件所支持的特性, 并对这些特征进行测试。
1 . 善用DirectX SDK自带文挡和Sample示例程序
学习DirectX 初期其实并不用有太多的数学和物理基础,因为DirectX 的学习初期无非是在学一些API 的调用规则而已。所以,在学习初期我们最好淡化数学和物理知识,随着学习和掌握的深度,再补充数学和物理知识才是比较科学的路线。
我们在DirectX 这款为游戏而生的API 的大局观掌控上下足了功夫, 一起过了一遍DirectX 相关的周边知识,也接触了很多其他介绍DirectX 的书籍中不可能告诉大家的独家心得和学习方法。