Search Unity

  1. Are you interested in providing feedback directly to Unity teams? Sign up to become a member of Unity Pulse, our new product feedback and research community.
    Dismiss Notice

Unity Sprite shaders are bugged?

Discussion in 'General Graphics' started by SoftwareGeezers, Jul 29, 2021.

  1. SoftwareGeezers

    SoftwareGeezers

    Joined:
    Jun 22, 2013
    Posts:
    613
    In drawing the attached image2.png simple shadowed square sprite:
    Image2.png
    ...Unity is adding a dark outline. This changes the aesthetic completely. The same happens in 2019 and 2021.

    The left side shows the sprite in my graphics editor. The right side shows it zoomed in on Unity, the border being 1 pixel wide.

    Image1.png

    If I use the Standard rendering material in the Fade rendering mode, it works okay, but any sprite or similar material, default or discrete material, adds this border. I've tried various sprite settings like no compression but the problem persists.
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    10,893
    I thought I knew the reason, but then I attempted to reproduce the issue you're seeing and I cannot when using an image I made myself to mimic what you have.

    Does the same issue happen with this image? If not it might be a problem with the output of the tool you're using.
    graphicTest.png
     
  3. koirat

    koirat

    Joined:
    Jul 7, 2012
    Posts:
    1,067
    Wild guess but might be mipmapping issue.
     
  4. Torbach78

    Torbach78

    Joined:
    Aug 10, 2013
    Posts:
    194
    Alpha blending + Bilinear filtering doing its magic

    • Small 48x48 sprites have edge quality 'fuzziness' zoomed in beyond 1:1 anyway
    • couple that with the Alpha Blend mode and you get this dark outline.

    you may want to use pre-multiplied alpha blending when a sprite is on a black background (e.g. drop shadow)

    options
    • filter setting from bilinear -> point (no filter) e.g. 'nearest neighbor' expansion bc I don't know if there is a way bilinear can have a 'border preserve' solution based on a threshold
    • increase the res on the image above 128.. The Left image I made is 128 and on the right is your provided 48x48 png
    upload_2021-7-29_19-14-4.png

    you can try to utilize different solutions for drop shadowing
    1. A programmatic solution and re-author the image for Alpha blending (all blueish, no black premultiplication) and no need for drop shadow texture space use.
    2. Create B&W drop shadows separately (pack them R8 if you need to save memory, they can also be low res like 32x32 as long as you keep them uncompressed they filter well)

    edit here are the same images with a Premultiplied Blend mode
    upload_2021-7-29_19-25-44.png
     
    Last edited: Jul 30, 2021
  5. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    10,893
    Yep, it's this. This is what I was going to say it was, but for some reason I couldn't see it when I tried it the first time. Trying it again it's absolutely the problem.
     
  6. SoftwareGeezers

    SoftwareGeezers

    Joined:
    Jun 22, 2013
    Posts:
    613
    Thanks. That's kinda sucky. I think point sampling will work okay.
     
  7. Torbach78

    Torbach78

    Joined:
    Aug 10, 2013
    Posts:
    194
    add a premult blend mode shader when you want to implement pre-multiplied sprite(s) - limiting projects to Alpha blend has always come with some degree of flaws

    i know the default built in sprite render doesn't have a pull down you can just grab something simple : I found this online and changed the Blend math to correct for premultiplied alpha
    Blend One OneMinusSrcAlpha



    Code (CSharp):
    1. Shader "premultiplied alpha sprite"
    2. {
    3.     Properties
    4.       {
    5.         _Color ("Tint", Color) = (0, 0, 0, 1)
    6.         _MainTex ("Texture", 2D) = "white" {}
    7.       }
    8.  
    9.     SubShader
    10.     {
    11.         Tags
    12.          {
    13.             "RenderType"="Transparent"
    14.             "Queue"="Transparent"
    15.           }
    16.  
    17.         Blend One OneMinusSrcAlpha
    18.  
    19.         ZWrite off
    20.         Cull off
    21.  
    22.         Pass
    23.      {
    24.  
    25.             CGPROGRAM
    26.  
    27.             #include "UnityCG.cginc"
    28.  
    29.             #pragma vertex vert
    30.             #pragma fragment frag
    31.  
    32.             sampler2D _MainTex;
    33.             float4 _MainTex_ST;
    34.  
    35.             fixed4 _Color;
    36.  
    37.             struct appdata
    38.             {
    39.                 float4 vertex : POSITION;
    40.                 float2 uv : TEXCOORD0;
    41.                 fixed4 color : COLOR;
    42.             };
    43.  
    44.             struct v2f
    45.            {
    46.                 float4 position : SV_POSITION;
    47.                 float2 uv : TEXCOORD0;
    48.                 fixed4 color : COLOR;
    49.             };
    50.  
    51.             v2f vert(appdata v)
    52.           {
    53.                 v2f o;
    54.                 o.position = UnityObjectToClipPos(v.vertex);
    55.                 o.uv = TRANSFORM_TEX(v.uv, _MainTex);
    56.                 o.color = v.color;
    57.                 return o;
    58.             }
    59.  
    60.             fixed4 frag(v2f i) : SV_TARGET
    61.            {
    62.                 fixed4 color = tex2D(_MainTex, i.uv);
    63.                 color *= _Color;
    64.                 color *= i.color;
    65.                 return color;
    66.             }
    67.  
    68.             ENDCG
    69.         }
    70.     }
    71. }
     
    SoftwareGeezers likes this.
  8. SoftwareGeezers

    SoftwareGeezers

    Joined:
    Jun 22, 2013
    Posts:
    613
  9. SoftwareGeezers

    SoftwareGeezers

    Joined:
    Jun 22, 2013
    Posts:
    613
    This issue, the limits of bilinear sampling, actually extends further I've just discovered. A 128x128 tile is overkill if viewed from a distance, which is where we'd want mipmaps, but these develop artefacts, I'm guessing from Unity downsampling the source.

    upload_2021-8-1_17-30-50.png

    Looks like we need to provide custom mipmaps which Unity doesn't support internally, needing an external tool to generate a .dds file. Reading around, it seems this is then limited to uncompressed RGB which is problematic.
     
unityunity