3D 渲染的局限性

参见

In addition to the limitations below, mobile platforms have even more limitations on 3D rendering compared to desktop platforms. See Mobile rendering limitations for more information.

前言

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

纹理尺寸限制

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

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

带状颜色

当使用GLES3或Vulkan渲染器时,Godot的3D引擎内部以高动态范围(HDR)进行渲染. 然而, 渲染输出将被色调映射(tonemmapped)到一个低动态范围, 以便它可以显示在屏幕上. 这可能导致可见的条带效应(banding), 特别是当使用未贴图的材质时. 在使用了具有平滑梯度的纹理的2D项目中也能看到这种效应.

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

  • 在项目设置中启用 Use Debanding。这将应用一个全屏 debanding 着色器作为后期处理效果,而且非常廉价。只有在使用 GLES3 或 Vulkan 渲染器时才支持全屏 debanding。它还需要在项目设置中启用 HDR(这是默认的)。

  • 或者,在你的纹理中烘焙一些噪声。这主要在2D中是有效的,例如用于虚化效果。在3D中,你也可以使用一个 自定义去噪着色器 来应用于你的 材质 。即使你的项目是用LDR渲染的,这种技术也是有效的,这意味着它在使用GLES2渲染器时也能发挥作用。

参见

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

深度缓冲精度

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

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

如果你只需要当玩家能够看到很远的地方时才提供高精度, 你可以根据游戏条件动态改变它. 例如, 如果玩家进入飞机, Near 属性可以暂时增加, 以避免远处的z冲突现象(z-fighting). 当玩家离开飞机时, 它便会被减少.

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

透明度排序

In Godot, transparent materials are drawn after opaque materials. Transparent objects are sorted back to front before being drawn based on the Spatial's position, not the vertex position in world space. Due to this, overlapping objects may often be sorted out of order. To fix improperly sorted objects, tweak the material's Render Priority property. This will force specific materials to appear in front or behind of other transparent materials. Even then, this may not always be sufficient.

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

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

  • If your texture mostly has fully opaque and fully transparent areas, you can use alpha testing instead of alpha blending. This transparency mode is faster to render and doesn't suffer from transparency issues. Enable Parameters > Use Alpha Scissor in SpatialMaterial, and adjust Alpha Scissor Threshold accordingly if needed. Note that MSAA will not anti-alias the texture's edges, but FXAA will.

  • If you need to render semi-transparent areas of the texture, alpha scissor isn't suitable. Instead, setting the SpatialMaterial's Parameters > Depth Draw Mode property to Opaque Pre-Pass can sometimes work (at a performance cost).

  • 如果你想让材质随着距离增加而褪色, 使用StandardMaterial3D距离褪色模式 Pixel DitherObject Dither 来代替 PixelAlpha , 这将使材质不透明, 它也可以投射阴影.

多采样抗锯齿

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

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

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

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

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

  • 为了使镜面反射锯齿不那么明显,请打开项目设置,并启用 Rendering > Quality > Screen Space Filters > Screen Space Roughness Limiter。这个滤波器对性能有一定影响,只有当您确实需要它时, 才应该启用。

  • 除了(或代替)MSAA之外, 启用FXAA.FXAA是一个屏幕空间的抗锯齿方法, 因此它将平滑一切事物. 缺点是它会使场景显得模糊, 特别是在分辨率低于1440p的时候.

  • 以更高的分辨率渲染场景,然后在与窗口大小匹配的 ViewportTexture 中显示它。确保在 ViewportTexture 的标记中启用 Filter。这种技术叫做超采样,非常慢。通常只推荐在离线渲染时使用。