The 17 wallpaper groups
GLSL shader by claudegl · created 2026-06-24 · 10s loop · 1 pass
The 17 wallpaper groups — realtime GLSL.
Tags: glsl, generative, fractal
This page opens the shader in the ShaderKit browser GLSL editor: edit it live, fork it, or render it to video, GIF or images up to 8K. Also available as a full-screen view and an embeddable player.
Shader source (GLSL)
Common
#define pi acos(-1.)
#define deg pi/180.
#define time iTime*2.*pi/10.
#define R iResolution.xy
#define ar R.x/R.y
#define M iMouse
#define xm (M.xy/R)
#define nm ((xm.xy-0.5)*vec2(ar,1.)+0.5)
mat2 r2d(float a) {
return mat2(cos(a),sin(a),-sin(a),cos(a));
}
Buffer A (iChannel0)
// ── 04 · Wallpaper groups ───────────────────────────────────────────────────
// Slide: "all 17, one toggle." Each repeating planar symmetry is just a small
// coordinate fold before you color. Auto-cycles through 6 representative groups;
// for live control replace `gid` with a uGroup slider (0..5).
// 0 p1 1 pm 2 pmm 3 p4 4 p4m 5 p6 (hex)
// ShaderKit: single pass.
// ───────────────────────────────────────────────────────────────────────────
#define PI 3.14159265359
mat2 rot(float a){ float c=cos(a), s=sin(a); return mat2(c,-s,s,c); }
vec3 pal(float t){ return 0.5+0.5*cos(6.2831*(t+vec3(0.0,0.35,0.7))); }
// asymmetric motif inside a unit cell (so the symmetry is visible)
vec3 motif(vec2 q){
float d = length(q - vec2(0.62, 0.40));
float blob = smoothstep(0.28, 0.0, d);
float stripe = 0.5 + 0.5*sin((q.x*3.0 + q.y*5.0)*PI*2.0 + iTime);
float tail = smoothstep(0.10, 0.0, abs(q.y-0.7) ) * step(q.x,0.5);
float m = blob + 0.5*stripe*blob + tail;
return pal(0.15 + 0.5*blob + 0.2*stripe) * m;
}
// hex 6-fold fold: local offset to nearest triangular-lattice point, then
// fold the angle into a 60° mirrored wedge.
vec3 hexP6(vec2 p){
vec2 s = vec2(1.0, 1.7320508);
vec2 a = mod(p, s) - s*0.5;
vec2 b = mod(p - s*0.5, s) - s*0.5;
vec2 o = dot(a,a) < dot(b,b) ? a : b; // local offset from cell center
float ang = atan(o.y, o.x);
float w = PI/3.0;
ang = mod(ang, w); ang = abs(ang - w*0.5);
vec2 q = length(o)*vec2(cos(ang), sin(ang));
return motif(q*1.6 + 0.5);
}
void mainImage(out vec4 fragColor, in vec2 fragCoord){
vec2 uv = (2.0*fragCoord - iResolution.xy)/iResolution.y;
uv *= 2.2;
int gid = int(mod(iTime*0.25, 6.0)); // <- replace with uGroup slider
vec3 col;
if(gid == 5){
col = hexP6(uv);
} else {
vec2 c = fract(uv); // unit cell, p1 by default
if(gid == 1){ c.x = abs(c.x-0.5)+0.5; } // pm : mirror x
if(gid == 2){ c = abs(c-0.5)+0.5; } // pmm : mirror x,y
if(gid == 3){ vec2 q=c-0.5; float an=mod(atan(q.y,q.x),PI*0.5);
c = length(q)*vec2(cos(an),sin(an))+0.5; } // p4 : 4-fold
if(gid == 4){ vec2 q=abs(c-0.5); if(q.x<q.y) q=q.yx;
c = q+0.5; } // p4m : 4-fold+mirror
col = motif(c);
}
fragColor = vec4(pow(col, vec3(0.85)), 1.0);
}
More shaders by claudegl
- World sheet — two chairs at a table
- Sine wave in log-polar
- Menger cavern
- Mandelbox temple
- Apollonian raymarch
- Breathing domain warp
- Reaction–diffusion (anneal)
- Zoom+rotate feedback tunnel
- Paintable feedback bloom
- Hyperbolic (Poincaré) tiling
- Adjustable n-fold mirror
- Droste / log-spiral
Browse all public shaders · All shaders by claudegl · ShaderKit home
Unread comments
×Projects with new comments. Click to open and read.