- Home /
How would you go about creating a material that allows you to add fully tiling textures to a 2D sprite?
Hello! Obligatory "first post" so apologies if this is a simple question but:
I am currently running into an issue with my top down 2D shooter. For my environments I didn't want to used a fully tile based workflow, I wanted to use various polygons and geometric shapes to create interesting environments. Once I created these environments I wanted to texture the 2D sprites that make up the objects. However I cannot find any way to apply textures correctly to 2D sprites. I wrote a quick shader which allows me to apply the texture image over the sprite, however it does not repeat like a texture ought to, despite the source image being set to repeat and messing with the tiling rate. I will post the shader I am attempting to use down below, any help is much appreciated!
Shader "SpritesTest"
{
Properties
{
[PerRendererData] _MainTex("Sprite Texture", 2D) = "white" {}
_SubTex("Sub 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;
v2f vert(appdata_t IN)
{
v2f OUT;
OUT.vertex = UnityObjectToClipPos(IN.vertex);
OUT.texcoord = IN.texcoord;
OUT.color = IN.color * _Color;
#ifdef PIXELSNAP_ON
OUT.vertex = UnityPixelSnap(OUT.vertex);
#endif
return OUT;
}
sampler2D _MainTex;
sampler2D _SubTex;
sampler2D _AlphaTex;
float _AlphaSplitEnabled;
fixed4 SampleSpriteTexture(float2 uv)
{
fixed4 color = tex2D(_SubTex, 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
}
}
}
Answer by ReneSchleese · Jul 02, 2020 at 10:46 AM
For the tiling and offset values within the material inspector to work with the shader, you need to modify the UVs using Unity's TRANSFORM_TEX makro. I modified your shader and marked the important changes with "HERE".
Shader "SpritesTest"
{
Properties
{
[PerRendererData] _MainTex("Sprite Texture", 2D) = "white" {}
_SubTex("Sub 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
// HERE: traditional alpha blending
Blend SrcAlpha 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;
// HERE: Define a second set of UVs
float2 tiledUVs : TEXCOORD1;
};
fixed4 _Color;
sampler2D _MainTex;
sampler2D _AlphaTex;
float _AlphaSplitEnabled;
// HERE: Define a float4 _SubTex_ST with the correct naming for the TRANSFORM_TEX makro to work
sampler2D _SubTex;
float4 _SubTex_ST;
v2f vert(appdata_t IN)
{
v2f OUT;
OUT.vertex = UnityObjectToClipPos(IN.vertex);
OUT.texcoord = IN.texcoord;
OUT.color = IN.color * _Color;
#ifdef PIXELSNAP_ON
OUT.vertex = UnityPixelSnap(OUT.vertex);
#endif
// HERE: Use the TRANSFORM_TEX makro to calculate the new UVs of the tiled texture in the material inspector
OUT.tiledUVs = TRANSFORM_TEX(IN.texcoord, _SubTex);
return OUT;
}
fixed4 frag(v2f IN) : SV_Target
{
// HERE: First sample the sprite using its default UVs. Then sample the tile texture using the modified UVs.
fixed4 mainCol = tex2D(_MainTex, IN.texcoord);
fixed4 tileCol = tex2D(_SubTex, IN.tiledUVs);
tileCol.a = mainCol.rgb;
return tileCol;
}
ENDCG
}
}
}
Your answer
Follow this Question
Related Questions
Black boarder on transparent sprites 2 Answers
Overlay texture on sprite 0 Answers
How can I use atlas sprite as texture for a material? 2 Answers