Unity Occlusion Culling 遮挡剔除研究
本文章由cartzhang编写,转载请注明出处。 所有权利保留。  
文章链接:http://blog.csdn.net/cartzhang/article/details/52684127  
作者:cartzhang
一、unity裁剪包括,视锥裁剪和遮挡裁剪。
什么是视锥体裁剪? 
我们来直接看下官方的图解,看图说话。 
场景中的对象: 
https://docs.unity3d.com/uploads/Main/OcclusionNoCulling.png 
 
 
视锥体的裁剪: 
https://docs.unity3d.com/uploads/Main/OcclusionFrustumCulling.png 
 
 
 
那什么是遮挡裁剪呢? 
https://docs.unity3d.com/uploads/Main/OcclusionFullCulling.png 
 
 
一图胜千言,这就是遮挡裁剪。 
要说的是,之前的此功能必须是pro版本才有的,现在使用的5.4.0f3版本是有的。 
遮挡裁剪的原理:通过在场景中使用一个虚拟的摄像机来创建一个物体潜在可视性状态(set)的层级. 这些数据可以让每个运行时间内的摄像机来确定什么能看见什么看不见。通过这些数据, Unity 将确定只把可以看见的物体送去渲染. 
使用二叉树进行处理,通过判断是否在相机中可以看到来,把看到的送去渲染。 
当然还可以通过划定一个盒子来确定裁剪空间,更多细节请自行参考官方。 
要说的是:当你使用遮挡剔除时你依然使用视锥体剔除,他们是并行不悖的。 
 
本来有同事,是关于怎么判断对象是否在相机内渲染。 
这个想来简单,找到对象的render,然后判断Renderer.isvisiable即可。 
这时候发现,他说这个没有卵用。那我就自己试试了。 
先写了个扩展方法:
public static class RendererExtensions
{
    public static bool IsVisibleFrom(this Renderer renderer, Camera camera)
    {
        Plane[] planes = GeometryUtility.CalculateFrustumPlanes(camera);
        return GeometryUtility.TestPlanesAABB(planes, renderer.bounds);
    }
}但是这个方法很明显只判断是否在视锥平头体内,不判断是否可见。 
那问题就在于遮挡裁剪啊,那看官方也琢磨了很久,一开始总是做不好。下面就是个记录历程,希望对看本文的你有所帮助。 
来吧,实践是检验真理的唯一标准啊。
二、首先搭建一个简单场景。
 
注意:要把所有的cube转换为静态的,static. 
 其中有个小红色块是有代码的。 
脚本如下:
public class IsRenderByCamera : MonoBehaviour
{
    private Renderer rend;
    // Use this for initialization
    void Start ()
    {
        rend = this.GetComponent<Renderer>();
    }
    // Update is called once per frame
    void Update ()
    {
        //if (rend.IsVisibleFrom(Camera.main))
        //{
        //    Debug.Log("visible by main camera");
        //}
        //else
        //{
        //    Debug.Log("not visible by any camera");
        //}
        //if (rend.IsVisibleFrom(Camera.main)) Debug.Log("Visible");
        //else Debug.Log("Not visible");
        if (rend.isVisible)
        {
            Debug.LogError("red cube is Visible");
        }
        else
        {
            Debug.LogError("red cube not Visible"); ;
        }
        if (Camera.main.useOcclusionCulling)
        {
            Debug.Log("currrent occluson is using");
        }
    }
    void OnWillRenderObject()
    {
        //Debug.Log("will render ");
    }
    void OnBecameVisible()
    {
        //Debug.Log("became Visible");
    }
    void OnBecameInvisible()
    {
        //Debug.Log("became InVisible");
    }
}直接构建操作如下: 
 
   下面就不多说了,直接构建啊。 
构建完毕,看到如下结果: 
 
发现没有,坐标轴位置就是相机位置,注意有什么特点。 
在场景中直接拽动相机到大的遮挡版之前,发现没有发生任何所想的,所有对象依旧在渲染啊。 
三、这是怎么回事。
查找了各种资料和尝试,相机在大遮挡板之前,遮挡在其后的小块没有一个消失不渲染的。而相机进入到蓝色盒子里面的时候,就可以发现有小块依次的不渲染。 
 
这个就简单了、 
所以,在相机的后面添加了一个cube,记得也修改为静态的。构建后如下图: 
结果呢: 
 
真的可以,大功告成啊。
四、是不是全部都需要为静态的呢?
怎么办,继续测试实验啊。
实验一、
就把相机背后点,还有做边界的小块做为静态,其他都非静态。 
当然结果很明显了。没有遮挡版,无法实现遮挡裁剪。
实验二、
将大白板该为静态。 
 
可以实现对大白板后面对象的遮挡裁剪。 
 
而超越之后就没有效果了。 
五、注意:
1.若在unity编辑器中没有选中Occlusion,在场景中拖拽相机,并不会出现效果。这个很怀疑是bug. 
顺便说下,测试版本为5.4.0f3。 
2.还有就是必须在Visulize模型下才可以正常使用。 
 
而在Edit模式下,不进行遮挡裁剪。 
 
所以,怀疑Unity的版本只在编辑器下才有效果。写代码就是为打包测试、
六、打包测试
结果是打包后遮挡裁剪是正常的。可以使用。哈哈,嫌疑排除,自己想多了。 
但是怀疑精神还要有的。对吧? 
本来是判断对象是否在相机内渲染做处理的,误入歧途,做了这些工作,分享出来,自己做个记录,以飨读者。
七、工程地址:
Github:https://github.com/cartzhang/OcclusionCullingTest
参考:
https://docs.unity3d.com/Manual/OcclusionCulling.html 
http://bbs.9ria.com/thread-216913-1-1.html
——————THE————————————————END——————– 
 
若有问题,请随时联系!!! 
非常感谢!!!
Unity Occlusion Culling 遮挡剔除研究的更多相关文章
- Occlusion Culling遮挡剔除理解设置和地形优化应用
		这里使用的是unity5.5版本 具体解释网上都有,就不多说了,这里主要说明怎么使用,以及参数设置和实际注意点 在大场景地形的优化上,但也不是随便烘焙就能降低帧率的,必须结合实际情况来考虑,当然还有透 ... 
- Unity性能优化-遮挡剔除
		1. Occlusion Culling-遮挡剔除的含义:没有在Camear视野范围内的游戏物体不进行渲染Render(默认情况下,Unity是会渲染所有GameObject,无论Camear是否看得 ... 
- Unity4.3 遮挡剔除:基本知识
		http://blogs.unity3d.com/2013/12/02/occlusion-culling-in-unity-4-3-the-basics/ 这篇博文由Umbra Software的J ... 
- 遮挡剔除 Occlusion Culling(转)
		一.首先介绍下draw call(这个东西越少你的游戏跑的越快): 在游戏中每一个被展示的独立的部分都被放在了一个特别的包中,我们称之为“描绘指令”(draw call),然后这个包传递到3D部分在屏 ... 
- Unity3D-游戏场景优化之遮挡剔除(Occlusion Culling)的使用
		在大型3D游戏场景中,如何优化游戏性能是非常重要的一步.一般遮挡剔除是非常常用的.接下来我们看看如何使用遮挡剔除. 假设这是一个游戏场景. 下面这是相机的视口,相机的视觉是看不到很大立方体后面的那些小 ... 
- unity 的视锥剔除和遮挡剔除
		Regular frustum culling only renders objects within the camera’s view. This is automatic and always ... 
- Occlusion Culling
		遮挡剔除 http://www.bjbkws.com/online/1092/ unity遮挡剔除(应用) http://www.unitymanual.com/thread-37302-1-1.ht ... 
- [WebGL入门]十九,遮挡剔除和深度測试
		注:文章译自http://wgld.org/,原作者杉本雅広(doxas),文章中假设有我的额外说明,我会加上[lufy:],另外.鄙人webgl研究还不够深入,一些专业词语,假设翻译有误.欢迎大家指 ... 
- Hierarchical Z-Buffer Occlusion Culling
		While I was at GDC I had the pleasure of attending the Rendering with Conviction talk by Stephen Hil ... 
随机推荐
- libmysqlclient.so.16未找到方法
			用mysql命令登录的时候报错: [root@iZ www]# mysql -uroot -p mysql: error while loading shared libraries: libmysq ... 
- mysql> set sql_mode='';  mysql> set sql_mode='traditional';
			mysql> set sql_mode=''; mysql> set sql_mode='traditional'; 
- ownCloud-9.1.1 (Ubuntu 16.04)
			平台: Ubuntu 类型: 虚拟机镜像 软件包: owncloud-9.1.1 commercial content management open-source owncloud storage ... 
- Moodle-3.1.2 (Ubuntu 16.04 )
			平台: Ubuntu 类型: 虚拟机镜像 软件包: moodle-3.1.2 commercial education moodle open-source 服务优惠价: 按服务商许可协议 云服务器费 ... 
- manjaro安装后你需要做的配置
			1.切换中国源 sudo gedit /etc/pacman-mirrors.conf 如果提示没有gedit , 则执行命令 : sudo pacman -S gedit 修改如下地方为中国: On ... 
- C#对bat脚本文件的操作示例
			实现C#操作bat脚本文件 using System;using System.Collections.Generic;using System.ComponentModel;using System ... 
- 从C++起步到MFC实战VC++软件工程师高端培训 视频保存在 播音员的网盘中
			从C++起步到MFC实战VC++软件工程师高端培训(服务器端开发方向)[共332课时]视频保存在 播音员的网盘中http://www.it1352.com/VideoTutorial/Details? ... 
- Leetcode back(215) to be continue
			solution discussion https://leetcode.com/problems/kth-largest-element-in-an-array/description/ -- 21 ... 
- css隐藏元素
			在CSS中,让元素隐藏(指屏幕范围内肉眼不可见)的方法很多,有的占据空间,有的不占据空间:有的可以响应点击,有的不能响应点击.下面一个个列出,选一个适合你的 { display: none; /* 不 ... 
- 多线程, Thread类,Runnable接口
			多线程 线程:线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程.一个进程中是可以有多个线程的,这个应用程序也可以称之为多线程程序. 单线程程序:即,若有多个任务只能依次执 ... 
