Search Unity

2D Sprite Shader texcoord problem

Discussion in 'Shaders' started by GarlicDipping, Sep 25, 2016.

  1. GarlicDipping

    GarlicDipping

    Joined:
    Sep 7, 2013
    Posts:
    33
    Hi, Recently I downloaded & modified some shader codes for 2D Sprite Outline shader - which is from this tutorial : http://nielson.io/2016/04/2d-sprite-outlines-in-unity/
    (In Short, shader from this tutorial treats a pixel as an outline pixel when neighboring pixel is transparent.)


    I added some codes for this shader, because I trimmed every transparent pixels around my sprite resources, and for that original shader doesn't work properly :



    ...Like this.

    So after I modified frag() a bit :

    Code (csharp):
    1.  
    2. fixed4 frag(v2f IN) : SV_Target
    3. {
    4. fixed4 c = SampleSpriteTexture(IN.texcoord) * IN.color;
    5.  
    6. // If outline is enabled and there is a pixel, try to draw an outline.
    7. if (_Outline > 0 && c.a != 0) {
    8. float totalAlpha = 1.0;
    9.  
    10. //Color pixels when It's on the sprite texture's edge
    11. if (IN.texcoord.x < _MainTex_TexelSize.x || IN.texcoord.y < _MainTex_TexelSize.y ||
    12. IN.texcoord.x > 1 - _MainTex_TexelSize.x || IN.texcoord.y > 1 - _MainTex_TexelSize.y)
    13. {
    14. totalAlpha = 0;
    15. }
    16. else
    17. {
    18. [unroll(16)]
    19. for (int i = 1; i < _OutlineSize + 1; i++) {
    20. fixed4 pixelUp = tex2D(_MainTex, IN.texcoord + fixed2(0, i * _MainTex_TexelSize.y));
    21. fixed4 pixelDown = tex2D(_MainTex, IN.texcoord - fixed2(0, i * _MainTex_TexelSize.y));
    22. fixed4 pixelRight = tex2D(_MainTex, IN.texcoord + fixed2(i * _MainTex_TexelSize.x, 0));
    23. fixed4 pixelLeft = tex2D(_MainTex, IN.texcoord - fixed2(i * _MainTex_TexelSize.x, 0));
    24.  
    25. totalAlpha = totalAlpha * pixelUp.a * pixelDown.a * pixelRight.a * pixelLeft.a;
    26. }
    27. }
    28.  
    29. if (totalAlpha == 0) {
    30. c.rgba = fixed4(1, 1, 1, 1) * _OutlineColor;
    31. }
    32. }
    33.  
    34. c.rgb *= c.a;
    35.  
    36. return c;
    37. }
    38.  
    ...In the Editor, It looks OK :





    But, when I hit the play button :



    The outline doesn't work properly again.

    What am I doing wrong here? I'm almost new to shader coding, so any help will be greatly appreciated.

    (*And I didn't pack sprites manually, I just leave packing to Unity Built-In sprite packer.)
     
  2. GarlicDipping

    GarlicDipping

    Joined:
    Sep 7, 2013
    Posts:
    33
    OK, so I assume I got the reason of this bug.

    In Editor's Scene view, it seems like unity uses the original sprite file, which is not packed yet, so I can just detect sprite's edge with value 0 and 1.

    But, In play mode, I guess Unity uses built-in packed sprite sheet, and for that, 0 or 1 texcoord value is now not actually the edge of my sprite, it's edge of sprite sheet.

    So what I'm curious of now is, How can I get current rendering sprite's texcoord uv & size in the sprite sheet?

    If i can get those, I can check if it's real 'edge' of current drawing sprite...
     
  3. GarlicDipping

    GarlicDipping

    Joined:
    Sep 7, 2013
    Posts:
    33