Media Shader

v1.0.0
FreeWebGLInteractiveReduced MotionTailwind

An ultra-premium WebGL-based media distortion component that creates beautiful interactive liquid chromatic ripples, wave physics, and refractions on images or videos on hover.

Media Shader

Installation

npx vectorvesper add media-shader

Run npx vectorvesper init once first to set up your project.

Usage

Import

import { MediaShader } from "@/components/vv/media-shader";

Usage

<MediaShader />

Client-only component — disable SSR

This component uses WebGL and must be rendered client-side only.

import dynamic from "next/dynamic";

const ShaderImage = dynamic(
  () => import("@/components/vv/media-shader").then((m) => m.ShaderImage),
  { ssr: false }
);
This component respects prefers-reduced-motion and provides a graceful fallback.
Tailwind CSS must be configured in your project for styles to apply correctly.

Props

MediaShader is an ultra-premium WebGL-based media distortion component that projects standard image or video elements onto interactive GPU-accelerated planes. It creates organic liquid chromatic ripples, wave physics, and refractions on hover. Under the hood, it shares a single viewport-relative canvas to bypass context limits, and fails open gracefully to raw images/videos in reduced-motion or non-WebGL environments. Import it from @/components/vv/media-shader.

<ShaderImage />

A zero-configuration, drop-in <img> wrapper that renders the image with WebGL interactive shaders on hover.

PropTypeDefaultDescription
src*stringImage source URL.
altstring""Accessible image description.
preset"liquid-chromatic" | "curl-distortion" | "focus-loupe" | MediaShaderPreset"liquid-chromatic"The distortion effect preset to apply.
intensitynumber1.0Overall distortion strength multiplier.
noiseScalenumber1.0Spatial frequency scale (wobble density, loupe radius, etc.).
idlenumber0.5Ambient resting drift when not hovered (0 = still, 1 = full motion).
paramsreadonly number[]Array of 4 floating point numbers mapped to `u_params` vec4 in custom fragment shaders.

<ShaderVideo />

A drop-in <video> wrapper that renders video with WebGL interactive shaders on hover. Defaults to autoplay, loop, and muted.

PropTypeDefaultDescription
src*stringVideo source URL.
preset"liquid-chromatic" | "curl-distortion" | "focus-loupe" | MediaShaderPreset"liquid-chromatic"The distortion effect preset to apply.
intensitynumber1.0Overall distortion strength multiplier.
noiseScalenumber1.0Spatial frequency scale (wobble density, loupe radius, etc.).
idlenumber0.5Ambient resting drift when not hovered (0 = still, 1 = full motion).
paramsreadonly number[]Array of 4 floating point numbers mapped to `u_params` vec4 in custom fragment shaders.
autoPlaybooleantrueAutoplay the video.
loopbooleantrueLoop the video.
mutedbooleantrueStart muted (required for autoplay).
playsInlinebooleantrueInline playback on mobile.

Examples

Default Image (Liquid Chromatic)
<ShaderImage src="/hero.jpg" alt="Chromatic Liquid" preset="liquid-chromatic" />
Video with Curl Distortion
<ShaderVideo src="/clip.mp4" preset="curl-distortion" intensity={1.5} />
Focus Loupe on Image
<ShaderImage src="/hero.jpg" alt="Circular Magnifier" preset="focus-loupe" noiseScale={2.0} />
Client-component friendly. During SSR, the component outputs a standard image or video element immediately so no layout shift or hydration mismatch happens.
Bypasses WebGL context limits. Rather than creating a WebGL canvas per element, it uses a single global full-viewport canvas and textures registered media directly, pausing off-screen elements for extreme performance.
Automatically respects prefers-reduced-motion and displays the raw un-distorted element to avoid motion-induced issues.
Default presets include 'liquid-chromatic', 'curl-distortion', and 'focus-loupe'. Custom shaders can be passed directly as a preset object matching the MediaShaderPreset shape.

Source

export * from "./MediaShader";
View on GitHub →Report an issue