import React, { useRef } from "react";
import { useFrame, extend } from "@react-three/fiber";
import { shaderMaterial, Plane } from "@react-three/drei";
import * as THREE from "three";
import { easing } from "maath";
import vertexShader from "@/shaders/topography.vert";
import fragmentShader from "@/shaders/topography.frag";
// --- 1. SHADER: FLUID TOPOGRAPHY ---
const TopographyMaterial = shaderMaterial(
{
uTime: 0,
uColor: new THREE.Color("#e0e0e0"),
uResolution: new THREE.Vector2(1, 1),
uOpacity: 1.0,
uLineOpacity: 0.4,
uScale: 3.0,
uLineThickness: 0.03,
},
vertexShader,
fragmentShader
);
extend({ TopographyMaterial });
export function TopologyBackground({
isZoomedIn = false,
quality = 1,
color = "#e0e0e0",
opacity = 0.4,
speed = 0.05,
scale = 3.0,
lineThickness = 0.03,
}) {
const materialRef = useRef();
// Fixed world-space dimensions (doesn't change with camera zoom)
const planeWidth = 90;
const planeHeight = 40;
useFrame((_, delta) => {
if (!materialRef.current) return;
materialRef.current.uTime += delta * (speed / 0.05); // Normalize speed
materialRef.current.uResolution.set(planeWidth, planeHeight);
materialRef.current.uColor.set(color);
materialRef.current.uLineOpacity = opacity;
materialRef.current.uScale = scale;
materialRef.current.uLineThickness = lineThickness;
// Tween opacity based on zoom state
const targetOpacity = isZoomedIn ? 0.25 : 1.0;
easing.damp(materialRef.current, "uOpacity", targetOpacity, 0.3, delta);
});
// Low quality mode: render simple solid color plane (no shader)
if (quality < 0.5) {
return (
);
}
return (
// Pass the calculated Width/Height to the geometry
);
}