3D 游戏如何在没有每个角度的 sprite 的情况下渲染对象?

How can a 3D game render an object without having a sprite for every single angle?

在学习编写简单的 2D 游戏时,每个对象都会有一个精灵 sheet,其中包含玩家在每个 frame/animation 中的样子的小图片。 3D 模型似乎无法以这种方式工作,否则我们需要一张图像来显示对象的每个可能视图!

例如,一个旋转的立方体需要大量图像来描绘它在每一面的外观。所以我的问题是,当从任意角度观看时,3D 模型 "images" 是如何由引擎表示和渲染的?

在带有 sprite 表的 2D 世界中,您正在根据演员的状态(对象的视觉表示)绘制其中一个 sprite。在 3D 世界中,您正在为您的演员渲染一个模型,该模型是一系列多边形和映射到它的纹理。有标准化的模型文件(我最熟悉的是 Autodesk 3DS Max),其中模型和指定的纹理可以打包在一起(.3DS 或 .MAX 文件),提供图形库渲染对象及其对象所需的一切纹理。

简而言之,您不需要为 3D 对象的每个视图使用图像,您有一个模型,上面渲染了纹理,创建了由图形库渲染的动态视图。

多种方法

有多种渲染和存储 3D 图形和模型的方法。甚至还有不同的方法来渲染 2D 图形!除了 2D 位图,您还有 SVG。 SVG 使用数字来定义图像中的点。这些点构成形状。这些点也可以定义曲线。这使您无需像素即可制作图像。结果可以是更小的文件大小,此外还可以在不造成失真的情况下转换图像(缩放和旋转)。大多数 3D 图形都使用类似的技术,但 3D 除外。然而,这些方法的共同点是它们最终都将数据呈现为二维像素网格。

投影

渲染 3D 模型最常用的方法是 projection. All of the shapes to be rendered are broken down into triangles 在渲染之前。为什么是三角形?因为保证三角形是共面的。这为渲染器节省了大量工作,因为它不必担心“在线外着色”。这样做的一个缺点是大多数 3D 图形投影技术不支持完美的球体或其他圆形表面。您必须使用近似值和其他技巧来制作圆形表面(尽管有些渲染器支持圆形表面)。下一步是将所有 3D 点转换或投影 为屏幕上的 2D 点(如下所示)。

从那里开始,您实际上是在三角形中“着色”,使所有内容看起来都很立体。虽然这非常快,但另一个缺点是您不能真正拥有诸如反射和折射之类的东西。任何时候你在游戏中看到折射或反射表面,他们只是在使用技巧使它看起来像反射或折射 material。照明和阴影也是如此。

这是一个使用特殊着色使球体近似看起来平滑的示例。请注意,您仍然可以看到平滑版本周围的直线:

光线追踪

您还可以使用 ray tracing 渲染多边形。使用这种方法,您基本上可以追踪光线到达相机的路径。这使您可以进行逼真的反射和折射。但是,我不会详细介绍,因为目前在游戏中实际使用它太慢了。它主要用于 3D 动画(就像 Pixar 制作的那样)。具有低质量设置的简单场景可以很快进行光线追踪。但对于复杂、逼真的场景,渲染一帧可能需要几个小时(皮克斯电影就是这种情况)。但是,它确实会产生超逼真的图像:

光线投射

Ray casting不要与上述光线追踪相混淆。光线投射不会 追踪 光路。这意味着您只有平坦的表面;不反光。它也不会产生逼真的光线。然而,这可以相对快速地完成,因为在大多数情况下,您甚至不需要为每个像素投射光线。这是用于早期游戏(例如 Doom 和 Wolfenstein 3D)的方法。在早期的游戏中,光线投射用于地图,角色和其他物品使用始终面向相机的 2D 精灵进行渲染。这些精灵是从几个不同的角度绘制的,使它们看起来像 3D。这是 Wolfenstein 3D 的图片:


带有 JavaScript 和 HTML5 Canvas 的德军总部:图片来自 Martin Kliehm

存储数据

可以使用多种方法存储 3D 数据。它不一定取决于所使用的渲染方法。存储的数据本身没有任何意义,因此您必须使用已经提到的方法之一来呈现它。

多边形

这类似于 SVG。这也是存储模型数据的最常用方法。您使用 3D 点定义几何。这些点可以具有其他属性,例如纹理数据(以 UV 贴图的形式)、颜色数据以及您可能需要的任何其他属性。

可以使用多种文件格式存储数据。常用的文件格式是 COLLADA,这是一个 XML 文件,用于存储 3D 数据。不过还有 lot 其他格式。然而,从根本上说,所有文件格式仍然存储 3D 数据。

这是一个多边形模型的例子:

体素

这个方法很简单。您可以将 voxel models 想象成位图,只是它们是一堆位图叠加在一起以制作 3D 位图。所以你有一个 3D 像素网格。渲染体素的一种方法是将体素点转换为 3D 立方体。但是请注意,体素不必呈现为立方体。像像素一样,它们只是可能具有可以用不同方式解释的颜色数据的点。我不会详细介绍,因为这不是 too 常见的,并且您通常使用多边形方法渲染体素(就像将它们渲染为立方体时一样。这是体素的示例型号:


图片来自维基百科用户 Vossman