Distorted Pixels is a cyberpunk-flavored interactive WebGL experiment built with Three.js.
A static image is pushed through a shader pipeline and warped in real time by pointer velocity, creating a living glitch field that feels like dragging your hand through a neon data stream.
- Real-time pixel displacement using a
THREE.DataTexture. - Pointer-driven distortion with velocity memory and relaxation decay.
- Four curated demo presets (
index.htmltoindex4.html). - Custom GLSL shader pair wired through
js/shaders.js. - Lightweight setup: no bundler required, just a static server.
Three.js(local module atjs/lib/three.module.js)GLSLshaders (js/shaders.js, plus source files injs/shader/)lil-guifor live parameter tuning (js/lib/lil-gui.module.min.js)- HTML/CSS/JavaScript (ES modules)
DistortedPixels/
|- index.html # Demo 1 preset
|- index2.html # Demo 2 preset
|- index3.html # Demo 3 preset
|- index4.html # Demo 4 preset (GUI visible)
|- css/
| |- base.css # Layout, typography, and cyber UI styling
|- img/
| |- cyberdemo.jpg # Source image sampled by the shader
|- js/
| |- app.js # Three.js scene setup + interaction logic
| |- shaders.js # Inlined vertex/fragment shaders used at runtime
| |- shader/
| | |- vertex.glsl
| | |- fragment.glsl
| | |- vertexParticles.glsl
| |- lib/
| | |- three.module.js
| | |- lil-gui.module.min.js
Because the project uses ES module imports, open it via a local server (not directly as file://).
# option 1: Python
python3 -m http.server 5173
# option 2: Node (if installed)
npx serve .Then open:
http://localhost:5173/index.htmlhttp://localhost:5173/index2.htmlhttp://localhost:5173/index3.htmlhttp://localhost:5173/index4.html
The effect is tuned through data-* attributes on #canvasContainer in each index*.html file and read in js/app.js:
data-grid: resolution of the displacement field.data-mouse: radius of pointer influence.data-strength: intensity of velocity injection into the field.data-relaxation: decay factor each frame (higher = slower fade).
index4.html uses body.demo-4, which makes the lil-gui panel visible (hidden in the other presets by CSS).
- A square
DataTextureis generated as a dynamic offset grid. - Pointer movement writes velocity energy into nearby grid cells.
- Each frame, values are damped by
relaxationto create trailing motion. - The fragment shader samples the image with UV offsets (
offset.rg) to produce the glitch displacement.
demo 1(index.html): balanced, cinematic baseline.demo 2(index2.html): high-density grid, tighter but richer distortion field.demo 3(index3.html): chunkier pixel feel with lower grid resolution.demo 4(index4.html): similar to demo 3 with live GUI enabled.
- Swap
img/cyberdemo.jpgwith your own texture for a new atmosphere. - Edit shader code in
js/shaders.jsfor immediate runtime changes. - Keep canonical shader source in
js/shader/*.glslif you prefer external GLSL organization. - Adjust per-demo
data-*values to design different interaction moods.
data-mobile-srcis present in HTML presets but is not currently consumed injs/app.js.- The renderer clamps pixel ratio to
2for performance balance on high-DPI screens. - Pointer events are used (
pointerdown,pointermove,pointerup) for desktop/mobile input compatibility.
Created by Csaba Farkas (Sylenia Inc.)
- GitHub:
https://github.com/Sylenia - LinkedIn:
https://www.linkedin.com/in/csaba-farkas-chess-trainer-scrum-master-coach/