zoukankan      html  css  js  c++  java
  • NGUI Panel裁剪、层级实现原理

    1.NGUI渲染顺序。
    上面的文章详细的分析了unity中camera depth -> sorting layer -> sorting order -> RenderQueue  -> Z等属性是如何影响渲染的,大家有疑问可以参考这篇文章。
    在NGUI中,层级主要是通过sorting order 和 RenderQueue实现的。
    源码如下,NGUI默认使用RenderQueue设置显示层级,这里的renderQueue是根据panel+widget的depth递增(+1)得出来的。
    for (int i = 0; i < drawCalls.Count; ++i)
          {
             UIDrawCall dc = drawCalls[i];
     
             dc.renderQueue = (renderQueue == RenderQueue.Explicit) ? startingRenderQueue : startingRenderQueue + i;
             dc.alwaysOnScreen = alwaysOnScreen &&
                (mClipping == UIDrawCall.Clipping.None || mClipping == UIDrawCall.Clipping.ConstrainButDontClip);
             dc.sortingOrder = useSortingOrder ? ((mSortingOrder == 0 && renderQueue == RenderQueue.Automatic) ? sortOrder : mSortingOrder) : 0;
             dc.sortingLayerName = useSortingOrder ? mSortingLayerName : null;
             dc.clipTexture = mClipTexture;
          } 
    2.NGUI裁剪。
    UIPanel的裁剪主要是通过名字为Hidden/Unlit/Transparent Colored x的shader实现的,x小等于3
    看不懂这个shader的可以参考https://gameinstitute.qq.com/community/detail/128082
    3.简单实现NGUI的层级和裁剪功能。
    1.生成两个mesh,设置不同的depth和贴图,便于显示层级关系。
    与上一篇的区别在于设置了NGUI用于裁剪shader,以及mRenderer.sortingOrder和裁剪属性。
    public class NguiObjTest: MonoBehaviour
    {
        private Texture mMeshMatTex;
        private MeshFilter mFilter;
        private MeshRenderer mRenderer;
        private Material mDynamicMat;
        private Vector4 drawingDimensions = new Vector4(0, 0, 200, 400);
        private int mDepth = 0;
        private NguiTest mTest;
        
        //颜色测试
        Color mColor = Color.grey; 
        Color mGradientTop = Color.green; 
        Color mGradientBottom = Color.red;
     
        public void Create(Texture tex, int depth, NguiTest panel) {
            //transform.localScale = Vector3.one * 0.2f;
            transform.localPosition = new Vector3(depth*20, depth*20 , 0);
            mMeshMatTex = tex;
            mDepth = depth;
            mTest = panel;
     
            CreateMesh();
            SetMeshRender();
        }
     
        private void CreateMesh() {
            Vector3[] newVertices;
            Vector2[] newUV;
            GetUITextureVertices(out newVertices, out newUV);
     
            int indexCount = (newVertices.Length >> 1) * 3; //四个顶点构成两个三角形,共2*3 = 6个顶点
            int[] newTriangles = new int[indexCount];
            int index = 0;
            
            for (int i = 0; i < newVertices.Length; i += 4)
            {
                newTriangles[index++] = i;
                newTriangles[index++] = i + 1;
                newTriangles[index++] = i + 2;
     
                newTriangles[index++] = i + 2;
                newTriangles[index++] = i + 3;
                newTriangles[index++] = i;
            }
            
            if (mFilter == null) mFilter = gameObject.GetComponent<MeshFilter>();
            if (mFilter == null) mFilter = gameObject.AddComponent<MeshFilter>();
            
            Mesh mesh = new Mesh();
            mesh.hideFlags = HideFlags.DontSave;
     
            // Do some calculations...
            mesh.vertices = newVertices;
            mesh.uv = newUV;
            mesh.triangles = newTriangles;
            mesh.SetColors(SetColor());
            mesh.name = "NGUI Test";
            mFilter.mesh = mesh;
        }
     
        /// <summary>
        /// 显示一个Texture,顶点数4
        /// </summary>
        /// <param name="vert"></param>
        /// <param name="uvs"></param>
        private void GetUITextureVertices(out Vector3[] vert, out Vector2[] uvs) {
            Vector4 v = drawingDimensions;
            vert = new []{new Vector3(v.x,v.y), new Vector3(v.x,v.w),
                new Vector3(v.z,v.w),new Vector3(v.z,v.y), };
            uvs = new []{new Vector2(0,0), new Vector2(0,1),new Vector2(1,1),new Vector2(1,0), };
        }
     
        /// <summary>
        /// 通过Hidden/Unlit/Transparent Colored 1 shader实现裁剪。_ClipRange0裁剪区域,虚边_ClipArgs0(边缘渐隐效果)
        /// mDynamicMat.renderQueuemRenderer.sortingOrder都可以修改显示层级
        /// </summary>
        private void SetMeshRender() 
        {
            if (mRenderer == null) mRenderer = gameObject.GetComponent<MeshRenderer>();
            if (mRenderer == null) mRenderer = gameObject.AddComponent<MeshRenderer>();
            
            Shader shader = Shader.Find("Hidden/Unlit/Transparent Colored 1");
            mDynamicMat = new Material(shader);
            mDynamicMat.name = "[NGUI] " + shader.name;
            mDynamicMat.mainTexture = mMeshMatTex;
     
            Vector4 cr = mTest.ClipRange;
            Vector4 soft = mTest.ClipSoftness;
            float angle = 0f;
            
            angle *= -Mathf.Deg2Rad;
     
            Vector2 sharpness = new Vector2(1000.0f, 1000.0f);
            if (soft.x > 0f) sharpness.x = cr.z / soft.x;
            if (soft.y > 0f) sharpness.y = cr.w / soft.y;
     
            mDynamicMat.SetVector(Shader.PropertyToID("_ClipRange0"), 
                new Vector4(-cr.x / cr.z, -cr.y / cr.w, 1f / cr.z, 1f / cr.w));
            mDynamicMat.SetVector(Shader.PropertyToID("_ClipArgs0"), 
                new Vector4(sharpness.x, sharpness.y, Mathf.Sin(angle), Mathf.Cos(angle)));
     
            //mDynamicMat.renderQueue = 3000 + mDepth;
            mRenderer.sortingOrder = mDepth; //层级
            mRenderer.sharedMaterials = new Material[] { mDynamicMat };
        }
     
        /// <summary>
        /// 颜色设置,参考UIBasicSprite.AddVertexColours
        /// 每个顶点对应一个颜色值,通过mesh.SetColors传给mesh做显示
        /// </summary>
        public List<Color> SetColor() 
        {
            List<Color> col = new List<Color>();
            col.Add(mColor * mGradientBottom);//0,0
            col.Add(mColor * mGradientTop);//0,1
            col.Add(mColor * mGradientTop);//1,1
            col.Add(mColor * mGradientBottom);//1,0
     
            return col;
        }
    }
    2.生成测试mesh。
    public class NguiTest: MonoBehaviour {
        public Vector4 mClipRange;
        public Vector4 mClipSoftness;
     
        public Texture mTop;
        public Texture mBottom;
        // Start is called before the first frame update
        void Start() {
            TestPanel();
        }
     
        /// <summary>
        /// 生成两个对象,传入不一样的depth和Texture
        /// 测试层级和裁剪区域
        /// </summary>
        private void TestPanel() 
        {
            GameObject bottom = new GameObject("Bottom");
            NguiObjTest ntBottom = bottom.AddComponent<NguiObjTest>();
            ntBottom.Create(mBottom, 1, this);
            
            GameObject top = new GameObject("Top");
            NguiObjTest ntTop = top.AddComponent<NguiObjTest>();
            ntTop.Create(mTop, 2, this);
        }
     
        public Vector4 ClipRange 
        {
            get {
                return mClipRange;
            }
        }
        
        public Vector4 ClipSoftness 
        {
            get {
                return mClipSoftness;
            }
        }
    }
    3.测试,基于上述代码实现NGUI的层级、裁剪、颜色功能。
    在界面上生成一个空对象并挂载NguiTest组件,设置如下属性,mClipRange是裁剪区域(世界坐标),mClipSoftness是便于的渐隐效果,mTop是显示在上层的图片。
    效果如下:这边加了NGUI的Gradient颜色渐变效果。
     
  • 相关阅读:
    Office 365开发环境概览
    Office 365开发概述及生态环境介绍(二)
    介绍Office 365 中文用户社区 4.0
    学习一点Markdown的基本知识
    Office 365开发概述及生态环境介绍(一)
    如何完全卸载OneDrive (Windows 10 64bit)
    国内版Office 365和Azure AAD绑定的问题及解决方案
    Office 365常见问题解答(第一期)
    招聘视音频工程师
    信念、思考、行动-谈谈程序员返回家乡的创业问题
  • 原文地址:https://www.cnblogs.com/wang-jin-fu/p/13508966.html
Copyright © 2011-2022 走看看