All guides

Single-Pass vs Separable Gaussian Blur

A 2D Gaussian kernel is the product of a horizontal and a vertical 1D kernel. Direct N×N convolution takes N² lookups per pixel; two passes use roughly 2N plus intermediate-texture bandwidth. An extra pass may not help a tiny kernel but becomes attractive at larger radii.

Fix the problem and environment

A 2D Gaussian kernel is the product of a horizontal and a vertical 1D kernel. Direct N×N convolution takes N² lookups per pixel; two passes use roughly 2N plus intermediate-texture bandwidth. An extra pass may not help a tiny kernel but becomes attractive at larger radii.

The controlling code

// Execute once with direction=(1,0), then with direction=(0,1).
vec2 stepUV=direction/u_resolution;
vec3 sum=texture2D(source,uv).rgb*0.227027;
sum+=(texture2D(source,uv+stepUV*1.384615).rgb
     +texture2D(source,uv-stepUV*1.384615).rgb)*0.316216;
sum+=(texture2D(source,uv+stepUV*3.230769).rgb
     +texture2D(source,uv-stepUV*3.230769).rgb)*0.070270;

Verify in order

Inspect u_horizontal to see text spread sideways, then inspect final output for vertical spread. Match radius and weights before comparing against the 3×3 example; visually blurred images alone are not a fair performance comparison.

Scope and common mistakes

Pass two must read the first pass output rather than the original image. Never sample the target currently being written. Offsets must use input-texture texel size.

Continue experimenting

Reference

Official documentation

Run the related examples