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冲突的对象移得更远.
透明度排序
在 Godot 中,透明材质是在不透明材质之后绘制的。透明对象在绘制之前会从后向前排序,排序依据是该 Node3D 的位置,而不是世界空间中顶点的位置。因此, 互相有重叠的对象可能会出现排序错误的情况。要修复排序不当的对象,可以调整材质的 渲染优先级 属性,或节点的 排序偏置 属性。渲染优先级将强制特定材质出现在其他透明材质的前面或后面,而排序偏置将向前或向后移动对象以进行排序。即便如此,这可能也并不总是能解决问题。
一些渲染引擎会使用顺序无关的透明技术来缓解这个问题,但这类技术对于 GPU 而言开销很大。Godot 目前没有提供这个功能,但仍然有几种方法可以避免这个问题:
只有在你真正需要的时候才让材质透明。如果一种材质只有一个很小的透明部分,请考虑将它分割成一个单独的材质。这将允许不透明部分投射阴影,也可以提高性能。
如果你的纹理大部分都是完全不透明和完全透明的区域,则可以使用 Alpha 测试而不是 Alpha 混合。这种透明模式渲染速度更快,并且不会出现透明度问题。在 StandardMaterial3D 中启用 Transparency > Transparency 至 Alpha 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 Dither 或 Object Dither 来代替 PixelAlpha ,这将使材质不透明,还可以加快渲染速度。
多采样抗锯齿
参见
抗锯齿在 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),它的速度非常慢。通常仅建议将其用于离线渲染。