# Implementation of Unity pixelation post-processing effect

Posted by kylebud on Fri, 04 Mar 2022 15:12:27 +0100

## Realization idea

Pixelation is to make many adjacent pixels become one pixel, which will naturally have the effect of pixelation.
According to this idea, we can immediately think of a way to divide the screen into several areas. Each area is composed of several adjacent pixels. Each area is a square, and then calculate the convolution of the square as the color of this area.
This method will be a little troublesome. The shader we wrote today simply samples a pixel in this area to represent the color of the whole area.
It may sound unreliable, but it actually looks good. After all, it's all pixel effect, and some errors may be better.

## code implementation

Write a function to input the uv and return the color. We first convert the uv into screen coordinates for easy calculation, then divide it by the pixel block size we need, then use the floor function to round it down, and then multiply it back by the pixel block size to get the effect that the colors of a certain area are the same. Such a pixelated shader is completed. Yes, it's that simple.

```    half4 pixel(half2 uv)
{
half2 screenPos = floor(uv * _ScreenParams.xy / _PixelSize) * _PixelSize;
return tex2D(_MainTex, screenPos / _ScreenParams.xy);
}
```

Original drawing After pixelation Let's finally add a stripe effect. Enables 45 degree slash stripes to appear on the screen.
This calculation is also based on the simple linear function y=x+nk, where x and y are coordinates, n is the pixel size, and k is any integer. Our goal is to blacken out the X and Y coordinates that satisfy this function.
After transforming the formula, it can be found that (y-x)%n=0
We can test according to this formula, and y=-x+nk is the same

```    half2 stitch(half2 uv)
{
half2 screenPos = floor(uv * _ScreenParams.xy);
half2 reminder;
reminder.y = (screenPos.y - screenPos.x) % _PixelSize;
reminder.x = (screenPos.y + screenPos.x) % _PixelSize;
return reminder;
}
```

Finally, judge whether the remainder is 0 in the slice shader

``` return (reminder.y == 0 || reminder.x == 0)&&_AddStrip==1 ? half4(0, 0, 0, 1) : color;
```

Effect after adding stripes ## Complete code

c# code

```namespace Colorful
{
using UnityEngine;

[ExecuteInEditMode]
public class Pixelate : MonoBehaviour
{
public int    PixelSize = 8;

protected void OnRenderImage(RenderTexture source, RenderTexture destination)
{
Material material = new Material(shader);
material.SetInt("_PixelSize", PixelSize);
Graphics.Blit(source, destination, material);
}
}
}
```

```Shader "LX/Pixelate"
{
Properties
{
_MainTex ("Base (RGB)", 2D) = "white" {}
}

CGINCLUDE
#include "UnityCG.cginc"

sampler2D _MainTex;
int _PixelSize;

half2 stitch(half2 uv)
{
half2 screenPos = floor(uv * _ScreenParams.xy);
half2 reminder;
reminder.y = (screenPos.y - screenPos.x) % _PixelSize;
reminder.x = (screenPos.y + screenPos.x) % _PixelSize;
return reminder;
}

half4 pixel(half2 uv)
{
half2 screenPos = floor(uv * _ScreenParams.xy / _PixelSize) * _PixelSize;
return tex2D(_MainTex, screenPos / _ScreenParams.xy);
}

half4 frag(v2f_img i) : SV_Target
{
half2 reminder = stitch(i.uv);
half4 color = pixel(i.uv);
return (reminder.y == 0 || reminder.x == 0)&&_AddStrip==1 ? half4(0, 0, 0, 1) : color;
}
ENDCG

{
ZTest Always Cull Off ZWrite Off
Fog
{
Mode off
}

Pass
{
CGPROGRAM
#pragma vertex vert_img
#pragma fragment frag
ENDCG
}

}

FallBack off
}
```