【LOD】

LOD(Level of Detail,层次细节) 是优化3D模型渲染性能的核心技术,LOD 的核心思想:物体在屏幕上占用像素少时,用更低精度的模型(或直接不渲染)以节省 CPU/GPU/内存开销;在接近摄像机时用高精度模型以保证画质

通常最高等级是LOD0,随后可以依次是LOD1、LOD2、LOD3、LOD4,一般0~4共五个等级基本够用

(在理解上,可以认为不同LOD等级是不同的模型,只是形状相似,必要时也可以不相似)

不同LOD等级的区别在于模型三角面数,三角面少有利于提高渲染性能

通常会先做出LOD0的高精模型,通过一些减面技术(建模软件会内置)得到其余等级的模型

此外,也可能需要为不同模型准备不同的材质或贴图

LOD的核心在于切换策略,最简单的策略是:物体与摄像机的距离

在Unity中使用LODGroup组件可以实现LOD切换,其以“屏幕相对高度”(screen relative height)为依据,其是物体包围球(或包围盒)的投影大小与屏幕高度的比值

每个 LOD 有一个阈值(Inspector 中为滑条),当物体在屏幕上的相对高度小于该阈值时,会切换到下一个 LOD

 注意,切换是每帧基于当前渲染相机计算的,因此多摄像机场景下不同摄像机可能看到不同的 LOD

【使用】

LODGroup使用struct LOD来记录不同等级LOD的数据,核心是两个数据:

  • public float screenRelativeTransitionHeight;//屏占比
  • public Renderer[] renderers;//渲染器

通过SetLODs接口设置LODGroup所管理的LOD,设置为空意味着删除

SetLODs(List<LOD> lodList, int index, int count, bool updateBoundsByLOD0)

可以根据游戏策略给不同角色设置不同的LOD等级

通过GetLODs可以获取当前设置的LOD

通过ForceLOD(int index)强制显示某个等级的LOD,停止自动切。传入-1时再开启自动切换

localReferencePoint 是 LODGroup 用来做距离 / 屏幕覆盖计算的“基准点”,以 LODGroup 的本地坐标(local space)表示

Unity 在选择某个 LOD 时,会把这个本地点变换到世界空间(transform.TransformPoint(localReferencePoint)),然后以相机到该世界点的距离(与屏幕覆盖计算相关)来决定应该显示哪个 LOD

默认情形下,这个点通常是基于模型/渲染器的中心计算出来的(或者为 (0,0,0)),可以在 Inspector 或脚本中手动设置它

如果模型的几何中心与 Transform 的 pivot 有较大偏移,或者模型由多个分散的 renderers 组成,默认参考点可能并不是期望的“视觉中心”。这会导致 LOD 提前或延后切换。修改 localReferencePoint 可以把“测距点”移动到比 pivot 更合理的位置(例如角色的胸口、对象几何中心、摄像机更常接近的部分等)例如:

  • 一个长长的物体(火车、有长杆子的模型),pivot 在一端:把参考点移到模型中部/中心,可以避免摄像机接近另一端时仍然使用远距离 LOD
  • 多个 renderer 分散布局(树群、复杂道具):把参考点设为所有 renderer 的包围盒中心
  • 想让某个部分先显示高模:把参考点移动到该部分靠近相机的一侧

QualitySettings.lodBias会影响全局LOD缩放判定

Unity 在决定使用哪个 LOD 时会比较物体的屏幕相对高度(objectScreenSize)与每级 LOD 的阈值。实际比较时会把 objectScreenSize 乘以 QualitySettings.lodBias:effectiveSize = objectScreenSize * QualitySettings.lodBias然后用 effectiveSize 与各 LOD 的 screenRelativeTransitionHeight 比较

 lodBias > 1:把物体看得更“大”,高精度 LOD 会在更远处保留(更晚降级 → 更好画质,但性能开销更高)

lodBias < 1:把物体看得更“小”,更早降级到低精度 LOD(性能更好但画质下降)

建议保持为正数(通常 0.5、1、2 等),避免设置为 0 或负数

在性能/画质需要平衡时通过 QualitySettings.lodBias 调整整体 LOD 行为,而无需单独改每个模型的阈值

【切换方式】

一般来说,切换都会涉及平滑的问题,硬切在视觉上会导致抖动。

LODGroup提供CrossFade和SpeedTree两种平滑切换方式

CrossFade的实现是通过同时渲染两个 LOD,并调整它们的透明度来平滑过渡,其通过确切的时间做后置切换,通过LODGroup.crossFadeAnimationDuration设置切换时间

也可以禁用时间切换,通过设置LOD的Fade Transition Width做自定义切换

但 CrossFade的切换方式会增加额外的渲染开销,移动端慎用

如果是SpeedTree制作的模型,SpeedTree 几何体存储每个顶点的下一个 LOD 位置,每个顶点都知道如何在当前 LOD 位置与下一个 LOD 位置之间进行插值,过渡会交给 SpeedTree 的着色器/运行时处理。这种方式用的不多。

更进一步的来说,我们可以根据游戏的特点综合更多的因素,自己动态切换LOD。这些因素包括:距离、视角、转速、屏幕像素占比等

【HLOD简介】

普通 LOD(LODGroup)通常是单个对象按距离切换几组网格,关注单体细节。

HLOD(Hierarchical Level Of Detail,分层细节层级),把多个对象当成一个整体来做 LOD,解决的是 draw call、材质切换和大范围场景的整体开销,而不仅仅是单个模型的三角数。

通常先分层Hierarchy,把场景划分成树状层级(小组 → 更大组 → ...),每个层级都有自己的 LOD(高细节到低细节)。

然后聚合Clustering,在某一层级把多个独立网格合并成一个或少数几个代理网格,以减少 draw call 和批次开销,同时不同层级的代理可以有更简化的贴图、材质,可以做材质贴图的合并

HLOD的切换策略和LODGroup大体相似,由于是针对多组对象的,HLOD的使用相比原来会降低内存。但可能也会导致多余的物体Mesh被加载而增大内存。

通常可用于以下静态场景:

  • 开放世界/大地图:城市、山地、植被密集地区,将远处建筑/树群合并为代理
  • 视距外的复杂物体群:群集小物件(石堆、杂物)在远处用单一代理替换

【参考】

https://docs.unity3d.com/cn/2023.2/Manual/class-LODGroup.html

Logo

这里是一个专注于游戏开发的社区,我们致力于为广大游戏爱好者提供一个良好的学习和交流平台。我们的专区包含了各大流行引擎的技术博文,涵盖了从入门到进阶的各个阶段,无论你是初学者还是资深开发者,都能在这里找到适合自己的内容。除此之外,我们还会不定期举办游戏开发相关的活动,让大家更好地交流互动。加入我们,一起探索游戏开发的奥秘吧!

更多推荐