Virtual Drugs
Browser webcam-effects toy: two working WebGL passes — an autonomous hue/distortion/kaleidoscope effect and a genuine Laplacian-pyramid Eulerian video magnification pipeline — with optional audio reactivity. Five more effect buttons are labels with nothing behind them.
Virtual Drugs puts the laptop camera on a full-screen WebGL quad and runs a fragment shader over the live feed. Two effects are actually implemented. "LSD" is an autonomous pass — hue rotation, saturation cycling, wave distortion, zoom breathing, chromatic aberration, plus optional kaleidoscope, fractal-fold and liquid warp — that animates on its own and is only enhanced, not driven, by music. "DXM" is a real multi-pass implementation of Eulerian video magnification: Gaussian and Laplacian pyramids built in render targets, per-level second-order Butterworth IIR temporal filtering with ping-pong buffers, amplification, and pyramid collapse — the technique that makes a pulse or a small vibration visible in an ordinary video. Audio is optional: a PHP endpoint lists whatever files are in the audio directory, and a Web Audio analyser splits the spectrum into bass/mid/treble bands that feed the effect parameters through a master influence slider. Five further buttons — mushrooms, DMT, MDMA, ketamine, cannabis — are present in the UI as placeholders with no shader behind them. Everything runs client-side; nothing is uploaded and no video leaves the browser. Feature work stopped in July 2025.
- JavaScript
- GLSL
- Three.js
- WebGL
- Web Audio API
- MediaDevices API
- Service Worker API
- Tailwind CSS
- PHP
- Apache
- ESLint
- Prettier
Virtual Drugs is a single-page WebGL toy that treats the webcam feed as a signal to process rather than a picture to decorate. The camera stream becomes a texture on a full-screen quad, a fragment shader rewrites it every frame, and that is the entire application — no 3D objects, no overlays, no compositing of anything that was not already in the frame.
What is built
Two of the seven effect buttons are wired to real shaders.
- LSD — a colour and geometry pass that runs on its own clock: hue rotation with a wave pattern across the frame, saturation cycling, sine/cosine spatial distortion, a slow zoom "breath", and chromatic aberration from RGB channel offsets. Optional sub-modes fold the image through a kaleidoscope, a fractal UV remap, and a liquid warp. Sliders expose hue speed, distortion amount, kaleidoscope segments and fractal iterations live.
- DXM — Eulerian video magnification, done properly rather than faked. Each frame is decomposed into a Gaussian pyramid and then a Laplacian pyramid across four levels of WebGL render targets; every level is passed through a second-order Butterworth bandpass IIR filter whose coefficients are computed from a user-set frequency band in Hz; the filter's per-pixel state is carried between frames in ping-pong buffers; the filtered bands are amplified and the pyramid is collapsed back into an image. Controls cover amplification factor, the low and high cutoff frequencies, pyramid depth, chromatic attenuation, and a motion / colour / both mode switch. This is the part of the project worth keeping: it is the technique that reveals a heartbeat in the skin or a structural vibration too small to see, running at interactive rates in a browser.
Audio
Music is optional and enhances the effects rather than driving them — the visuals look the same with the sound off, just steadier. A small PHP endpoint scans the audio directory and returns whatever MP3/WAV/OGG/M4A files are sitting there, which the UI renders as a dropdown; the deployed instance ships two tracks from the author's own catalogue. A Web Audio analyser splits the FFT into bass (0–10% of the spectrum), mid (10–50%), treble (50–100%) and an overall amplitude, and a master "audio influence" slider scales how hard those numbers push the shader uniforms. There is no autoplay; Chrome will not create an audio context without a click, and the UI is built around that.
How it is put together
Three.js does the render-target and material plumbing, but the
interesting code is the GLSL. Effects are separate shader classes
extending a common BaseShader that supplies the
vertex shader, the mirrored UVs, aspect correction and the shared
uniforms; switching effects swaps the whole material on the quad
instead of toggling dead branches inside one giant shader. There
is no build step — the page imports Three.js through an
importmap and is served as static files by Apache
alongside the one PHP endpoint. ESLint and Prettier are
configured; a service worker and a web app manifest make it
installable, with URL shortcuts that jump straight to either
effect.
Nothing is collected. The video never leaves the page, there is no database and no account, and the only server-side code is the directory listing for the audio dropdown.
What is planned, and what is only a label
The five remaining buttons — mushrooms, DMT, MDMA, ketamine, cannabis — have no shader behind them. Clicking one clears the active effect and flips its own label to "ON" while the image stops changing, which is the most visible rough edge in the build. The repository carries a long design document with worked-out classes and GLSL for each of them, so they are specified rather than started. Also plumbed but unused: a hand-position uniform pair in the base shader with nothing feeding it, a frame-feedback/trail uniform that the LSD shader declares and never reads, and four further shader classes (ASCII, ripple, kaleidoscope, whirlpool) that are written but not imported. The roadmap beyond that — recording and export, preset save/load, beat and onset detection, face masking, adaptive quality — is a wish list, not work in progress.
Status
Dormant. The last feature work landed in July 2025 and the only change since has been repository housekeeping. The deployment is still up and still works: grant the camera, pick LSD or DXM, and the shader runs. It is kept in the portfolio for the magnification pipeline and for the effect-rack UI pattern, both of which are worth reusing somewhere with a reason to exist.
Build something like this
Want a tool like this for your shop?
We've shipped this kind of thing before. Twenty-minute intro call, no slides.