Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
//
// shader starts here, c# companion script below
//
// PS. Make sure to use square texture (sides must be equal)
//
Shader "Unlit/spritePixelated"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
[Header(Scaling)]
_Res ("Resolution", Float) = 1024
_PixelSize ("Pixel Size", Float) = .0625
[Header(Sprite MetaData)]
_SpriteUV ("Sprite Rect", Vector) = (1,1,0,0)
_SpritePivot ("Sprite Pivot", Vector) = (1,1,0,0)
_UVCenter ("_UVCenter", Vector) = (0,0,0,0)
}
SubShader
{
Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"
"DisableBatching"="True"
}
LOD 100
Blend SrcAlpha OneMinusSrcAlpha
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
uniform half _Res, _PixelSize;
uniform half4 _SpriteUV, _SpritePivot, _UVCenter;
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
float2 quant(float2 q, float2 v){
return floor(q/v)*v;
}
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
float2 quantToWorld(float2 value, float q){
float2 wp = mul(unity_ObjectToWorld, float4(value,0,0) );
wp = quant(wp, q) ;
return mul(unity_WorldToObject, float4(wp,0,0));
}
fixed4 frag (v2f i) : SV_Target
{
float2 uv = i.uv;
// next line is the pixelation
uv = quantToWorld(uv-_UVCenter.xy, 1/_Res)+_UVCenter.xy;
fixed4 col = tex2D(_MainTex, uv);
clip(col.a-.001);
return col;
}
ENDCG
}
}
}
// c# companion script
// SpriteUVToShader.cs -------------------------------------------------------------------------------------------------------------------------------- //
// Save you your project, add to your SpriteRenderer gameObject
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
[ExecuteInEditMode]
[RequireComponent(typeof(SpriteRenderer))]
public class SpriteUVToShader : MonoBehaviour {
public string UV_property="_SpriteUV";
public string Pivot_property="_SpritePivot";
public string uvCenter_property="_UVCenter";
public string textureSize_property="_Res";
public string pixelSize_property="_PixelSize";
SpriteRenderer sr;
Sprite sprite;
MaterialPropertyBlock mpb;
void OnValidate()
{
update();
}
void OnWillRenderObject(){
update();
}
void Start(){
update();
}
void update(){
if(sr==null)
sr = GetComponent<SpriteRenderer>();
if(sprite != sr.sprite){
sprite = sr.sprite;
applySpriteUV(sr, sprite, ref mpb, UV_property, Pivot_property, uvCenter_property);
applySpriteTX(sr, sprite, ref mpb, textureSize_property, pixelSize_property);
}
}
public static void applySpriteUV(Renderer renderer, Sprite toSprite, ref MaterialPropertyBlock mpb,
string uvProp=null, string pivotProp=null, string uvCenterProp=null){
if(toSprite==null) return;
var scale = new Vector2(
toSprite.textureRect.width/ toSprite.texture.width,
toSprite.textureRect.height/toSprite.texture.height);
var offset = new Vector2(
toSprite.rect.x/toSprite.texture.width,
toSprite.rect.y/toSprite.texture.height);
Vector4 uvVector = new Vector4(scale.x,scale.y,offset.x,offset.y);
Vector4 pivotVector = new Vector4(toSprite.pivot.x/toSprite.rect.width,toSprite.pivot.y/toSprite.rect.height);
if(string.IsNullOrEmpty(uvProp))
uvProp = "_MainTex_ST";
if(mpb==null)
mpb = new MaterialPropertyBlock();
renderer.GetPropertyBlock(mpb);
mpb.SetVector(uvProp, uvVector);
if(!string.IsNullOrEmpty(pivotProp))
mpb.SetVector(pivotProp, pivotVector);
if(!string.IsNullOrEmpty(uvCenterProp))
mpb.SetVector(uvCenterProp, new Vector2(
Mathf.Lerp(uvVector.z, uvVector.z+uvVector.x, pivotVector.x),
Mathf.Lerp(uvVector.w, uvVector.w+uvVector.y, pivotVector.y)
));
renderer.SetPropertyBlock(mpb);
}
public static void applySpriteTX(Renderer renderer, Sprite toSprite, ref MaterialPropertyBlock mpb,
string texSizeProp=null, string pixSizeProp=null){
if(toSprite==null || string.IsNullOrEmpty(texSizeProp)) return;
if(mpb==null)
mpb = new MaterialPropertyBlock();
renderer.GetPropertyBlock(mpb);
mpb.SetFloat(texSizeProp, toSprite.texture.width);
if(!string.IsNullOrEmpty(pixSizeProp))
mpb.SetFloat(pixSizeProp, 1f/toSprite.pixelsPerUnit);
renderer.SetPropertyBlock(mpb);
}
}
@Hammster

This comment has been minimized.

Copy link

Hammster commented Feb 18, 2018

The texture used needs to be a square, otherwise it will look like this ;)

disortion

@Babarzor

This comment has been minimized.

Copy link

Babarzor commented Oct 23, 2018

facinating, I don't understand anything but it works .. now I wonder how we do to modify the pixel/unit :-p (to have bigger pixels than screen
resolution...)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.