Skip to content

Instantly share code, notes, and snippets.

@dasannikov
Created December 1, 2025 16:12
Show Gist options
  • Select an option

  • Save dasannikov/9d6040833d1b44d603ac01b09788b1cc to your computer and use it in GitHub Desktop.

Select an option

Save dasannikov/9d6040833d1b44d603ac01b09788b1cc to your computer and use it in GitHub Desktop.
Unity3D Shader for UI Image with Rotated Grid Super-Sampling
Shader "UiImage-RGSS"
{
Properties
{
_MainTex ("Sprite Texture", 2D) = "white" {}
_Color ("Tint", Color) = (1,1,1,1)
_StencilComp ("Stencil Comparison", Float) = 8
_Stencil ("Stencil ID", Float) = 0
_StencilOp ("Stencil Operation", Float) = 0
_StencilWriteMask ("Stencil Write Mask", Float) = 255
_StencilReadMask ("Stencil Read Mask", Float) = 255
_ColorMask ("Color Mask", Float) = 15
[Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use Alpha Clip", Float) = 0
}
SubShader
{
Tags
{
"Queue"="Transparent"
"IgnoreProjector"="True"
"RenderType"="Transparent"
"PreviewType"="Plane"
"CanUseSpriteAtlas"="True"
}
Stencil
{
Ref [_Stencil]
Comp [_StencilComp]
Pass [_StencilOp]
ReadMask [_StencilReadMask]
WriteMask [_StencilWriteMask]
}
Cull Off
Lighting Off
ZWrite Off
ZTest [unity_GUIZTestMode]
Blend SrcAlpha OneMinusSrcAlpha
ColorMask [_ColorMask]
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 3.0
#include "UnityCG.cginc"
#include "UnityUI.cginc"
#pragma multi_compile_local _ UNITY_UI_CLIP_RECT
#pragma multi_compile_local _ UNITY_UI_ALPHACLIP
struct appdata
{
float4 vertex : POSITION;
float4 color : COLOR;
float2 texcoord : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct v2f
{
float4 vertex : SV_POSITION;
fixed4 color : COLOR;
float2 texcoord : TEXCOORD0;
float4 worldPosition : TEXCOORD1;
UNITY_VERTEX_OUTPUT_STEREO
};
sampler2D _MainTex;
fixed4 _Color;
fixed4 _TextureSampleAdd;
float4 _ClipRect;
float4 _MainTex_ST;
// Rotated Grid Super-Sampling (RGSS)
// RGSS offsets for 2x2 rotated grid supersampling
static const float2 rgss_uv_offsets = float2(0.125, 0.375);
// RGSS texture sampling function
fixed4 rgss_tex2D(sampler2D texture_sampler, float2 uv)
{
// Per pixel partial derivatives
float2 dx = ddx(uv);
float2 dy = ddy(uv);
// Supersampled using 2x2 rotated grid
fixed4 col = tex2D(texture_sampler, uv + rgss_uv_offsets.x * dx + rgss_uv_offsets.y * dy);
col += tex2D(texture_sampler, uv - rgss_uv_offsets.x * dx - rgss_uv_offsets.y * dy);
col += tex2D(texture_sampler, uv + rgss_uv_offsets.y * dx - rgss_uv_offsets.x * dy);
col += tex2D(texture_sampler, uv - rgss_uv_offsets.y * dx + rgss_uv_offsets.x * dy);
col *= 0.25;
return col;
}
v2f vert(appdata v)
{
v2f o;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
o.worldPosition = v.vertex;
o.vertex = UnityObjectToClipPos(o.worldPosition);
o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
o.color = v.color * _Color;
return o;
}
fixed4 frag(v2f i) : SV_Target
{
// Use RGSS sampling
fixed4 color = rgss_tex2D(_MainTex, i.texcoord) + _TextureSampleAdd;
color *= i.color;
#ifdef UNITY_UI_CLIP_RECT
color.a *= UnityGet2DClipping(i.worldPosition.xy, _ClipRect);
#endif
#ifdef UNITY_UI_ALPHACLIP
clip(color.a - 0.001);
#endif
return color;
}
ENDCG
}
}
}
@dasannikov
Copy link
Author

dasannikov commented Dec 1, 2025

Here is the details: https://medium.com/@dasannikov/unity-tricks-solving-noisy-ui-icons-485c79f746a4
Assign the shader as a Material to your UI Image, and make sure to enable mipmaps with trilinear filtering for the image's texture.
It’s worth mentioning that better results are achieved only when the mipmap bias is set to –1. In Unity3D, you can only change this via script - google it.

@dasannikov
Copy link
Author

Here is live web Demo but for Defeold Engine implementation:
https://indiesoftby.github.io/defold-sharp-sprite/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment