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
Name | Type | Default | Description |
---|---|---|---|
videoSrc | string | - | The source URL of the video to be played in the background. |
meshColor | string | "#4a90e2" | The color of the WebGL mesh overlay. |
meshDensity | number | 25 | The density of the WebGL mesh overlay. |
distortionIntensity | number | 1.5 | The 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>
);
}