Skip to content

Instantly share code, notes, and snippets.

@hippocoder
Created February 22, 2026 19:40
Show Gist options
  • Select an option

  • Save hippocoder/5e96985fcab802d81ab509529f4baa14 to your computer and use it in GitHub Desktop.

Select an option

Save hippocoder/5e96985fcab802d81ab509529f4baa14 to your computer and use it in GitHub Desktop.
Pixel Art Antialiasing UVs
// ANTIALIASED PIXEL ART SAMPLING EXAMPLE
//old code by Robert Cummings, thanks to Ben Golus for the original techniques + the internets etc (this isn't copyrighted code!)
//all this code is considered open source - do what you want, just don't bother charging for it, share with people
//each texel is a flat plateau of solid colour.
//blending occurs at transition band at texel borders, sized to cover one screen pixel, no shimmer/blur/crawl etc...
//this effectively turns the bilinear filter into a box filter exactly one screen pixel wide, centered on the texel boundary.
//texture and sampler should use BILINEAR filtering + CLAMP or WRAP as needed, no mipmaps!!!
//point filtering will NOT work
//should work with on UE (custom nodes), Unity, Godot / most engines with a few tweaks
//haven't tested it in a long time and will not support you :P
//---
float2 PixelArtUV(float2 uv, float2 textureSize)
{
//UV in texel space (0..textureSize)
float2 texelUV = uv * textureSize;
float2 dxUV = ddx(texelUV);
float2 dyUV = ddy(texelUV);
float2 filterWidth = max(
float2(length(float2(dxUV.x, dyUV.x)),
length(float2(dxUV.y, dyUV.y))),
// Clamp to a minimum to avoid division by zero at extreme close-ups
float2(1.0e-5, 1.0e-5)
);
float2 texelCenter = floor(texelUV - 0.5) + 0.5; //center of nearest texel
float2 frac_ = texelUV - texelCenter; // -.5 .. +.5 from center
float2 halfPixel = 0.5 * filterWidth;
float2 snapped = clamp(frac_ / halfPixel, -1.0, 1.0);
// Remap from [-1,1] back to [-0.5, 0.5]
snapped = snapped * 0.5;
//reconstruct the UV
float2 newTexelUV = texelCenter + snapped;
//convert back
return newTexelUV / textureSize;
}
//-- example
Texture2D _SpriteTexture : register(t0);
SamplerState _SpriteSampler : register(s0); //bilinear, Clamp
struct PSInput
{
float4 position : SV_POSITION;
float2 uv : TEXCOORD0;
};
float4 PSMain(PSInput input) : SV_TARGET
{
// textureSize = (width, height) of _SpriteTexture in texels
float2 textureSize;
_SpriteTexture.GetDimensions(textureSize.x, textureSize.y);
float2 aaUV = PixelArtUV(input.uv, textureSize);
return _SpriteTexture.Sample(_SpriteSampler, aaUV);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment