Unity Lod和Occlusion Culling

Lod和Occlusion Culling

  • Lod和遮挡剔除。
      Occlusion Culling:Occlusion Culling 技术是指当一个物体被其他物体遮挡住而相对当前摄像机为不可见时,可以不对其进行渲染。遮挡剔除操作在Unity引擎中并不是自动进行的,这时因为在很多情况下离摄像机较远的物体先被渲染,而靠近摄像机的物体后被渲染,从而覆盖了先前渲染的物体(这被称为重复渲染overdraw)。遮挡剔除不同于视椎体剔除(Frustum Culling)视椎体剔除只是不渲染摄像机视椎范围之外的物体,而被其他物体遮挡但依然在视椎范围之内的物体则不会被剔除。(当使用遮挡剔除功能时,视椎体剔除依然有效)

遮挡剔除:在我们的场景中,如果物体1在Camera渲染中遮挡了另一个物体2,那物体2就不会再Camera中进行渲染,虽然物体2没有在Camera中进行渲染但是在整个游戏场景中这个物体同样存在。为了优化效率,这里就需要使用遮挡剔除。
  Lod: 如果一个物体离我们的Camera很远,我们自然就看不见这个物体(或者只能看见一个“小点”)。但是这个物体在场景中仍然会根据它的顶点结构进行渲染并消耗性能。这时候为了优化,如果它离我们的Camera距离很远,我们就不需要对它进行渲染,也就是Lod。

Occlusion Culling(遮挡剔除)

  • 遮挡剔除功能在Unity中使用Occlusion Culling(遮挡剔除)组件来进行实现

    • 首先我们需要对需要进行遮挡以及被遮挡的物体进行烘焙。
    • 在烘焙的时候,我们需要对遮挡的物体和被遮挡的物体进行选择不同的情况不同的解决方案。(比如一个玻璃物体遮挡住了另一个物体这时我们也应该对玻璃后的物体进行渲染)
    • 这里不考虑这种情况,直接进行烘焙。
Paste_Image.png
  • 烘焙完成以后,这里我们将Occlusion Culling的属性从Edit改为Visualize来查看效果。
Paste_Image.png
  • 这时无法再Camera中渲染出来的物体,在场景中也不会进行渲染。
遮挡剔除.gif

Lod

  • Lod功能,unity内置的组件也会为我们提供了一套解决方案。(LOD Group组件)
  • 首先我们先创建一个小球,可以看见camera已经距离很远,此时只能看见一个小点。但它仍然是场景中进行了渲染。
  • 实现LOD优化,为它添加LOD Group组件。


    Paste_Image.png
Paste_Image.png
Paste_Image.png
  • 其中LOD 0,LOD 1分别为Camera距离这个球的距离区域划分。
  • 我们可以在这些相对距离区域中选择是否要在这个距离对小球渲染。
Paste_Image.png
Paste_Image.png
  • 我们在需要对小球进行渲染的距离区域中添加小球的Mesh网格信息,这样在这个Camera到小球的距离内,场景就是对小球进行渲染。

  • 到我们拖到LOD 2的距离区域后段时,这时场景会认为小球在距离Camera这么远的距离时不需要对小球进行渲染了,则小球就没有被渲染。(只是取消了小球的渲染,并不是enable等于false,所以小球的网格信息仍然存在。)

Paste_Image.png
  • 这时如果你觉得这个距离小球还需要被渲染,你就通过Add为这个距离区域添加上小球的render。小球会被渲染出来。
Paste_Image.png
Paste_Image.png
  • 如果你对这些距离区域都不是你自己想要的,你同样可以对区域进行编辑并创建新的距离区域。
Paste_Image.png
Paste_Image.png
  • 运行游戏来观察效果,当小球具体我们Camera超过我们的渲染的距离区域时,小球就不会进行渲染。(尽管小球仍然在我们Camera的视野范围之内


    LOD.gif

以上方案的缺陷。

  • 以上完成的操作都是静态的物体,但是在我们的实际项目开发中,NPC,Monster,建筑物等都是动态生成的。这种情况肯定就无法烘焙成静态的。

动态解决方案。(LOD)

  • 这时我们使用脚本来控制。而LOD的核心也就是在距离远的时候将小球的MeshRender组件失活我们根据这个核心点去编写代码。

    • 为我们的Camera添加一个LODAndOcclusionController的脚本。
    • 完成简单的动态LOD功能。
Paste_Image.png
  • 场景测试。
    • 这时我们可以发现当Camera和小球的距离超过5米的时候,小球则不会进行渲染。小球是动态运动的也同样没有关系。


      动态LOD.gif
动态LOD2.gif

动态解决方案。(遮挡剔除)

  • 使用Ray射线来进行判断。
  • 我们将所有需要进行遮罩剔除的物体添加Tag为Occlusion。

  • 并为我们的Camera添加脚本。

Paste_Image.png
Occlusion.gif

总结:

我们的LOD以及Occlusion,都是基于GameObject的MeshRender组件来实现的。只有掌握好核心点,不让它们进行渲染,这样减少了Draw Call自然就优化了性能。(主要为什么是让MeshRender组件失活,因为我们直接把整个游戏对象都失活了,那所有的碰撞信息也全部都会失效。)

推薦閱讀更多精彩內容