Attention: Here be dragons

This is the latest (unstable) version of this documentation, which may document features not available in or compatible with released stable versions of Godot.

3D 渲染的局限性

前言

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

纹理尺寸限制

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

移动端GPU通常仅支持小于4096×4096的纹理. 此外, 一些移动端GPU不支持对非二的幂次大小的纹理进行重复(repeat)操作. 因此, 如果你想让你的纹理在所有平台上正确显示, 你应该避免使用比4096×4096大的纹理, 如果纹理需要重复, 应该使用两倍的大小.

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

带状颜色

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

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

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

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

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

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

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

参见

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

一些渲染引擎会使用顺序无关的透明技术来缓解这个问题,但这类技术对于 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 裁剪材质)

多采样抗锯齿

参见

抗锯齿在 3D 抗锯齿 页面上有详细解释。

多重样本抗锯齿(MSAA)指的是在渲染对象时在多边形的边上取多个覆盖样本(coverage samples), 但它不会增加用于渲染场景的颜色样本数量. 下面是它在实践中的作用和局限性:

  • 网格的边缘将被很好地平滑(就像超采样一样).

  • 使用alpha测试(1位透明度)的透明材质无法被平滑.

  • 镜面反射锯齿问题(即出现在反射表面上的“火花”(sparkle))无法解决。

有几种方法可以解决这一限制, 这取决于你的绩效预算:

  • 为了使镜面反射锯齿不那么明显,请打开项目设置,开启高级设置,然后启用 渲染 > 抗锯齿 > 屏幕空间粗糙度限制器。这个滤波器令渲染性能付出一些代价,只有当你确实需要它时才应该启用。

  • 除了(或代替)MSAA 之外,还可以启用快速近似抗锯齿 (FXAA)。由于 FXAA 是一种屏幕空间抗锯齿方法,因此它可以平滑任何内容。 而 FXAA 的缺点时会使场景显得更加模糊,尤其是在分辨率低于 1440p 的情况下。 此外,FXAA 还缺乏时间信息,这意味着它对镜面反射锯齿的影响有限。

  • 除了(或代替)MSAA 之外,还可以启用临时抗锯齿 (TAA)。由于 TAA 是一种屏幕空间抗锯齿方法,因此它可以平滑任何内容。而 TAA 的缺点是,它会使场景显得更加模糊,尤其是在分辨率低于 1440p 的情况下。与 FXAA 相比,TAA 可以提供卓越的质量,并且可以有效地对抗镜面反射锯齿。然而,与 FXAA 相比,TAA 的性能成本更高,并且 TAA 会在快速移动时引入重影伪像。

  • 通过将项目设置中 缩放 3D > 缩放 设置增加到 1.0 以上,就可以以更高分辨率渲染场景。这种技术称为超采样抗锯齿 (SSAA),它的速度非常慢。通常仅建议将其用于离线渲染。