美文网首页搭建自己的Unity知识体系
Unity 字体二(三)颜色渐变

Unity 字体二(三)颜色渐变

作者: 会打马赛克的小老弟 | 来源:发表于2019-12-23 15:39 被阅读0次

    字体颜色渐变

    我们先看看二颜色渐变效果:


    二颜色渐变效果

    我们看看三颜色渐变效果:


    三颜色渐变效果

    左面Scene场景是网格状态。

    通过Scene场景我们可以看见,我们需要向中间插入两个点,做个顶点过渡。

    顶点部署应该是这样的:

         *  TL--------TR
         *  |          |
         *  |          |
         *  CL--------CR
         *  |          |
         *  |          |
         *  BL--------BR
    

    首先我们要知道,显示文本有个文本区域,而这个区域的坐标是基于局部坐标,所以我们要先转出到屏幕坐标,然后再换算。

    准备的变量和枚举:

    public enum GradientType
    {
        TowColor = 0,
        ThreeColor,
    }
        [SerializeField] private GradientType m_GradientType = GradientType.TowColor;
        [SerializeField] private Color32 m_TopColor = Color.white;
        [SerializeField] private Color32 m_MiddleColor = Color.white;
        [SerializeField] private Color32 m_BottomColor = Color.black;
        [Range(0f, 1f)] [SerializeField] private float m_ColorOffset = 0.5f;
        [SerializeField] private Camera m_UICamera;
        private List<UIVertex> iVertices = new List<UIVertex>();
    

    核心换算代码:

    vh.GetUIVertexStream(iVertices);
            vh.Clear();
    
    
            for (int i = 0; i < iVertices.Count; i += 6)
            {
    
                UIVertex TL = iVertices[i + 0];
                UIVertex TR = iVertices[i + 1];
                UIVertex CR = iVertices[i + 2];
                UIVertex CL = iVertices[i + 4];
                UIVertex BL = iVertices[i + 4];
                UIVertex BR = iVertices[i + 2];
    
                Vector2 uvTL = iVertices[i + 0].uv0;
                Vector2 uvTR = iVertices[i + 1].uv0;
                Vector2 uvBR = iVertices[i + 2].uv0;
                Vector2 uvBL = iVertices[i + 4].uv0;
    
                Vector3 TR_World_Pos = this.transform.TransformPoint(TR.position);
                Vector3 BR_World_Pos = this.transform.TransformPoint(BR.position);
                Vector3 TR_Screen_Pos = TR_World_Pos;
                Vector3 BR_Screen_Pos = BR_World_Pos;
                
                if (this.m_UICamera != null)
                {
                    TR_Screen_Pos = this.m_UICamera.WorldToScreenPoint(TR_World_Pos);
                    BR_Screen_Pos = this.m_UICamera.WorldToScreenPoint(BR_World_Pos);
                }
    
                float yHeight = (TR_Screen_Pos.y - BR_Screen_Pos.y) * this.m_ColorOffset;
                Vector2 C_Screen_Pos = new Vector2(TR_Screen_Pos.x, TR_Screen_Pos.y - yHeight);
    
                if (this.m_UICamera != null)
                {
                    C_Screen_Pos = this.m_UICamera.ScreenToWorldPoint(C_Screen_Pos);
                }
                CR.position = this.transform.InverseTransformPoint(C_Screen_Pos);
                CL.position.y = CR.position.y;
    
                CR.uv0.y = CR.uv0.y * this.m_ColorOffset;
                CL.uv0.y = CL.uv0.y * this.m_ColorOffset;
    
                TL.color = this.m_TopColor;
                TR.color = this.m_TopColor;
                CR.color = this.m_MiddleColor;
                CL.color = this.m_MiddleColor;
                BL.color = this.m_BottomColor;
                BR.color = this.m_BottomColor;
    
                vh.AddVert(TL);
                vh.AddVert(TR);
                vh.AddVert(CR);
                vh.AddVert(CL);
                vh.AddVert(BL);
                vh.AddVert(BR);
            }
    

    上面的代码意思就是先清理原始数据,然后把坐标转到屏幕坐标系上,需要经过两步 局部坐标 => 世界坐标 => 屏幕坐标,然后给y做某个点上距离缩放:

    屏幕坐标计算
    float yHeight = (TR_Screen_Pos.y - BR_Screen_Pos.y) * this.m_ColorOffset;在这个距离做个缩放,TR_Screen_Pos.y - yHeight 计算出来差值,就是我们需要的中点高度。(CR\CL的高度是一样的,计算一次即可,X值保留默认。)

    接下来添加三角面:

    
            for (int i = 0; i < vh.currentVertCount; i += 6)
            {
                if (this.m_GradientType == GradientType.ThreeColor)
                {
                    vh.AddTriangle(i + 0, i + 1, i + 2);
                    vh.AddTriangle(i + 2, i + 3, i + 0);
                    vh.AddTriangle(i + 3, i + 2, i + 5);
                    vh.AddTriangle(i + 5, i + 4, i + 3);
                }
                else
                {
                    vh.AddTriangle(i + 0, i + 1, i + 5);
                    vh.AddTriangle(i + 0, i + 5, i + 4);
                }
            }
    

    大致就是这些。

    补充,上面版本有些bug,核心算法做个优化:

    /*
             *  TL--------TR
             *  |          |
             *  |          |
             *  CL--------CR
             *  |          |
             *  |          |
             *  BL--------BR
             * **/
    
    
            for (int i = 0; i < count; i++)
            {
                UIVertex vertex = UIVertex.simpleVert;
                vh.PopulateUIVertex(ref vertex, i);
                this.iVertices.Add(vertex);
            }
            vh.Clear();
    
            for (int i = 0; i < this.iVertices.Count; i += 4)
            {
    
                UIVertex TL = this.GeneralUIVertex(this.iVertices[i + 0]);
                UIVertex TR = this.GeneralUIVertex(this.iVertices[i + 1]);
                UIVertex BR = this.GeneralUIVertex(this.iVertices[i + 2]);
                UIVertex BL = this.GeneralUIVertex(this.iVertices[i + 3]);
    
                TL.color = this.m_TopColor;
                TR.color = this.m_TopColor;
                BL.color = this.m_BottomColor;
                BR.color = this.m_BottomColor;
    
    
                vh.AddVert(TL);
                vh.AddVert(TR);
    
                if (this.m_GradientType == GradientType.ThreeColor)
                {
                    UIVertex CR = this.GeneralUIVertex(this.iVertices[i + 2]);
                    UIVertex CL = this.GeneralUIVertex(this.iVertices[i + 3]);
    
                    CR.position = (TR.position + BR.position) * this.m_ColorOffset;
                    CL.position = (TL.position + BL.position) * this.m_ColorOffset;
                    CR.uv0 = (TR.uv0 + BR.uv0) * this.m_ColorOffset;
                    CL.uv0 = (TL.uv0 + BL.uv0) * this.m_ColorOffset;
                    CR.color = this.m_MiddleColor;
                    CL.color = this.m_MiddleColor;
    
                    vh.AddVert(CR);
                    vh.AddVert(CL);
                }
    
                vh.AddVert(BR);
                vh.AddVert(BL);
            }
    
            int step = 4;
            if (this.m_GradientType == GradientType.ThreeColor)
            {
                step = 6;
            }
    
            for (int i = 0; i < vh.currentVertCount; i += step)
            {
                if (this.m_GradientType == GradientType.ThreeColor)
                {
                    vh.AddTriangle(i + 0, i + 1, i + 2);
                    vh.AddTriangle(i + 2, i + 3, i + 0);
                    vh.AddTriangle(i + 3, i + 2, i + 4);
                    vh.AddTriangle(i + 4, i + 5, i + 3);
                }
                else
                {
                    vh.AddTriangle(i + 0, i + 1, i + 2);
                    vh.AddTriangle(i + 2, i + 3, i + 0);
                }
            }
    
        private UIVertex GeneralUIVertex(UIVertex vertex)
        {
            UIVertex result     = UIVertex.simpleVert;
            result.normal       = new Vector3(vertex.normal.x, vertex.normal.y, vertex.normal.z);
            result.position     = new Vector3(vertex.position.x, vertex.position.y, vertex.position.z);
            result.tangent      = new Vector4(vertex.tangent.x, vertex.tangent.y, vertex.tangent.z, vertex.tangent.w);
            result.uv0          = new Vector2(vertex.uv0.x, vertex.uv0.y);
            result.uv1          = new Vector2(vertex.uv1.x, vertex.uv1.y);
            return result;
        }
    

    最终代码:

    using UnityEngine;
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine.UI;
    using System;
    
    public enum GradientType
    {
        TowColor = 0,
        ThreeColor,
    }
    
    /// <summary>
    /// 渐变字体
    /// </summary>
    public class Gradient : BaseMeshEffect
    {
        [SerializeField] private GradientType m_GradientType = GradientType.TowColor;
        [SerializeField] private Color32 m_TopColor = Color.white;
        [SerializeField] private Color32 m_MiddleColor = Color.white;
        [SerializeField] private Color32 m_BottomColor = Color.black;
        [Range(0f, 1f)] [SerializeField] private float m_ColorOffset = 0.5f;
        [SerializeField] private Camera m_UICamera;
        private List<UIVertex> iVertices = new List<UIVertex>();
    
        public override void ModifyMesh(VertexHelper vh)
        {
            this.iVertices.Clear();
    
            if (!IsActive())
            {
                return;
            }
    
            var count = vh.currentVertCount;
            if (count == 0)
                return;
    
            /*
             *  TL--------TR
             *  |          |
             *  |          |
             *  CL--------CR
             *  |          |
             *  |          |
             *  BL--------BR
             * **/
    
    
            for (int i = 0; i < count; i++)
            {
                UIVertex vertex = UIVertex.simpleVert;
                vh.PopulateUIVertex(ref vertex, i);
                this.iVertices.Add(vertex);
            }
            vh.Clear();
    
            for (int i = 0; i < this.iVertices.Count; i += 4)
            {
    
                UIVertex TL = this.GeneralUIVertex(this.iVertices[i + 0]);
                UIVertex TR = this.GeneralUIVertex(this.iVertices[i + 1]);
                UIVertex BR = this.GeneralUIVertex(this.iVertices[i + 2]);
                UIVertex BL = this.GeneralUIVertex(this.iVertices[i + 3]);
    
                TL.color = this.m_TopColor;
                TR.color = this.m_TopColor;
                BL.color = this.m_BottomColor;
                BR.color = this.m_BottomColor;
    
    
                vh.AddVert(TL);
                vh.AddVert(TR);
    
                if (this.m_GradientType == GradientType.ThreeColor)
                {
                    UIVertex CR = this.GeneralUIVertex(this.iVertices[i + 2]);
                    UIVertex CL = this.GeneralUIVertex(this.iVertices[i + 3]);
    
                    CR.position = (TR.position + BR.position) * this.m_ColorOffset;
                    CL.position = (TL.position + BL.position) * this.m_ColorOffset;
                    CR.uv0 = (TR.uv0 + BR.uv0) * this.m_ColorOffset;
                    CL.uv0 = (TL.uv0 + BL.uv0) * this.m_ColorOffset;
                    CR.color = this.m_MiddleColor;
                    CL.color = this.m_MiddleColor;
    
                    vh.AddVert(CR);
                    vh.AddVert(CL);
                }
    
                vh.AddVert(BR);
                vh.AddVert(BL);
            }
    
            int step = 4;
            if (this.m_GradientType == GradientType.ThreeColor)
            {
                step = 6;
            }
    
            for (int i = 0; i < vh.currentVertCount; i += step)
            {
                if (this.m_GradientType == GradientType.ThreeColor)
                {
                    vh.AddTriangle(i + 0, i + 1, i + 2);
                    vh.AddTriangle(i + 2, i + 3, i + 0);
                    vh.AddTriangle(i + 3, i + 2, i + 4);
                    vh.AddTriangle(i + 4, i + 5, i + 3);
                }
                else
                {
                    vh.AddTriangle(i + 0, i + 1, i + 2);
                    vh.AddTriangle(i + 2, i + 3, i + 0);
                }
            }
    
        }
    
        private UIVertex GeneralUIVertex(UIVertex vertex)
        {
            UIVertex result     = UIVertex.simpleVert;
            result.normal       = new Vector3(vertex.normal.x, vertex.normal.y, vertex.normal.z);
            result.position     = new Vector3(vertex.position.x, vertex.position.y, vertex.position.z);
            result.tangent      = new Vector4(vertex.tangent.x, vertex.tangent.y, vertex.tangent.z, vertex.tangent.w);
            result.uv0          = new Vector2(vertex.uv0.x, vertex.uv0.y);
            result.uv1          = new Vector2(vertex.uv1.x, vertex.uv1.y);
            return result;
        }
    }
    
    
    

    相关文章

      网友评论

        本文标题:Unity 字体二(三)颜色渐变

        本文链接:https://www.haomeiwen.com/subject/achfoctx.html