[Unity/UI]使用更多的顶点信息与图集uv映射

      好久没有写新的文章了,最近一直沉迷FF14(绝神兵好难啊(:з」∠))。最近踩了一个新的坑,怕过几天自己又忘记了所以要赶紧写下来提醒自己~。
      我们在制作UI功能的时候,有时候会需要一些额外的效果,为了性能考虑,有的时候我们会使用shader进行UI效果的优化。P.S.这里贴一篇大佬的优化文章,这个我看了好久,里面的代码有点奇怪,但是思路真的很有用!!! Unity手游开发札记——使用Shader进行UGUI的优化
      然后我们有的时候要使用一些额外的贴图进行采样,然后采样要使用到uv值,当我们使用单张的图片是没有问题的,但是一旦我们使用了图集,这个时候UI中获取到的uv值就不是标准的[0-1]范围的uv值了,而是基于图集中的图片位置计算出的uv值。这也是Unity的UI究竟为什么可以合批的原因。
      但是我们要对其他贴图(这张贴图没有被打进图集,当然打进图集也可以,但是要做一些额外操作,比如把这张图片的uv值也存在顶点信息中)采样时需要一个标准的[0-1]范围的uv,这个时候我们就要借助C#端进行图集的映射了。
      通过DataUtility类中的GetOuterUV函数,我们可以获取到图片在图集中的uv值,然后借助BaseMeshEffect中的ModifyMesh函数,我们可以拿到传给shader之前的顶点数据。然后我们就可以给shader传递更多我们自己定义的参数啦。

    public override void ModifyMesh(VertexHelper vh)
    {
        if (!IsActive())
            return;
        if (img==null)
        {
            img = GetComponent<Image>();
        }
        if(img.sprite==null)
            return;
        outerUv = DataUtility.GetOuterUV(img.sprite);
        UIVertex vert = new UIVertex();
        for (int i = 0; i < vh.currentVertCount; i++)
        {
            vh.PopulateUIVertex(ref vert, i);
            vert.uv1 = Caluv1(vert.uv0);
            vh.SetUIVertex(vert, i);
        }
    }
    private Vector2 Caluv1(Vector2 uv0)
    {
        uv0.x = uv0.x - outerUv.x > 0 ? 1 : 0;
        uv0.y = uv0.y - outerUv.y > 0 ? 1 : 0;
        return uv0;
    }

      这里我直接使用了顶点的uv0数据,因为uv数据理论上与我使用GetOuterUV函数获取到的uv值是相同的,所以我只计算了左下角坐标,直接把uv1的值设置到了[0-1]范围。
      然后还要在shader中添加对应的uv1值接收,要在a2v结构中添加TEXCOORD1属性,当然v2f结构中也要有对应的存储结构(下面的代码是直接从UI-Defalut中copy来的,只有//add的两行是我加的QAQ):

            struct appdata_t
            {
                float4 vertex   : POSITION;
                float4 color    : COLOR;
                float2 texcoord : TEXCOORD0;
                float2 texcoord1 : TEXCOORD1;//add
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            struct v2f
            {
                float4 vertex   : SV_POSITION;
                fixed4 color    : COLOR;
                float2 texcoord  : TEXCOORD0;
                float4 worldPosition : TEXCOORD1;
                float2 texcoord1  : TEXCOORD2;//add
                UNITY_VERTEX_OUTPUT_STEREO
            };

            v2f vert(appdata_t v)
            {
                v2f OUT;
                UNITY_SETUP_INSTANCE_ID(v);
                UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
                OUT.worldPosition = v.vertex;
                OUT.vertex = UnityObjectToClipPos(OUT.worldPosition);

                OUT.texcoord = v.texcoord;
                OUT.texcoord1 = v.texcoord1;
                OUT.color = v.color * _Color;
                return OUT;
            }

      当我以为这样就大功告成的时候,我发现自己高兴的实在是太早了,因为在测试的时候不管怎么样,我的texcoord1都像是没办法从C#端传入shader一样。而且当我直接输出uv1的值的时候,发现uv1的值还会因为物体的X坐标不同而变化。。。。经过两个多小时的百度,我终于找到了这篇文章Unity3D UGUI 源码学习 BaseMeshEffect
      原来一切的罪魁祸首竟然是canvas,因为canvans不允许我们使用除了uv0以外更多的顶点信息,所以我们填充的uv1信息也就完全没有作用了。

canvans设置额外信息

      设置完canvans之后,我的uv1值终于可以顺利传入shader啦!不多说了,FF14启动!

      补充:

      因为我之前的理解是Image的范围就是顶点的绘制范围,那么对应的uv也应该是处于[0-1]的范围内。但是后来在测试时发现并不是所有图片的uv值都在[0-1]的范围内。
      当我们使用的图片周围有一些空白像素时,Unity内部会帮我们做一个优化,直接舍弃掉多余的像素。


举个栗子

      就拿上一张图来说,这张图的大小是256*256,但是图片的周围有很多无用的像素,没有填充任何信息,这个时候我们在ModifyMesh函数中获取到的顶点uv值就不是一个[0-1]范围内的值了,而是一个Unity优化过的uv值。
      就在我好奇为什么uv不是[0-1]范围时还可以绘制出正常的图像时,我打开了线框模式...才发现原来在绘制顶点的时候根本就不是根据Image范围来绘制顶点的,而是像文字一样,只绘制有效像素范围:


Image与线框

      图中白色范围是Image组件范围,黑色范围是实际顶点所绘制的线框,上面的图片周围的无用像素已经被unity优化掉了,如果这种图片我们还用上面的算法把uv映射到[0-1]的范围,那么在使用这套uv采样的过程中就会出现错误的结果!(但是uv0是正确的,我暂时做了一个开关可以判断是否使用uv1,如果后面有更好的解决方法也会在这里补充)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,245评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,749评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,960评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,575评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,668评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,670评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,664评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,422评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,864评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,178评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,340评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,015评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,646评论 3 323
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,265评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,494评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,261评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,206评论 2 352

推荐阅读更多精彩内容