-
-
Save talecrafter/81e2f3bb7fb4b4fc367e7b851772b646 to your computer and use it in GitHub Desktop.
/* | |
Basic Sprite Shader for aligning pixel art to the same grid, based on the Unity Sprite Shader. | |
Create one Material where you assign the same Pixels Per Unit value you use on your imported Sprites, | |
then reuse this Material on all appropriate Sprite Renderers. | |
(You can use Shader.SetGlobalFloat to set that Pixels Per Unit value for all your shaders: | |
https://docs.unity3d.com/ScriptReference/Shader.SetGlobalFloat.html) | |
This is not for scaled or rotated artwork. If you need those features, look at low res render textures. | |
Use this however you want. | |
@talecrafter | |
*/ | |
Shader "Sprites/PixelArt" | |
{ | |
Properties | |
{ | |
[PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {} | |
_Color ("Tint", Color) = (1,1,1,1) | |
_pixelsPerUnit("Pixels Per Unit", Float) = 16 | |
} | |
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 _ UNITY_ETC1_EXTERNAL_ALPHA | |
#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; | |
float _pixelsPerUnit; | |
float4 AlignToPixelGrid(float4 vertex) | |
{ | |
float4 worldPos = mul(unity_ObjectToWorld, vertex); | |
worldPos.x = floor(worldPos.x * _pixelsPerUnit + 0.5) / _pixelsPerUnit; | |
worldPos.y = floor(worldPos.y * _pixelsPerUnit + 0.5) / _pixelsPerUnit; | |
return mul(unity_WorldToObject, worldPos); | |
} | |
v2f vert(appdata_t IN) | |
{ | |
float4 alignedPos = AlignToPixelGrid(IN.vertex); | |
v2f OUT; | |
OUT.vertex = mul(UNITY_MATRIX_MVP, alignedPos); | |
OUT.texcoord = IN.texcoord; | |
OUT.color = IN.color * _Color; | |
return OUT; | |
} | |
sampler2D _MainTex; | |
sampler2D _AlphaTex; | |
fixed4 SampleSpriteTexture(float2 uv) | |
{ | |
fixed4 color = tex2D(_MainTex, uv); | |
#if ETC1_EXTERNAL_ALPHA | |
color.a = tex2D(_AlphaTex, uv).r; | |
#endif | |
return color; | |
} | |
fixed4 frag(v2f IN) : SV_Target | |
{ | |
fixed4 c = SampleSpriteTexture (IN.texcoord) * IN.color; | |
c.rgb *= c.a; | |
return c; | |
} | |
ENDCG | |
} | |
} | |
} |
@Skybladev2
The 0.5 is for offsetting the result so the source position is inside a virtual square by all four possible new positions. It's half a pixel in world space which would be 0.03125 and not 0.0625 for a _pixelsPerUnit of 16. (I guess you meant 0.0625 and the missing 0 was a typo.)
Here's it written in another way:
float offset = 0.5 / _pixelsPerUnit;
worldPos.x = floor(worldPos.x * _pixelsPerUnit) / _pixelsPerUnit + offset;
@talecrafter
No, I meant 0.625 which is 3/4 - 1/8.
Ok, I checked - there is no difference between 0.5 and 0.625, so forget it.
@Skybladev2
Ok, that's what you meant. Thanks for checking. :)
Note it looks like before Unity 5.4, the functions in the UnityCG.cginc library "unity_WorldToObject" and "unity_ObjectToWorld" were named "_World2Object" and "_Object2World" respectively. https://forum.unity3d.com/threads/_object2world-undeclared.385227/
So if using this on older versions of unity, you'll want to change those lines or it won't compile.
Thanks for sharing the code @talecrafter!
Hi @talecrafter. I've been using this shader and it's really useful! In a recent version of Unity it seems to be broken though. Would you happen to have patched this in the meantime? Any chance of updating the gist? Thanks for sharing! :)
EDIT: Oh, I just realised you have already updated it. It works now. Thank you!
"(As far as I know there's no possiblity to get this value automatically.)"
You can use Unity - Scripting API: Shader.SetGlobalFloat
https://docs.unity3d.com/ScriptReference/Shader.SetGlobalFloat.html
It sets a float shared by all shaders at the same time.
Thanks for sharing, a must have for any pixel-perfect project!
Good
Bruh
Bruh
Is there a URP version of this? I'd love to be able to use this with the 2D lights
Don't you think it's better to add 0.625 instead of 0.5 to avoid rounding issues?
Or maybe there are no issues and this is an overkill? :)