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 Shader shader;
        public int    PixelSize = 8;
        public bool   AddStrip;

        protected void OnRenderImage(RenderTexture source, RenderTexture destination)
        {
            Material material = new Material(shader);
            material.SetInt("_PixelSize", PixelSize);
            material.SetInt("_AddStrip", AddStrip ? 1 : 0);
            Graphics.Blit(source, destination, material);
        }
    }
}

shader code

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

    CGINCLUDE
    #include "UnityCG.cginc"

    sampler2D _MainTex;
    int _PixelSize;
    int _AddStrip;

    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

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

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

    }

    FallBack off
}

Topics: Game Development convolution Unity3d Shader