Case Study
Particles Cursor Animation Shader (Three.js + GLSL)
An image-to-particles transformation driven entirely by custom GLSL, where a cursor-controlled displacement canvas dynamically pushes particles away with a glowing trail. Built with Three.js, shader-based point rendering, and deployed to GitHub Pages via Vite.
The Problem
Create a high-performance cursor-driven particle interaction system where an image is reconstructed from GPU-rendered points and dynamically displaced in real time using a 2D canvas as a live displacement texture, while remaining portable to GitHub Pages.
Solution
- Converted a full-resolution image into a dense GPU-driven particle field using a subdivided PlaneGeometry with index disabled for true point rendering.
- Used a hidden 2D canvas as a live displacement texture, updated every frame with a fading trail buffer.
- Mapped cursor position to UV space via raycasting against an invisible interaction plane, so displacement stays aligned with the image.
- Generated radial displacement vectors per particle using randomized angles and intensity attributes controlled in the vertex shader.
- Applied smoothstep thresholding on the displacement texture to avoid harsh stepping and keep motion feeling fluid.
- Computed gl_PointSize in the vertex shader based on image brightness and depth attenuation for proper perspective.
- Stamped a glow sprite into the displacement canvas with velocity-based alpha to create a responsive trail effect.
- Configured Vite with a custom base path so the static build works cleanly on GitHub Pages.
Results
- Responsive cursor-driven particle repulsion with smooth temporal fading and no visible popping.
- Image remains recognizable while dynamically deforming under interaction, selling the illusion of a living photo.
- Stable frame rate on mid-range hardware with a high-resolution particle field.
- Self-contained demo deployed to GitHub Pages and linked directly from the portfolio.
Next
- Add curl-noise flow fields for idle particle motion when the cursor is still.
- Support multi-touch / mobile interactions by mapping multiple pointers into the displacement canvas.
- Move displacement simulation fully onto the GPU using a ping-pong framebuffer instead of a 2D canvas.
- Layer in post-processing bloom and additive glow to push the highlight energy further.