如何撰写一份提供优雅性能的3D引擎

如何撰写一份提供优雅性能的3D引擎

我对3D了解不多。 翻译的动机首先是对内容的兴奋,其次是为了练习英汉翻译技巧。 由于本人水平和经验有限,文章中肯定存在很多误解和误译。 也恳请读者指出,以便我们共同进步。

好文章必定是人人欣赏的,欢迎大家自由转载:)

介绍

我们来谈谈如何编写一个提供优雅性能的 3D 引擎。 您的引擎需要提供:曲面、动态光照、体积雾、镜子、门户、天空盒、顶点着色器、粒子系统、静态网格模型、动画网格模型。 如果您已经知道上述所有功能的工作原理,您也许可以将它们组合到一个引擎中。

ETC! 在开始编写代码之前,您必须首先考虑如何构建引擎。 大多数时候,你一定很渴望制作一款游戏,但如果你直接开始为你的引擎编写代码,你肯定会感到非常不舒服。 在开发后期,您可能需要添加新的特效和控件。 并且不得不多次重写大量本地代码,甚至最终因失败而放弃。 花时间仔细考虑引擎的问题将为您节省大量时间并减少麻烦。 你不会急于建造一个庞大的项目; 您可能会在引擎完成之前就放弃它并转向其他事情。 好吧,除非你学会了学习所需知识的方法,否则你可能无法完成这些事情。 完成设计确实是一件很美妙的事情3D角色,你会感觉更好,并且会因此而发光!

让我们分析一下功能齐全的 3D 游戏引擎所需的基本组件。 首先,这为具有 3D 经验但需要一些指导的开发人员提供了一些信息。 这里有一些内容并不难且快速掌握,但您必须应用。 为了让您的工作更轻松,这里概述了游戏引擎的工作量和部件数量。 我将这些组件称为系统、控制台、支持、渲染器/引擎核心、游戏界面和工具/数据。 。

工具/数据

在开发过程中,您总是需要一些数据,但不幸的是它并不像编写文本文件或定义立方体那么简单。 您至少需要一个 3D 模型编辑器、一个关卡编辑器和一个图形程序。 您可以购买它或在线查找一些免费程序来满足您的开发需求。 不幸的是,您可能还需要一些您根本无法访问的工具(它们还不存在),因此您必须自己编写它们。 您可能最终会设计和编写自己的关卡编辑器,因为您永远无法获得所需的东西。 您还可以编写一些代码来打包大量文件。 整天处理成百上千个文件是非常痛苦的。 您还必须编写一些转换器或插件来将 3D 模型编辑器的模型格式转换为您自己的格式。 您还需要用于处理游戏数据的工具,例如可见性估计或光照贴图。

一个基本的经验法则是,您可能希望在设计工具中放入与游戏本身一样多或更多的代码。 一开始你总是会找到现成的格式和工具,但随着时间的推移,你会意识到你需要引擎的大功能,并且你会放弃旧的写作方式。

也许使用第3方工具来辅助开发很流行,所以你必须时刻关注你的设计。 因为一旦你将你的引擎发布为opensouce或允许修改,那么也许有一天有人会应用你的开发成果,他们会扩展它或进行一些修改。

也许您还应该花与设计和编写游戏、工具和引擎一样多的时间来设计美术、关卡、音效音乐和物理模型。

系统

系统是发动机和机器本身之间进行通信和交互的组件。 当一个优秀的引擎准备移植到某个平台时,它的系统是唯一需要进行重大更改(代码扩展)的地方。 我们将一个系统分为几个子系统,包括:图形、输入、声音、定时器和配置。 主系统负责初始化、更新和关闭所有子系统。

游戏中的图形子系统非常直观。 如果你想在屏幕上画一些东西,它(图形子系统)就会做到。 大多数情况下,图形子系统是使用 OpenGL、Direct3D、Glide 或软件渲染来实现的。 如果更理想的话,你甚至可以支持这些API,然后抽象出一个“图形层”并将其放在实现API之上。 这会给客户开发者或者玩家更多的选择。 以获得最佳的兼容性和最佳的性能。

输入子系统(Input Sub-System)需要对来自各种输入设备(键盘、鼠标、游戏手柄[Gamepad]、游戏手柄[Joystick])的输入触发进行统一控制和接收处理。 (透明处理)例如,在游戏中,系统想要检测玩家的位置是否在向前移动。 与其直接单独检测每个输入设备,不如通过向输入子系统发送请求来获取输入信息,而输入子系统则在幕后做真正的工作(单独检测每个输入设备),所有这些对输入子系统都是透明的客户端开发人员。 用户和玩家可以非常自由地切换输入设备游戏素材下载 免费,并且很容易通过不同的输入设备获得统一的行为。

声音子系统(声音系统)负责加载和播放声音。 这个子系统的功能非常简单明了,但是目前很多游戏都支持3D声音,所以实现起来会稍微复杂一些。

3D游戏引擎中的许多出色表现都是基于“时间系统”(时间)。 所以你需要一些时间来思考一下时间子系统(Timer sub-system)。 即使很简单,一切(游戏中的)都是由时间触发来改变运动,但合理的设计会阻止你一遍又一遍地编写大量相同的控制代码来实现……

配置系统位于所有子系统的顶层。 它负责读取配置记录文件、命令行参数,或者修改设置(setup)。 所有子系统在初始化和操作期间都将保持与系统的通信。 切换图像分辨率、颜色深度、按键绑定、声音支持选项,甚至加载游戏,该系统使这些实现变得极其简单和方便。 将你的引擎设计得更加可配置将为调试和测试带来更大的便利; 玩家和用户还可以轻松选择他们喜欢的跑步方式。

安慰

哈! 我知道每个人都喜欢构建像 Quake 这样的控制台系统。 但这确实是个好主意。 通过命令行变量和函数,您可以在运行时更改游戏或引擎设置,而无需重新启动。 在开发过程中输出调试信息非常有用。 很多时候你需要测试一系列变量的值,而将这些值输出到控制台显然比运行调试器要快得多。 一旦在引擎运行时发现错误,您不必立即退出程序; 通过控制台,你可以做一些非常轻微的控制并打印出错误消息。 如果您不希望最终用户看到或使用控制台,您可以非常轻松地禁用它,我想没有人能够看到它。

支持

支持将在您的引擎中随处使用。 这个系统包括你引擎中的所有数学组件(点、面积、矩阵等)、(内部)存储管理器、文件加载器和数据容器(如果你不想自己编写,也可以使用STL )。 该模块的任务似乎非常基础且低级。 也许您会在其他相关项目中重用它。

Renderer/Engine Core(渲染/引擎核心)

哈~是的,每个人都喜欢3D图像渲染! 由于渲染 3D 世界的方式有很多种,因此几乎不可能概述以不同方式工作的各种 3D 图形管道。

无论你的渲染器如何工作,最重要的是使你的渲染器组件基于且干净。

首先可以确定的是,您将拥有不同的模块来完成不同的任务。 我将渲染器分为以下部分:可见性、碰撞检测和响应、相机(Camera)、静态几何体、动态几何体、粒子系统、Billboarding、网格、天空盒、照明、雾化)、节点着色(顶点着色)和输出(输出)。

这些部分中的每一个都需要一个接口来轻松更改设置、位置、方向以及可能与系统相关的其他属性配置。

将出现的主要陷阱之一是“功能膨胀”,这将取决于您想要在设计过程中实现哪些功能。 但如果你不把新的功能构建到引擎中游戏引擎原理及应用,你会发现一切都会变得更加困难,解决问题的方式也会特别差。

另一件有意义的事情是让所有三角形(或面)最终通过渲染管道中的同一点。 (不是每次都是每个三角形,我们谈论的是三角形列表、扇形、条带等)多花一点工作通过相同的光、雾等和阴影代码格式化所有对象,这样就很方便只需切换材质和纹理id,即可使任意多边形具有不同的渲染效果。

这不会损害大量渲染的点游戏引擎原理及应用,但如果您不小心,可能会导致大量冗余代码。

您最终可能会发现,实现您需要的所有炫酷效果可能只占用总代码的 15% 左右,甚至更少。 这当然是因为大多数游戏引擎不仅仅关注图形性能。

游戏界面(游戏媒体)

3D(游戏)引擎的一个非常重要的部分是它是一个游戏引擎。 但这不是游戏。 真正的游戏需要一些永远不应该包含在游戏引擎中的组件。 引擎和游戏制作之间的控制媒介可以让代码设计更清晰,应用起来更舒服。 虽然这是一些额外的代码,但它使游戏引擎非常可重用。 还可以通过设计支持游戏逻辑的脚本语言来让开发更加方便,并且游戏的代码也可以放在库中。 如果你想把你的游戏逻辑系统设计嵌入到引擎本身中,大量的问题和大量的修改肯定会让你放弃重用这个引擎的想法。

因此,此时你可能正在思考这个问题:连接引擎和游戏的媒体层到底提供了什么? 答案是控制。 引擎的几乎每个部分都具有动态属性,引擎/游戏层提供了修改这些动态属性的接口。 它们包括相机、模型属性、灯光、粒子系统物理、播放声音、播放音乐和处理输入。 、切换关卡(changeing level)、碰撞检测和响应(collision detector and response),以及顶部显示的2D图形界面、标题画面等相关的东西。 基本上,如果您希望您的游戏优雅地实现这些元素,则必须将此媒体层(界面)放置在引擎中。

游戏

在这里,我无法告诉您如何编写游戏。 轮到你炫耀了。 如果您为出色的引擎设计了一组出色的媒体层,我认为设计和编写游戏的过程会容易得多。

3D游戏引擎设计是一个庞大的软件工程。 一个人独立完成设计和写作不是不可能,但也不是一两个晚上就能完成的事情。 您可能会编写几兆字节的源代码。 如果你没有持久的信念和热情,你可能无法完成它。

当然,不要指望第一次尝试就能编写出完整的引擎。 选择实施较小项目所需的小型引擎。 按照你的方式努力工作,你就会取得成功。

文章来源:https://blog.csdn.net/gogor/article/details/6587906