Aspect Ratio Correction in GLSL
Dividing fragCoord by resolution normalizes both axes to zero-to-one, but a unit on each axis may cover a different pixel count. Use one pixel scale for circles, such as dividing both axes by canvas height. Image lookup still uses UV normalized independently per axis.
Fix the problem and environment
Dividing fragCoord by resolution normalizes both axes to zero-to-one, but a unit on each axis may cover a different pixel count. Use one pixel scale for circles, such as dividing both axes by canvas height. Image lookup still uses UV normalized independently per axis.
The controlling code
vec2 uv=gl_FragCoord.xy/u_resolution;
vec2 p=(2.0*gl_FragCoord.xy-u_resolution)/u_resolution.y;
float circle=1.0-smoothstep(0.3,0.31,length(p));
float cellPixels=12.0;
vec2 blockUV=(floor(gl_FragCoord.xy/cellPixels)+0.5)*cellPixels/u_resolution;
Verify in order
Test square, wide and portrait canvases. The circle must remain circular and pixelation cells must have equal horizontal and vertical pixel lengths.
Scope and common mistakes
Keep CSS size and drawing-buffer size coordinated. Changing only element styling leaves shader pixel units inconsistent with displayed pixels.