Pixel Shader Examples

The following collections each explore a topic in pixel shaders. Each consists of a series of examples, with each example building on the previous.

In the future I'd like to produce accompanying text, diagrams, exercises, tools, etc. to fully support the development of these topics. But in the meantime don't let this stop you from developing your own understanding through exploration and experimentation!

Sampling: Color Distortion

precision mediump float; varying vec2 position; uniform sampler2D webcam; float wave(float x, float amount) { return (sin(x * amount) + 1.) * .5; } void main() { vec4 color = texture2D(webcam, position); gl_FragColor.r = wave(color.r, 10.); gl_FragColor.g = wave(color.g, 20.); gl_FragColor.b = wave(color.b, 40.); gl_FragColor.a = 1.; }

Sampling: Spatial Distortion

precision mediump float; varying vec2 position; uniform sampler2D webcam; uniform float time; void main() { vec2 p = position; p.x = p.x + sin(p.y*80.+time*6.)*0.03; gl_FragColor = texture2D(webcam, p); }

Sampling: Displacement

precision mediump float; varying vec2 position; uniform sampler2D webcam; uniform float time; float stripes(vec2 p, float steps) { return fract(p.x*steps); } void main() { vec2 p = position; vec4 color = texture2D(webcam, p); p.x += color.r * 0.1 * sin(time); float brightness = stripes(p, 10.); gl_FragColor.rgb = vec3(brightness); gl_FragColor.a = 1.; }

Case Study: Patterns

precision mediump float; varying vec2 position; uniform sampler2D webcam; uniform float time; float wrap(float x) { return abs(mod(x, 2.)-1.); } void main() { vec2 p = position; float size = 0.1; p.x = mod(p.x, size); p.x = abs(p.x - size/2.); p.x = wrap(p.x + time/6.); gl_FragColor = texture2D(webcam, p); }

Case Study: Quasicrystal

precision mediump float; varying vec2 position; uniform float time; float wave(vec2 p, float angle) { vec2 direction = vec2(cos(angle), sin(angle)); return cos(dot(p, direction)); } float wrap(float x) { return abs(mod(x, 2.)-1.); } void main() { vec2 p = (position - 0.5) * 50.; float brightness = 0.; for (float i = 1.; i <= 11.; i++) { brightness += wave(p, time / i); } brightness = wrap(brightness); gl_FragColor.rgb = vec3(brightness); gl_FragColor.a = 1.; }

Noise

precision mediump float; varying vec2 position; uniform float time; float random(float p) { return fract(sin(p)*10000.); } float noise(vec2 p) { return random(p.x + p.y*10000.); } vec2 sw(vec2 p) {return vec2( floor(p.x) , floor(p.y) );} vec2 se(vec2 p) {return vec2( ceil(p.x) , floor(p.y) );} vec2 nw(vec2 p) {return vec2( floor(p.x) , ceil(p.y) );} vec2 ne(vec2 p) {return vec2( ceil(p.x) , ceil(p.y) );} float smoothNoise(vec2 p) { vec2 inter = smoothstep(0., 1., fract(p)); float s = mix(noise(sw(p)), noise(se(p)), inter.x); float n = mix(noise(nw(p)), noise(ne(p)), inter.x); return mix(s, n, inter.y); return noise(nw(p)); } float movingNoise(vec2 p) { float total = 0.0; total += smoothNoise(p - time); total += smoothNoise(p*2. + time) / 2.; total += smoothNoise(p*4. - time) / 4.; total += smoothNoise(p*8. + time) / 8.; total += smoothNoise(p*16. - time) / 16.; total /= 1. + 1./2. + 1./4. + 1./8. + 1./16.; return total; } float nestedNoise(vec2 p) { float x = movingNoise(p); float y = movingNoise(p + 100.); return movingNoise(p + vec2(x, y)); } void main() { vec2 p = position * 6.; float brightness = nestedNoise(p); gl_FragColor.rgb = vec3(brightness); gl_FragColor.a = 1.; }