原文地址 http://fabiensanglard.net/doom3/(翻译的 有很多 错误有的我现在能改的尽量改一些但是就事实来说作者很多地方有些地方写的可以比如原作者 博客文章中讲述doom3法线贴图凹凸贴图bump等等部分图文都有包括一些领悟配图doom3前向光照变换光线的变化等等.....嗯有些地方适中有的领悟就...........大同小异理解源代码多一些好处之一就是想修改的时候能够自己改一改代码..............现在看也有不足比如ui其实也是要调用opengl等渲染的渲染2d的比如各种文字按钮 游戏中很多作者似乎只重视3d的显示很多并没有写2d的很多渲染包括其他的很多,现在看 原作者只是写了一部分而且只是doom3引擎部分的一部分而已而不全面且没有那么深入.........我从作者文章中得到的很多领悟 有限 ..........本质上还是要翻阅源代码嗯要看源代码源代码内容最多id tech 源代码 有它自身的特点比如关卡编辑器brush 可以编辑地图编辑器内部就可以有些图片加载不上来我删除了有需要看英文原文就是了有的也未必全部.....本质上要看源代码源代码 其实可以把很多注释 翻译成汉语看看我自己有时间的话翻译一下感觉比以前领悟了一些............前进了一些 ....................)2012年6月8日DOOM3源代码评测简介第1部分共6部分2011年11月23日id软件保持传统并发布了其以前引擎的源代码。这一次是轮到了idTech4使用它创造出Prey,quake4当然是Doom 3.在几个小时之内GitHub上的源代码被下载了400多次人们开始看游戏内部机制/在其他平台上引导引擎。我也跳上它并及时完成了Mac OS X的Intel版本 约翰·卡马克。在清晰度和评论方面这是 Doom iPhone代码库这是更新的因此更好的评论的id软件最好的开源代码。之一我强烈建议大家阅读编译和实验。下面是我的笔记 就我的理解。像往常一样我已经清理了它我希望它会节省一个人几个小时我也希望它会激励我们中的一些人阅读 更多的代码并成为更好的程序员。第1部分概述第2部分Dmap第3部分渲染器第4部分剖析分析 代码一部分 而已……第5部分脚本第6部分访谈包括与约翰·卡马克的问答从笔记到文章...我注意到我正在使用越来越多的绘图和越来越少的文本来解释代码库。到目前为止我已经使用gliffy绘制但这个工具有一些令人沮丧的限制如缺乏alpha通道。我正在考虑编写一个专门用于使用SVG和Javascript绘制3D引擎的工具。我想知道这样的事情是否已经存在无论如何回到代码...背景掌握 这样一个突破性引擎的 源代码 是 令人兴奋的。Doom III于2004年发布为实时引擎设定了新的 视觉 和 音频 标准最为显着的是“统一照明与阴影”。这项技术首次允许艺术家以 好莱坞的规模 表达 自己。即使8年后在Delta-Labs-4中 与 HellKnight 的第一次遭遇 仍然 看起来 非常棒第一次联系源代码现在通过Github进行分发这是一件好事因为来自id Software的FTP服务器几乎总是关闭或重载。来自TTimo的原始版本与Visual Studio 2010 Professional编译良好。不幸的是 Visual Studio 2010“Express” 缺少MFC因此无法使用。这是令人失望的释放此处 翻译有误但有些人已经删除了依赖。Windows 7的 git clone https://github.com/TTimo/doom3.gpl.gitWindows 7的 git clone https://github.com/TTimo/doom3.gpl.git对于代码阅读和探索我更喜欢在Mac OS X上使用XCode 4.0SpotLight的搜索速度变量 亮点(翻译有误 ) 和 “命令点击” 翻译有误达到 定义 使得 体验 优于 Visual Studio。XCode项目在发布时被破坏但是很 容易解决几个步骤现在有一个Github存储库由“坏扇区”在Mac OS X Lion 上 运行 良好。MacOS X git克隆 https://github.com/badsector/Doom3-for-MacOSX-MacOS X git克隆https://github.com/badsector/Doom3-for-MacOSX-注意安装 Visual Studio 2010生产力电动工具后Visual Studio 2010中也可以看到“变量hightlights”和“Control-Click”。我不明白为什么这不是香草安装的一部分。两个代码库现在都处于最佳状态一次点击可执行文件下载代码击中F8 / Commmand-B。运行 琐事为了运行游戏您将需要base包含Doom 3游戏的文件夹。因为我不想浪费时间从Doom 3 CD中提取它们并更新它们我下载了Steam版本。似乎id软件团队做的一样因为Visual Studio项目发布 仍然包含set fs_basepath C:\Program Files (x86)\Steam\steamapps\common\doom 3在调试设置琐事引擎是用Visual Studio .NET开发的。但代码不具有单行的C发布的版本需要Visual Studio 2010 Professional 才能 编译。琐事Id软件团队似乎是Matrix电影系列黑客帝国的粉丝Quake III的工作题目是“Trinity”Doom III的工作题目是“Neo”。都出自黑客帝国电影中翻译有误代码文件夹结构该解决方案分为 反映 引擎整体架构 的项目项目构建意见视窗MacO SXgamegamex86.dllgamex86.soDoom3游戏d3xpgamex86.dllgamex86.soDoom3 eXPensionRessurection游戏MayaImportMayaImport.dll-资产创建工具链的一部分在运行时加载以打开Maya文件并导入怪物摄像头路径和地图。doom3Doom3.exeDoom3.appDoom 3引擎TypeInfoTypeInfo.exe-内部RTTI帮助器生成GameTypeInfo.h具有每个成员大小的所有Doom3类类型的映射。这允许通过TypeInfo类进行内存调试。CurlLibCurlLib.lib-HTTP客户端用于下载文件Staticaly 链接到 gamex86.dll 和doom3.exe。idlibidLib.libidLib.aid软件库。包括解析器词法分析器字典...Staticaly链接到gamex86.dll和doom3.exe。像 idTech2的每个引擎一样我们找到一个封闭的源代码二进制doom.exe和一个开放源代码的 动态库gamex86.dll自2004年10月以来大多数代码库已经通过Doom3 SDK访问只有Doom3可执行源代码失踪。模式能够构建idlib.agamex86.dll但 引擎的核心仍然是 封闭源。现在已经开源了不过卡马克阴影体反转方法 未知 注意引擎不使用标准C 库所有容器映射链接列表...都被重新实现但libc被广泛使用。注意在游戏模块中每个类都扩展了idClass。这允许引擎执行内部RTTI并通过类名实例化类。琐事如果你看图纸你会看到几个基本框架如Filesystem在Doom3.exe项目中。这是一个问题因为gamex86.dll也需要加载资源。这些子系统由doom3.exe中的gamex86.dll动态加载这是图中箭头实现的。如果我们用PE Explorer中的DLL我们可以看到gamex86.dll导出一个方法GetGameAPI一切正常完全相同的方式Quake2中加载的渲染和游戏的DDL交换对象的指针当Doom3.exe启动它exe这是图中箭头实现的。如果我们用PE Explorer中的DLL我们可以看到gamex86.dll导出一个方法 一切正常完全相同的方式Quake2中加载的渲染和游戏的DDL交换对象的指针当Doom3.exe启动它exe这是图中箭头 实现的。如果我们用PE Explorer中的DLL我们可以看到gamex86.dll导出一个方法 一切正常完全相同的方式Quake2中加载的渲染和游戏的DDL交换对象的指针当Doom3.exe启动它通过DLL加载其进程内存空间LoadLibrary。GetGameAPI使用win32来获取dll中的地址GetProcAddress。打电话GetGameAPI。 翻译有误gameExport_t * GetGameAPI_tgameImport_t * import;gameExport_t * GetGameAPI_tgameImport_t * import;在“握手”翻译可能有误结束时Doom3.exe 具有 指向idGame对象的 指针Game.dll具有指向gameImport_t包含对 所有 缺少 子系统 的 其他引用 的 对象 的 指针例如idFileSystem。Gamex86 对 Doom 3 可执行对象 的看法typedef struct{int版本;// API版本idSys * sys;//非便携式系统服务idCommon * common;// commonidCmdSystem * cmdSystem// console command systemidCVarSystem * cvarSystem;// 控制台 变量系统idFileSystem * fileSystem;//文件系统idNetworkSystem * networkSystem;//网络系统idRenderSystem * renderSystem;// render systemidSoundSystem * soundSystem;// sound systemidRenderModelManager * renderModelManager;//渲染模型管理器idUserInterfaceManager * uiManager;//用户界面管理器idDeclManager * declManager;//声明管理器idAASFileManager * AASFileManager;// AAS文件管理器idCollisionModelManager * collisionModelManager;// 碰撞模型管理器} gameImport_t;typedef struct{int版本;// API版本idSys * sys;//非便携式系统服务idCommon * common;// commonidCmdSystem * cmdSystem// console command systemidCVarSystem * cvarSystem;//控制台变量系统idFileSystem * fileSystem;//文件系统idNetworkSystem * networkSystem;//网络系统idRenderSystem * renderSystem;// render systemidSoundSystem * soundSystem;// sound systemidRenderModelManager * renderModelManager;//渲染模型管理器idUserInterfaceManager * uiManager;//用户界面管理器idDeclManager * declManager;//声明管理器idAASFileManager * AASFileManager;// AAS文件管理器idCollisionModelManager * collisionModelManager;//碰撞模型管理器} gameImport_t;game / Modd对象中的Doom 3的视图typedef结构 {int版本;// API版本idGame *game;//界面运行游戏idGameEdit * gameEdit;// 界面 进行 游戏内编辑} gameExport_t;typedef结构 {int版本;// API版本idGame *game;// 界面 运行 游戏idGameEdit * gameEdit;// 界面 进行 游戏内 编辑} gameExport_t;注意了解更好的每个子系统的一个很好的资源是Doom3 SDK文档页面该页面现在不见得就能打开它似乎是在2004年深入了解代码的人写的所以可能是 开发团队的成员。代码在挖掘之前一些统计数据来自cloc./cloc-1.56.pl新 2180个文本文件。 2002独特文件。 626个文件被忽略。 http://cloc.sourceforge.net v 1.56 T 19.0 s77.9 files / s47576.6 lines / s -------------------------------------------------- ----------------------------- 语言文件空白评论代码 -------------------------------------------------- ----------------------------- C 517 87078 113107 366433 C / C 标头617 29833 27176 111105 C 171 11408 15566 53540 Bourne Shell 29 5399 6516 39966 使43 1196 874 9121 m4 10 1079 232 9025 HTML 55 391 76 4142 Objective C 6 709 656 2606 Perl 10 523 411 2380 yacc 1 95 97 912 Python 10 108 182 895 目标C 1 145 20 768 DOS批次5 0 0 61 Teamcenter def 4 3 0 51 Lisp 1 5 20 25 awk 1 2 1 17 -------------------------------------------------- ----------------------------- SUM1481 137974 164934 601047 -------------------------------------------------- -----------------------------./cloc-1.56.pl新 2180个文本文件。 2002独特文件。 626个文件被忽略。 http://cloc.sourceforge.net v 1.56 T 19.0 s77.9 files / s47576.6 lines / s -------------------------------------------------- ----------------------------- 语言文件空白评论代码 -------------------------------------------------- ----------------------------- C 517 87078 113107 366433 C / C 标头617 29833 27176 111105 C 171 11408 15566 53540 Bourne Shell 29 5399 6516 39966 使43 1196 874 9121 m4 10 1079 232 9025 HTML 55 391 76 4142 Objective C 6 709 656 2606 Perl 10 523 411 2380 yacc 1 95 97 912 Python 10 108 182 895 目标C 1 145 20 768 DOS批次5 0 0 61 Teamcenter def 4 3 0 51 Lisp 1 5 20 25 awk 1 2 1 17 -------------------------------------------------- ----------------------------- SUM1481 137974 164934 601047 -------------------------------------------------- -----------------------------代码行的数量通常不是一个很好的指标但是在这里为了评估引擎的理解力度可能非常有帮助。与Quake III相比601,047行代码使引擎 两倍“难”。关于id的历史的几个统计软件引擎代码行代码线厄运idTech1idTech2idTech3idTech4发动机39079143855135788239398601032工具3411115528140128417-总39420155010163928367815601032注意对于工具来说idTech3 的巨大 增长 来自lcc代码库用于生成QVM字节码的C编译器。注意由于Doom3被集成到引擎代码库中所以没有任何工具 被 归结 为 Doom3。从高层来看这里有几个有趣的事实在第一次在软件历史上代码是C 而不是C.约翰·卡马克在我们的问答中阐述了这一点。抽象和多态在代码中使用很多。但是一个好的技巧避免了一些对象的 vtable 性能。所有 资产 都以 人类可读 的文本形式存储。没有更多的二进制该代码正在广泛使用词法分析器/解析器。约翰·卡马克John Carmack在我们的问答中阐述了这一点。模板用于低级实用程序类主要是idLib但从来没有在上层看到(此一句空缺翻译有误)所-他们不会让你的的方式 谷歌 的V8源代码。在代码评论方面它是来自id软件的 第二好 的 代码库唯一一个更好的是Doom iPhone可能是 因为 它 比 Doom3 更新。30的评论仍然很出色很少找到一个很好的评论的项目在代码的某些部分参见dmap页面实际上比语句更多的注释。OOP封装使代码清洁易于阅读。低级装配优化的时代已经过去了。这里有一些技巧idMath::InvSqrt和 空间本地化 优化但大多数代码只是尝试在可用时使用这些工具GPU着色器OpenGL VBOSIMDAltivecSMPL2优化R_AddModelSurfaces每个模型处理... 。查看由John Carmack定义的idTech4编码标准镜像也很有意思我特别赞赏关于const布局的评论。展开循环这是主要循环展开引擎最重要的部分idCommonLocal commonLocal;// OS专用对象idCommon * common commonLocal;//接口指针因为Init是依赖于操作系统的它是一种抽象的方法intWINAPI WinMain HINSTANCE hInstance HINSTANCE hPrevInstance LPSTR lpCmdLine int nCmdShow { Sys_SetPhysicalWorkMemory192 201024 20;// 最小 201,326,592最大 1,073,741,824Sys_CreateConsole ;//由于 引擎 是 多线程的互斥体在这里初始化每个“关键”并发执行代码的一个互斥体。forinti 0; i MAX_CRITICAL_SECTIONS; i { InitializeCriticalSectionwin32.criticalSections [i]; } common- Init0NULLlpCmdLine;// 评估 VRAM 有 多少不是通过 OpenGL 完成 但OS调用Sys_StartAsyncThread {//下一个查找运行是一个单独的线程。而1 { usleep16666;//运行在60Hzcommon- Async;//做工作Sys_TriggerEventTRIGGER_EVENT_ONE;//解锁其他线程等待输入pthread_testcancel ;// 检查主线程是否被取消在关机时。} } Sys_ShowConsole而1{ Win_Frame;//显示或隐藏控制台共框架 { session- Frame//游戏逻辑{forinti 0; i gameTicsToRun; i RunGameTic { game- RunFramecmd;//从这一点起执行跳转到GameX86.dll的地址空间。for ent activeEntities.Next; ent NULL; ent ent- activeNode.Next ent- GetPhysics - UpdateTimetime;//让实体思考} } session- UpdateScreenfalse;//正常的按序屏幕更新{ renderSystem- BeginFrame idGame :: Draw// Renderer前端。实际上并没有与GPU沟通renderSystem- EndFrame R_IssueRenderCommands// 渲染器后端。将GPU优化的命令发布到GPU。} } } }idCommonLocal commonLocal;// OS专用对象idCommon * common commonLocal;//接口指针因为Init是依赖于操作系统的它是一种抽象的方法intWINAPI WinMain HINSTANCE hInstance HINSTANCE hPrevInstance LPSTR lpCmdLine int nCmdShow { Sys_SetPhysicalWorkMemory192 201024 20;// 最小 201,326,592最大 1,073,741,824Sys_CreateConsole ;//由于引擎是多线程的 互斥体 在 这里 初始化每个“关键”并发执行代码的一个互斥体。forinti 0; i MAX_CRITICAL_SECTIONS; i { InitializeCriticalSection win32.criticalSections [i] ; } common- Init0NULLlpCmdLine;// 评估 VRAM 有多少不是 通过 OpenGL 完成 但OS 调用Sys_StartAsyncThread {// 下一个 查找运行 是一个 单独的线程。而1 { usleep16666;//运行在60Hzcommon- Async;//做工作Sys_TriggerEventTRIGGER_EVENT_ONE;//解锁其他线程等待输入pthread_testcancel ;//检查 主线程 是否 被 取消在关机时。} } Sys_ShowConsole而1{ Win_Frame;//显示或隐藏控制台共框架 { session- Frame //游戏逻辑{forinti 0; i gameTicsToRun; i RunGameTic { game- RunFramecmd;// 从这一点起执行跳转到GameX86.dll的地址空间。forent activeEntities.Next; ent NULL; ent ent- activeNode.Next ent- GetPhysics - UpdateTimetime;//让实体 思考} } session- UpdateScreenfalse;//正常的按序屏幕更新{ renderSystem- BeginFrame idGame :: Draw// Renderer前端。实际上并没有与GPU沟通renderSystem- EndFrame R_IssueRenderCommands// 渲染器后端。将GPU优化的命令发布到GPU。} } } }有关详细信息请参阅阅读代码时作为地图使用的完全展开循环。它是id软件引擎的标准主循环。除了Sys_StartAsyncThread表示Doom3是 多线程 的。此线程的目标 是 处理 引擎 不希望 限制 帧 速率 的 时间 关键 功能声音混合用户输入生成。琐事idTech4高级对象都是具有虚拟方法的抽象类。这通常会涉及性能问题因为每个虚拟方法地址在运行时调用之前都必须在vtable中查找。但是有一个“伎俩”来避免这种情况。所有 对象 都 静态实例化idCommonLocal commonLocal;// 实现idCommon * common commonLocal;//指针for gamex86.dll由于 在 数据段中 静态分配 的 对象 具有 已知 类型编译器可以commonLocal在 调用 方法 时 优化 远程 执行 vtable查找。接口指针 在 握手 期间 使用因此doom3.exe可以 交换 对象引用gamex86.dll但在 这种 情况下vtable的成本 未被 优化。琐事从id软件中读取大多数引擎我发现一些方法名称自从doom1引擎以来就没有改变负责抽取 鼠标和 操纵杆输入的方法仍然被称为IN_frame()。渲染两个重要部分由于Doom3 使用 portal 门户系统所以预处理工具dmap完全脱离了 传统的 bsp构建器。我在一个专门的页面上深入审查了它。运行时渲染器具有非常有趣的体系结构因为它在前端和后端分为两部分更多的专用页面。剖析我使用Xcode的仪器来检查CPU周期在哪里。结果和分析在这里。脚本和虚拟机在每个idTech产品中VM和 脚本语言从以前的版本 都 完全改变了他们再次做到了 细节在这里。面试在阅读代码时几个新奇使我感到困惑所以我写信给约翰·卡马克他很高兴回复深入的解释C 。渲染器分为两块。基于文本的资产。解释的字节码我还编辑了关于idTech4的所有视频和新闻采访。这些都在采访页面。推荐读物像往常一样你可以享受的书如果你喜欢的代码还有一件事夏天来了并不总是很容易集中...但 总的 来说这是一个大部分 的 阅读。由于idTech5 源代码 将不会 很快 被发布如果有的话这让我与idTech3Quake III尚未被审查。也许如果有足够的人有兴趣我会写一些关于它的内容。注释