Docs
Mesh Matrix

Mesh Matrix

A dynamic hero section featuring a background video with an interactive WebGL mesh overlay that responds to mouse movement.

Creative Studio

Where imagination meets technology

Installation

Install the following dependencies:

npm install @react-three/fiber @react-three/drei three @types/three

Copy and paste the following code into your project.

components/ui/mesh-matrix.tsx

// @ts-nocheck - Disable type checking for Three.js components
"use client";
 
import React, { useRef } from "react";
import { Canvas, useFrame, useThree } from "@react-three/fiber";
import { useVideoTexture } from "@react-three/drei";
import type { Mesh, BufferGeometry } from "three";
import * as THREE from "three";
 
interface MeshProps {
  videoSrc: string;
  meshColor: string;
  meshDensity: number;
  distortionIntensity: number;
}
 
function VideoMesh({
  videoSrc,
  meshColor,
  meshDensity,
  distortionIntensity,
}: MeshProps) {
  const meshRef = useRef<Mesh>(null);
  const { viewport, mouse } = useThree();
  const texture = useVideoTexture(videoSrc);
 
  const geometry = new THREE.PlaneGeometry(
    viewport.width,
    viewport.height,
    meshDensity,
    meshDensity,
  );
 
  useFrame(({ clock }) => {
    if (!meshRef.current) return;
 
    const positions = (meshRef.current.geometry as BufferGeometry).attributes
      .position.array as Float32Array;
 
    const scaledMouseX = (mouse.x * viewport.width) / 2;
    const scaledMouseY = (mouse.y * viewport.height) / 2;
    const time = clock.getElapsedTime();
 
    for (let i = 0; i < positions.length; i += 3) {
      const x = positions[i];
      const y = positions[i + 1];
 
      const distance = Math.sqrt(
        Math.pow(x - scaledMouseX, 2) + Math.pow(y - scaledMouseY, 2),
      );
 
      const baseWave = Math.sin(distance * 0.3 + time) * 0.1;
      const mouseInfluence = Math.max(0, 1 - distance / 2);
      const distortion = mouseInfluence * distortionIntensity;
 
      positions[i + 2] = baseWave + distortion * Math.sin(distance - time);
    }
 
    (
      meshRef.current.geometry as BufferGeometry
    ).attributes.position.needsUpdate = true;
  });
 
  return (
    <mesh ref={meshRef} scale={[1, 1, 1]}>
      <primitive attach="geometry" object={geometry} />
      <meshBasicMaterial
        map={texture}
        wireframe
        color={meshColor}
        transparent
        opacity={0.3}
        side={THREE.DoubleSide}
      />
    </mesh>
  );
}
 
interface MeshMatrixProps {
  videoSrc: string;
  meshColor?: string;
  meshDensity?: number;
  distortionIntensity?: number;
  className?: string;
}
 
export function MeshMatrix({
  videoSrc,
  meshColor = "#ffffff",
  meshDensity = 30,
  distortionIntensity = 0.5,
  className = "",
}: MeshMatrixProps) {
  return (
    <div className={`relative h-full w-full ${className}`}>
      <Canvas
        camera={{ position: [0, 0, 5], fov: 75 }}
        style={{ position: "absolute", zIndex: 10 }}
      >
        <VideoMesh
          videoSrc={videoSrc}
          meshColor={meshColor}
          meshDensity={meshDensity}
          distortionIntensity={distortionIntensity}
        />
      </Canvas>
      <video
        src={videoSrc}
        className="absolute inset-0 h-full w-full object-cover dark:opacity-80"
        autoPlay
        loop
        muted
        playsInline
      />
    </div>
  );
}

Update the import paths to match your project setup.

import { MeshMatrix } from "@/components/ui/mesh-matrix";

Usage

import MeshMatrix from "@/components/ui/mesh-matrix";
 
export default function HeroSection() {
  return (
    <MeshMatrix
      videoSrc="/path-to-video.mp4"
      meshColor="#4a90e2"
      meshDensity={25}
      distortionIntensity={1.5}
    />
  );
}

Props

NameTypeDefaultDescription
videoSrcstring-The source URL of the video to be played in the background.
meshColorstring"#4a90e2"The color of the WebGL mesh overlay.
meshDensitynumber25The density of the WebGL mesh overlay.
distortionIntensitynumber1.5The intensity of the distortion effect applied to the WebGL mesh overlay.

Examples

Basic Usage

import MeshMatrix from "@/components/ui/mesh-matrix";
 
export default function HeroSection() {
  return <MeshMatrix videoSrc="/path-to-video.mp4" />;
}

Customization

import MeshMatrix from "@/components/ui/mesh-matrix";
 
export default function HeroSection() {
  return (
    <div className="relative h-[600px] w-full">
      <MeshMatrix
        videoSrc="/path-to-video.mp4"
        meshColor="#4a90e2"
        meshDensity={25}
        distortionIntensity={1.5}
      />
      <div className="absolute inset-0 flex items-center justify-center">
        <div className="z-10 text-center text-white">
          <h1 className="mb-4 text-5xl font-bold">Creative Studio</h1>
          <p className="text-xl">Where imagination meets technology</p>
        </div>
      </div>
    </div>
  );
}