Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Tilemap outline issue

Discussion in '2D' started by ktest112233, Mar 20, 2019.

  1. ktest112233

    ktest112233

    Joined:
    Jan 7, 2019
    Posts:
    37
    Hi,

    I am making a platformer game which has a bunch of platforms. I am adding outline to the map by using a shader but having the following issue:

    When the tile asset size is equal to that of the GRID TILE SIZE, the outlines only show up on edges.

    I believe that somehow the texture that the Tile renderer generates is being clipped. The outlines appear on the edge because there is some empty space..


    When the tile size is smaller than the GRID TILE SIZE, the outlines show up.



    Does anyone have a suggestion? I am using the following shader
    Code (CSharp):
    1. Shader "Sprites/Outline"
    2. {
    3.     Properties
    4.     {
    5.         [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
    6.         _Color ("Tint", Color) = (1,1,1,1)
    7.         [MaterialToggle] PixelSnap ("Pixel snap", Float) = 0
    8.         [HideInInspector] _RendererColor ("RendererColor", Color) = (1,1,1,1)
    9.         [HideInInspector] _Flip ("Flip", Vector) = (1,1,1,1)
    10.         [PerRendererData] _AlphaTex ("External Alpha", 2D) = "white" {}
    11.         [PerRendererData] _EnableExternalAlpha ("Enable External Alpha", Float) = 0
    12.  
    13.         // Add values to determine if outlining is enabled and outline color.
    14.         [PerRendererData] _Outline("Outline", Float) = 0
    15.         [PerRendererData] _OutlineColor("Outline Color", Color) = (1,1,1,1)
    16.         [PerRendererData] _OutlineSize("Outline Size", int) = 1
    17.     }
    18.  
    19.     SubShader
    20.     {
    21.         Tags
    22.         {
    23.             "Queue"="Transparent"
    24.             "IgnoreProjector"="True"
    25.             "RenderType"="Transparent"
    26.             "PreviewType"="Plane"
    27.             "CanUseSpriteAtlas"="True"
    28.         }
    29.  
    30.         Cull Off
    31.         Lighting Off
    32.         ZWrite Off
    33.         Blend One OneMinusSrcAlpha
    34.  
    35.         Pass
    36.         {
    37.         CGPROGRAM
    38.             #pragma vertex SpriteVert
    39.             #pragma fragment frag
    40.             #pragma target 2.0
    41.             #pragma multi_compile_instancing
    42.             #pragma multi_compile _ PIXELSNAP_ON
    43.             #pragma multi_compile _ ETC1_EXTERNAL_ALPHA
    44.             #include "UnitySprites.cginc"
    45.  
    46.             float _Outline;
    47.             fixed4 _OutlineColor;
    48.             int _OutlineSize;
    49.             float4 _MainTex_TexelSize;
    50.  
    51.             fixed4 frag(v2f IN) : SV_Target
    52.             {
    53.                 fixed4 c = SampleSpriteTexture(IN.texcoord) * IN.color;
    54.  
    55.                 // If outline is enabled and there is a pixel, try to draw an outline.
    56.                 if (_Outline > 0 && c.a != 0) {
    57.                     float totalAlpha = 1.0;
    58.  
    59.                     [unroll(16)]
    60.                     for (int i = 1; i < _OutlineSize + 1; i++) {
    61.                         fixed4 pixelUp = tex2D(_MainTex, IN.texcoord + fixed2(0, i * _MainTex_TexelSize.y));
    62.                         fixed4 pixelDown = tex2D(_MainTex, IN.texcoord - fixed2(0,i *  _MainTex_TexelSize.y));
    63.                         fixed4 pixelRight = tex2D(_MainTex, IN.texcoord + fixed2(i * _MainTex_TexelSize.x, 0));
    64.                         fixed4 pixelLeft = tex2D(_MainTex, IN.texcoord - fixed2(i * _MainTex_TexelSize.x, 0));
    65.  
    66.                         totalAlpha = totalAlpha * pixelUp.a * pixelDown.a * pixelRight.a * pixelLeft.a;
    67.                     }
    68.  
    69.                     if (totalAlpha == 0) {
    70.                         c.rgba = fixed4(1, 1, 1, 1) * _OutlineColor;
    71.                     }
    72.                 }
    73.  
    74.                 c.rgb *= c.a;
    75.  
    76.                 return c;
    77.             }
    78.         ENDCG
    79.         }
    80.     }
    81. }
    82.  
     
  2. Le-nain

    Le-nain

    Joined:
    Nov 26, 2012
    Posts:
    62
    Hello,
    Sorry to see no-one has been able to help you... that's sadly often the case regarding Tilemaps AFAIK...
    Alas I can't help you either, as you seem to have more knowledge than me regarding this topic.

    I'm here to ask you about something I noticed in your shader: I see you're using [PerRendererData] on a shader intended for Tilemaps. How does that work?
    I mean, I know how to use it when I have a renderer (e.g. SpriteRenderer) per object, and I can pass my MaterialPropertyBlock with my data for this specific object. But would you happen to know if there's a way to use [PerRendererData] with Tiles, so that I can pass some data specific to each tile (just like they do for _MainTex) ?

    In case you want some context, I'm trying to do some masking on my tiles, and would like to find a way to pass a mask texture specific to each individual tile to be able to access it from the frag.

    Thanks in advance.
     
  3. ktest112233

    ktest112233

    Joined:
    Jan 7, 2019
    Posts:
    37
    Hi, honestly I just picked up an online shader and tried modify it. I am afraid I can't help you out since I don't have much shader knowledge
     
  4. Le-nain

    Le-nain

    Joined:
    Nov 26, 2012
    Posts:
    62
    Haha then I'm outta luck.
    Thanks anyways.
     
  5. ChuanXin

    ChuanXin

    Unity Technologies

    Joined:
    Apr 7, 2015
    Posts:
    1,068
    This is not possible on a per Tile basis for the TilemapRenderer as each Tile is grouped by its main texture, unless each Tile happens to have its own texture.

    If your masking details can be specific for textures (as Tiles can share the same textures), you can check out Unity 2019.2 Secondary Textures (https://docs.unity3d.com/Manual/SpriteEditor-SecondaryTextures.html) and associate your mask texture by the main texture instead.
     
  6. Le-nain

    Le-nain

    Joined:
    Nov 26, 2012
    Posts:
    62
    Thanks for the answer!
    Coincidentally I'm actually currently in the process of trying this new secondary texture feature in 19.2, and that indeed looks like an interesting thing!
    I did try it with normal maps and it seems to be working fine with Tilemap, so now I'm gonna try with my mask + my custom shader instead but it should work just like the normal map, which would be wonderful.

    The only problem I've found so far with that feature is that apparently it breaks when I try atlasing the sprites... or did I do something wrong? Because unfortunately if that's the case I'm afraid it's still a no-go, as I definitely want to keep my atlases for performance reasons.
     
  7. ChuanXin

    ChuanXin

    Unity Technologies

    Joined:
    Apr 7, 2015
    Posts:
    1,068
    Right now, using the Sprite Packer/Sprite Atlas with Sprites with secondary textures will not work, but that will be updated in the future.

    As a workaround, you could manually layout all the Sprites in their textures (main and secondary) such that the UV matches for this situation, but that would be cumbersome in a development workflow not set up for this.
     
  8. Le-nain

    Le-nain

    Joined:
    Nov 26, 2012
    Posts:
    62
    Exactly. To be fair, I could actually already do that without secondary textures to fix my original issue for Tilemaps and use my custom masks, but it being too annoying in our pipeline was already what made me try to find alternatives.

    Not asking for an actual precise ETA and I understand fully that whatever you answer, this will be fully "off the record" and not binding at all but... do you have a vague idea of when I could potentially expect that to be supported?
    I just wabt to be able to wrap my head around whether I can potentially hope for it being available at some point during my current project's development cycle or if I'd better completely drop the idea.