【Unity Shader】UI特效在RawImage上使用运行良好,但是在Image上则不是预期效果的问题

20 篇文章 1 订阅
4 篇文章 2 订阅

疑惑

        在最开始用shader做UI特效的时候,或多或少会遇到这样的问题,就是用RawImage能得到预期效果,而用Image很有可能就得不到预期效果,关键原因还是UV的差异引起的.

简单说下RawImage和Image的差异:

他们是从MaskableGraphic派生出来的两个不同的分支,他俩并没有继承关系.

 游戏中应该跟多的会使用到Image,因为他是用的图集思想,可以达到自动合批的效果,性能是优于RawImage的,而能达到自动合批,那么他得有相同的材质球,比如两个Image分别显示同一个图集中的不同Sprite,那么他们的材质球中的贴图则就是整张图集(在FrameDebugger中可查看),而达到显示不同的Sprite则是通过Image网格中顶点的UV值来指定的,而RawImage则不是图集思想,就是单张纹理直接显示,他的网格顶点中的UV值就是正常的[0~1].

通常情况下做UI特效,内部算法要么直接对颜色值进行处理,要么就是用UV值做变化因子进行一些操作.而用UV值参与计算的shader就很有可能在Image上使用效果达不到预期的问题,因为内部的算法基本上都是视为UV的区间是0~1,那么处理的结果就可以想象是对整张图集进行处理,而当前这个Image就仅仅是取其中一小块,当然效果就很难达到预期.

PS:如果内部想用模型坐标来计算,那么更不靠谱,因为对合批的网格去取他的模型坐标本身就是离大谱的事儿.

解决办法

Image的网格里的UV值不是不在[0,1]区间吗.那么可以在使用uv值做变换之前,将他重新映射的到预期的[0,1]区间,那么后续的计算就能达到我们的预期效果.而在映射之前就得拿到当前Image上显示的Sprite在图集中uv值范围.

CPU端获取Sprite在图集中uv值范围代码:

    Vector4 GetSpriteUVRange(Image image){
        Sprite sp = image.sprite;
        Vector2[] uv = sp.uv;
        //四个分量值的含义  x:uMin  y:uMax  z:vMin  w:vMax
        Vector4 uvRange = new Vector4(1,0,1,0);
        for (int i = 0; i < uv.Length; i++)
        {
            Vector2 tempUV = uv[i];
            uvRange.x = Mathf.Min(uvRange.x, tempUV.x);
            uvRange.y = Mathf.Max(uvRange.y, tempUV.x);
            uvRange.z = Mathf.Min(uvRange.z, tempUV.y);
            uvRange.w = Mathf.Max(uvRange.w, tempUV.y);
        }

        return uvRange;
    }

将上面获取到的uv范围传入到Shader中,uv映射伪代码如下:

//这里的lerp其实不需要, 第三个参数计算的结果就是在[0,1]区间
//只是为了传达更常用的映射关系,比如像映射到1~3,那么吧前面的0,1 改为 1,3即可.
uv.x = lerp(0,1, (uv.x - uMin)/(uMax - uMin));
uv.y = lerp(0,1, (uv.y - vMin)/(vMax - vMin));

注意:uv映射不要影响到正常的纹理采样了,需要在纹理采样结束后再进行映射.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值