在uGUI正交相機中實現旋轉透視效果


正常uGUI使用正交相機的話,旋轉是沒有透視效果的,但如果能實現較簡單的透視,

對一些效果表現來說還是不錯的;見下圖(左為透視效果):

正常思路感覺各種麻煩。

因為uGUI使用unity的x和y方向表示寬高,z方向自然就是縱深,我們可以直接拿z值作為系數進行縮放處理,

達到偽透視的效果(美中不足,細看會有弧度感)。

 

但是,直接對z軸進行縮放會出現扭曲問題:

 

這種情況可以通過頂點細分來解決,一般細分一次即可。頂點越多,UV插值產生的扭曲影響就越小:

 

再擴展一下可支持Text組件:

 

 

最后上代碼:

namespace Hont
{
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.UI;

    [ExecuteInEditMode]
    public class UiPerspectiveFx : BaseMeshEffect
    {
        [Header("Only Image")]
        public int subdivision = 2;//有的材質細分2次,有的需3-4次。
        public float perspectiveScale = 1.0f;
        public bool alwaysRefresh = true;


        private void Update()
        {
            if (alwaysRefresh)
                graphic.SetVerticesDirty();
        }

        private void CalcPerspectiveScale(ref Vector3 point)
        {
            Vector3 wPos = transform.localToWorldMatrix.MultiplyPoint(point);
            float fixValue = wPos.z * perspectiveScale;
            point *= 1f + fixValue;
        }

        public override void ModifyMesh(VertexHelper vh)
        {
            RectTransform rectTransform = transform as RectTransform;

            if (graphic is Image)
            {
                vh.Clear();

                Vector2 begin = -rectTransform.sizeDelta * 0.5f;
                Vector2 cell = rectTransform.sizeDelta / subdivision;
                float uvCell = 1f / subdivision;
                for (int x = 0; x < subdivision; x++)//TODO:可進一步做緩存優化
                {
                    for (int y = 0; y < subdivision; y++)
                    {
                        Vector3 p0 = new Vector3(begin.x + cell.x * x, begin.y + cell.y * y);
                        Vector3 p1 = new Vector3(begin.x + cell.x * x, begin.y + cell.y * (y + 1));
                        Vector3 p2 = new Vector3(begin.x + cell.x * (x + 1), begin.y + cell.y * (y + 1));
                        Vector3 p3 = new Vector3(begin.x + cell.x * (x + 1), begin.y + cell.y * y);

                        Vector3 uv0 = new Vector3(x * uvCell, y * uvCell);
                        Vector3 uv1 = new Vector3(x * uvCell, (y + 1) * uvCell);
                        Vector3 uv2 = new Vector3((x + 1) * uvCell, (y + 1) * uvCell);
                        Vector3 uv3 = new Vector3((x + 1) * uvCell, y * uvCell);

                        CalcPerspectiveScale(ref p0);
                        CalcPerspectiveScale(ref p1);
                        CalcPerspectiveScale(ref p2);
                        CalcPerspectiveScale(ref p3);

                        vh.AddUIVertexQuad(new UIVertex[]
                        {
                        new UIVertex(){position=p0, color=graphic.color, uv0=uv0},
                        new UIVertex(){position=p1, color=graphic.color, uv0=uv1},
                        new UIVertex(){position=p2, color=graphic.color, uv0=uv2},
                        new UIVertex(){position=p3, color=graphic.color, uv0=uv3}
                        });
                    }
                }
            }
            else if (graphic is Text)
            {
                for (int i = 0, iMax = vh.currentVertCount; i < iMax; i++)
                {
                    UIVertex vertex = default;
                    vh.PopulateUIVertex(ref vertex, i);
                    CalcPerspectiveScale(ref vertex.position);
                    vh.SetUIVertex(vertex, i);
                }
            }
        }
    }
}

 

掛載到Image/Text組件下即可:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM