Texture Wrap Mode Mirror option doesn't seem to work for SpriteRenderer. Am I doing something wrong?

I created an asset that I want mirrored on repeat. I assumed setting the Wrap Mode to “Mirror” and Sprite Renderer Draw Mode to “Tiled”, but I’m just getting a basic repeat.

The Unity docs say that the Mirror option “Tiles the texture, creating a repeating pattern by mirroring it at every integer boundary.”

Here’s some pictures that show my configs and result.

Is it bad etiquette to bump posts?

So the docs say that Tiled mode is actually a 9-sliced version of the sprite that preserves the corners and is then tiled elsewhere. This seems to be a tiling of the UV space, so it’s not extending beyond the 0-1 UV space resulting in the texture’s repeat mode not coming into play.

To properly get mirrored tiling I think you will need to create a custom shader that scales the UV space.

You could try something like this that just leverages Unity’s magic “_ST” property and “TRANSFORM_TEX” function. So you would make a material with this shader, and then set your SpriteRenderer to Tiled while using it.

Sprites-Tiled Shader

Shader "Sprites/Tiled"
{
    Properties
    {
        [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
        _Color ("Tint", Color) = (1,1,1,1)
        [MaterialToggle] PixelSnap ("Pixel snap", Float) = 0
    }

    SubShader
    {
        Tags
        {
            "Queue"="Transparent"
            "IgnoreProjector"="True"
            "RenderType"="Transparent"
            "PreviewType"="Plane"
            "CanUseSpriteAtlas"="True"
        }

        Cull Off
        Lighting Off
        ZWrite Off
        Blend One OneMinusSrcAlpha

        Pass
        {
        CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile _ PIXELSNAP_ON
            #include "UnityCG.cginc"
         
            struct appdata_t
            {
                float4 vertex   : POSITION;
                float4 color    : COLOR;
                float2 texcoord : TEXCOORD0;
            };

            struct v2f
            {
                float4 vertex   : SV_POSITION;
                fixed4 color    : COLOR;
                float2 texcoord  : TEXCOORD0;
            };
         
            fixed4 _Color;

            sampler2D _MainTex;
            sampler2D _AlphaTex;
            float _AlphaSplitEnabled;
            float4 _MainTex_ST;

            v2f vert(appdata_t IN)
            {
                v2f OUT;
                OUT.vertex = UnityObjectToClipPos(IN.vertex);
                OUT.texcoord = TRANSFORM_TEX(IN.texcoord, _MainTex);
                OUT.color = IN.color * _Color;
                #ifdef PIXELSNAP_ON
                OUT.vertex = UnityPixelSnap (OUT.vertex);
                #endif

                return OUT;
            }

            fixed4 SampleSpriteTexture (float2 uv)
            {
                fixed4 color = tex2D (_MainTex, uv);

#if UNITY_TEXTURE_ALPHASPLIT_ALLOWED
                if (_AlphaSplitEnabled)
                    color.a = tex2D (_AlphaTex, uv).r;
#endif //UNITY_TEXTURE_ALPHASPLIT_ALLOWED

                return color;
            }

            fixed4 frag(v2f IN) : SV_Target
            {
                fixed4 c = SampleSpriteTexture (IN.texcoord) * IN.color;
                c.rgb *= c.a;
                return c;
            }
        ENDCG
        }
    }
}

Or if that causes issues, create a shader similarly based on the default, but just add your own “Scale” property and multiply the UV by that in the Sample function.

I’m not a shader expert, there may be a better way.

Of course, you could always use a full-width sprite and tile that but I’m sure you’ve considered that.

Of course, you could always use a full-width sprite and tile that but I’m sure you’ve considered that.

Hmm, I’m not sure what you mean by this last part.

For the rest of your comment, unfortunately I don’t think I have enough technical knowledge of UV and its relationship to 2D sprites or with Shaders (I typically use Shader Graph when I want to get any fancier than default materials).

To clarify, instead of having a half-arch sprite that you mirror, you could have one full width arch and tile it normally.

Tiling UVs is something you can do easily in shadergraph if you want to.

To clarify, instead of having a half-arch sprite that you mirror, you could have one full width arch and tile it normally.

Oh, haha. Yes, that is exactly what I ended up doing. Thanks for clarifying.

And thanks for the tutorial!

1 Like