Unity3D:动态裁切显隐

适用于优化模型,对模型动态裁切。目前没有动态LOD。只是显隐。方法如下。

主要用到3个东西

  1. 包围盒
  2. 相关矩阵
  3. 像素阈值
    public void StartDynamicCulling()
    {
        var bounds = GetComponent<collider>().BoundingBox;
        CornerPosVec = new Vector4[]
        {
            new Vector4(bounds.max.x,bounds.max.y,bounds.max.z,1),
            new Vector4(bounds.max.x,bounds.min.y,bounds.max.z,1),
            new Vector4(bounds.max.x,bounds.min.y,bounds.min.z,1),
            new Vector4(bounds.max.x,bounds.max.y,bounds.min.z,1),
            new Vector4(bounds.min.x,bounds.min.y,bounds.min.z,1),
            new Vector4(bounds.min.x,bounds.min.y,bounds.max.z,1),
            new Vector4(bounds.min.x,bounds.max.y,bounds.max.z,1),
            new Vector4(bounds.min.x,bounds.max.y,bounds.min.z,1)
        };
        _cornerCameraPosVecByTrans = new Vector4[CornerPosVec.Length];
        _cornerProjecionPosVecByTrans = new Vector4[CornerPosVec.Length];
        _slefMeshRenderer = GetComponent<MeshRenderer>();
        //InvokeRepeating("DynamicOcclusionCulling", 1, 3);

        StartCoroutine(DynamicOcclusionCulling());
    }
    public static bool IsVisibleFromCameraView(this Renderer render, Camera camera)
    {
        Plane[] planes = GeometryUtility.CalculateFrustumPlanes(camera);
        return GeometryUtility.TestPlanesAABB(planes, render.bounds);
    }    
    private IEnumerator DynamicOcclusionCulling()
    {
        do
        {
            //先判断是否在视锥体里
            if (!GetComponent<Renderer>().IsVisibleFromCameraView(Camera.main))
            {
                GetComponent<Renderer>().enabled = false;
            }
            else
            {
                //转到camera视角
                for (int i = 0; i < CornerPosVec.Length; i++)
                {
                    _cornerCameraPosVecByTrans[i] = Vector4ByMatrix(Camera.main.worldToCameraMatrix, CornerPosVec[i]);
                }
                for (int i = 0; i < CornerPosVec.Length; i++)
                {
                    _cornerProjecionPosVecByTrans[i] = Vector4ByMatrix(Camera.main.projectionMatrix, _cornerCameraPosVecByTrans[i]);
                }
                double min0 = double.MaxValue, min1 = double.MaxValue;
                double max0 = double.MinValue, max1 = double.MinValue;
                for (int i = 0; i < 8; i++)
                {
                    var ndcX = _cornerProjecionPosVecByTrans[i].x / _cornerProjecionPosVecByTrans[i].w;
                    var ndcY = _cornerProjecionPosVecByTrans[i].y / _cornerProjecionPosVecByTrans[i].w;
                    if (ndcX < min0) min0 = ndcX;
                    if (ndcY < min1) min1 = ndcY;
                    if (ndcX < max0) max0 = ndcX;
                    if (ndcY < max1) max1 = ndcY;
                }
                var xPixel = max0 - min0;
                var yPixel = max1 - min1;
                xPixel *= Screen.width;
                yPixel *= Screen.height;
                var threshold = 32;
                if (xPixel <= threshold || yPixel <= threshold)
                {
                    _slefMeshRenderer.enabled = false;
                }
                else
                {
                    _slefMeshRenderer.enabled = true;
                }
            }
            yield return new WaitForSeconds(2);
        } while (true);

    }

基本逻辑是这样。有更好想法欢迎提出。

You May Also Like

About the Author: 大腿Plus

发表评论