3D 渲染的局限性

前言

出于对性能的要求,实时渲染引擎有很多局限性。Godot的渲染器也不例外。 为了更有效地工作,你需要了解这些局限性。

纹理尺寸限制

在台式机和笔记本电脑上,旧设备可能不支持大于 8192×8192 的纹理。你可以在 GPUinfo.org 上检查你的目标 GPU 的限制。

移动端 GPU 通常限制为 4096×4096 纹理。此外,某些移动端 GPU 不支持非 2 的幂大小的纹理的重复操作。因此,如果你想纹理在所有平台上都能正确显示,则应避免使用大于 4096×4096 的纹理,如果纹理需要重复,则大小应为 2 的幂。

要限制可能因为尺寸太大而无法渲染的特定纹理的大小,你可以将 Process > Size Limit 导入选项设置为大于 0 的值。 这将减少导入时纹理的尺寸(保留纵横比),而不影响源文件。

带状颜色

使用 Forward+ 或 Mobile 移动渲染方法时,Godot 的 3D 引擎在内部以 HDR 进行渲染。但是渲染输出会经过色调映射到低动态范围,以便在屏幕上显示。这可能会导致可见的条带效应,尤其是在使用无纹理的材质时。出于性能原因,使用 Mobile 移动渲染方法时颜色精度也比使用 Forward+ 时要低。

使用兼容性渲染方法时,不使用 HDR,并且颜色精度是所有渲染方法中最低的。这也适用于 2D 渲染,在 2D 渲染中,使用平滑渐变纹理时可以看到条带。

有两个主要的方法来缓解条带:

  • 如果使用 Forward+ 或 Forward 移动渲染方法,请在 项目设置 > 渲染 > 抗锯齿 中启用 Use Debanding 。 这会应用全屏去色带着色器作为后期处理效果,并且非常经济合算。

  • 或者,将一些噪点烘焙到纹理中。这主要在 2D 中有效,例如用于渐晕(vignetting)效果。在 3D 中,你还可以使用一个自定义去色带着色器应用于你的材质。即使你的项目以低颜色精度渲染,该技术也能发挥作用,这意味着它在使用移动端和兼容性渲染方法时也能发挥作用。

色彩带对比(增加对比度以提高可视性)

色彩带对比(增加对比度以提高可视性)

参见

参见 Banding in Games: A Noisy Rant (PDF) 获取更多有关条带效应的细节和解决方案。

深度缓冲精度

为了在 3D 空间中排序对象,渲染引擎使用了深度缓冲区(也称为 Z 缓冲区)。这个缓冲区具有有限的精度:在桌面平台上是 24 位,在移动平台上有时是 16 位(出于性能原因)。如果两个不同的对象最终具有相同的缓冲值,那么就会发生 Z 冲突(Z-fighting),此时移动或旋转相机,将观察到纹理来回闪烁。

为了使深度缓冲在渲染区域上更精确,你应该增加摄像机节点的 Near 属性。但是要小心,如果你设置得太高,玩家就会看穿附近的几何体。同时,还应该减少摄像机节点的 Far 属性到你用例允许的最低值,尽管它不会像 Near 属性那样影响精度。

如果你仅在玩家能够看得远时才需要高精度,则可以根据游戏条件动态更改它。例如,如果玩家进入飞机,则可以暂时增加 Near 属性以避免远处的 Z 冲突( Z-fighting)。然后,一旦玩家离开飞机,就可以减少它。

根据场景和玩家视野条件,你还可以在玩家不会看出差异的情况下将产生z冲突的对象移得更远。

Z 冲突对比(通过将 Label3D 从地板偏移来调整场景前后)

Z 冲突对比(通过将 Label3D 从地板偏移来调整场景前后)

透明度排序

在 Godot 中,透明材质是在不透明材质之后绘制的。透明对象在绘制之前会从后向前排序,排序依据是该 Node3D 的位置,而不是世界空间中顶点的位置。因此, 互相有重叠的对象可能会出现排序错误的情况。要修复排序不当的对象,可以调整材质的 渲染优先级 属性,或节点的 排序偏置 属性。渲染优先级将强制特定材质出现在其他透明材质的前面或后面,而排序偏置将向前或向后移动对象以进行排序。即便如此,这可能也并不总是能解决问题。

透明物体不会渲染到法线-粗糙度缓冲区 (normal-roughness buffer),因为它们是在不透明几何体之后绘制的。因此,依赖于法线-粗糙度缓冲区的特征不会影响透明材质。

一些渲染引擎会使用顺序无关的透明技术来缓解这个问题,但这类技术对于 GPU 而言开销很大。Godot 目前没有提供这个功能,但仍然有几种方法可以避免这个问题:

  • 只有在你真正需要的时候才让材质透明。如果一种材质只有一个很小的透明部分,请考虑将它分割成一个单独的材质。这将允许不透明部分投射阴影,也可以提高性能。

  • 如果你的纹理大部分都是完全不透明和完全透明的区域,则可以使用 Alpha 测试而不是 Alpha 混合。这种透明模式渲染速度更快,并且不会出现透明度问题。在 StandardMaterial3D 中启用 Transparency > TransparencyAlpha Scissor ,并根据需要相应调整 Transparency > Alpha Scissor Threshold 。请注意,除非在材质属性中启用了 alpha 抗锯齿,否则 MSAA 不会对纹理边缘进行抗锯齿。但是,无论材质上是否启用了 alpha 抗锯齿功能,FXAA、TAA 和超级采样都能够对纹理边缘进行抗锯齿处理。

  • 如果你需要渲染纹理上的半透明区域,Alpha Scissor 就不适用了。将 StandardMaterial3D 的 Transparency > Transparency 属性设置为 Depth Pre-Pass 有时会有作用(以性能为代价)。你还可以尝试 Alpha Hash 模式。

  • 如果你想让材质随着距离增加而淡出, 使用 StandardMaterial3D 的距离淡出模式(distance fade mode)的 Pixel DitherObject Dither 来代替 PixelAlpha ,这将使材质不透明,还可以加快渲染速度。

透明度排序对比(左侧为 alpha 混合材质,右侧为 alpha 裁剪材质)

透明度排序对比(左侧为 alpha 混合材质,右侧为 alpha 裁剪材质)