zoukankan      html  css  js  c++  java
  • [UGUI]TiledSliceEffect----Image的Tiled类型产生过多顶点的优化

    如下图,当Image Type设置成Tile时会产生过多顶点。


     

    解决方法是用一个shader,把sprite的uv范围和tile步长传进去,在shader里用求余的方法处理。

    首先在canvas的Additional Shader Channels上勾选:

    以下是图片分成九宫格后,Image Type为Sliced的一个解决方案:

    新建一个TileSliceEffect脚本,继承BaseMeshEffect,下面要在ModifyMesh中添加代码。

    当图片分成九宫格后,排列顺序如下:

          

    四个角只缩放不tile,四个边只进行横向或纵向的tile,中间横向纵向都要tile。

    每个九宫格又分成两个三角形一共六个点,顺序如下(与在atlas中的方向有关):

     

    对于每个格中的六个点,取顶点范围:

    var rectBorder = verts[6 * i + 4].position - verts[6 * i + 1].position;
    rectBorder = new Vector3(Mathf.Abs(rectBorder.x), Mathf.Abs(rectBorder.y), Mathf.Abs(rectBorder.z));

    而在sprite中,原始格子的范围是:

    var overrideSprite = m_image.overrideSprite;
    var border = overrideSprite.border;
    var spriteSize = overrideSprite.rect.size;
    float tileWidth = (spriteSize.x - border.x - border.z) / m_image.pixelsPerUnit;
    float tileHeight = (spriteSize.y - border.y - border.w) / m_image.pixelsPerUnit;

    从这里可以得到一个tile的缩放比例,比如x轴方向缩放比例为(此处当image大小小于一个tile时为缩放效果,大于一个tile时为平铺效果):

    uv1.x = ((tileWidth == 0 || tileWidth >= rectBorder.x) ? 1f : tileWidth / rectBorder.x);

    接下来还需要得到每个格子的uv范围:

    var leftTopUV = verts[6 * i + 1].uv0;
    var rightBottomUV = verts[6 * i + 4].uv0;

    最后,要把这些信息传入shader。

     vert.uv2 = new Vector2 (leftTopUV.x, leftTopUV.y);
     vert.uv3 = new Vector2 (rightBottomUV.x, rightBottomUV.y);

    shader是从builtin的DefaultUI基础上改的:

                struct appdata_t {
                    float4 vertex:POSITION; 
                    float4 color:COLOR; 
                    float2 texcoord:TEXCOORD0; 
                    float2 tile:TEXCOORD1; 
              float2 lt:TEXCOORD2;
              float2 rb:TEXCOORD3; };
    struct v2f { float4 vertex:SV_POSITION; fixed4 color:COLOR; half4 texcoord:TEXCOORD0; half4 border:TEXCOORD1; float4 worldPosition:TEXCOORD2; };

    在vs中,把参数分开里把两个参数分开:

    OUT.texcoord.xy = IN.texcoord;
    OUT.texcoord.zw = IN.tile;
    OUT.border.xy = IN.lb;
    OUT.border.zw = IN.rt;

    fs中,对图片进行tile:

    IN.texcoord.x = lerp(IN.texcoord.x, saturate(IN.border.x + fmod((IN.texcoord.x - IN.border.x) * IN.texcoord.z, IN.border.z - IN.border.x)), step(0, IN.texcoord.z)); 
    IN.texcoord.y = lerp(IN.texcoord.y, saturate(IN.border.y + fmod((IN.texcoord.y - IN.border.y) * IN.texcoord.w, IN.border.w - IN.border.y)), step(0, IN.texcoord.w)); 

    这样就完成了基于slice类型的tile实现,效果如下:

    除了九宫格不会再增加任何顶点。

    也可以实现如下效果(边缘缩放,中间tile):

  • 相关阅读:
    NYOJ 35
    TOJ 3072
    HDU 1075
    POJ 1028
    TOJ 1153
    TOJ 1036
    POJ 1521
    POJ 3253
    NYOJ 467
    HDU 1671
  • 原文地址:https://www.cnblogs.com/drashnane/p/6361437.html
Copyright © 2011-2022 走看看