Skip to content

Instantly share code, notes, and snippets.

@joshcamas
Last active September 23, 2023 23:00
Show Gist options
  • Save joshcamas/a9e39b6401d12538a6af19a8cd79f43e to your computer and use it in GitHub Desktop.
Save joshcamas/a9e39b6401d12538a6af19a8cd79f43e to your computer and use it in GitHub Desktop.
Distant Pixelize Unity Effect
Shader "Ardenfall/Effects/DistantPixelize"
{
HLSLINCLUDE
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareDepthTexture.hlsl"
float _MaxPixelSize;
float _MinPixelSize;
float _MaxDistance;
TEXTURE2D_X(_MainTex);
SAMPLER(sampler_MainTex);
float4 _MainTex_TexelSize;
struct Attributes
{
float4 positionOS : POSITION;
float2 uv : TEXCOORD0;
};
struct Varyings {
float4 positionCS : POSITION;
float2 uv : TEXCOORD0;
};
Varyings Vert(Attributes input) {
Varyings output;
UNITY_SETUP_INSTANCE_ID(input);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
output.positionCS = TransformObjectToHClip(input.positionOS.xyz);
output.uv.xy = input.uv;
return output;
}
float2 CalculatePixelUV(float2 uv, float pixelSize)
{
float aspect = _ScreenParams.y / _ScreenParams.x;
// Round the UV coordinates to the calculated pixel size
float x = round(uv.x / (pixelSize * aspect)) * (pixelSize * aspect);
float y = round(uv.y / pixelSize) * pixelSize;
return float2(x,y);
}
float CalculateLinearDepthURP(float2 depthUv)
{
#if UNITY_REVERSED_Z
float depth = SampleSceneDepth(depthUv);
#else
float depth = lerp(UNITY_NEAR_CLIP_VALUE, 1, SampleSceneDepth(depthUv));
#endif
depth = LinearEyeDepth(depth, _ZBufferParams);
return depth;
}
float4 Frag(Varyings i) : SV_Target
{
//Sample depth using the largest pixel size.
//This does introduce some artifacts, but also fixes pixels from not being square
float2 depthUv = CalculatePixelUV(i.uv, _MaxPixelSize);
float depth = CalculateLinearDepthURP(depthUv);
if(depth > _MaxDistance)
depth = _MaxDistance;
//Calculate pixel size based on depth
float depthFactor = saturate((_MaxDistance - depth) / _MaxDistance);
float pixelSize = lerp(_MinPixelSize, _MaxPixelSize, depthFactor);
//Fix pixel size by making it a half step of the max pixel size. (If the max size is 1, then it could be 1, 0.5, 0.25, 0.125, etc)
//This stops pixels from looking extremely strange
float numHalves = log2(_MaxPixelSize / pixelSize);
pixelSize = _MaxPixelSize / pow(2.0, round(numHalves));
//Calculate pixelized UV
float2 pixelUV = CalculatePixelUV(i.uv, pixelSize);
return SAMPLE_TEXTURE2D_X(_MainTex, sampler_MainTex, pixelUV);
}
ENDHLSL
SubShader
{
Cull Off ZWrite Off ZTest Always
Pass
{
Name "Pixelize"
HLSLPROGRAM
#pragma vertex Vert
#pragma fragment Frag
ENDHLSL
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment