import { useRef, useEffect, useMemo, forwardRef } from "react";
import { Instance, Instances } from "@react-three/drei";
import { useGLTFWithKTX2 } from "../utils/useGLTFWithKTX2";
import { convertMaterialsToBasic } from "../utils/convertToBasic";
import * as THREE from "three";
const TreeSwayMaterial = forwardRef(({ time, ...props }, ref) => {
const uniforms = useRef({
time: { value: 0 },
swayAmount: { value: 0.3 },
swaySpeed: { value: 0.7 },
baseFrequency: { value: 0.8 },
map: { value: props.map },
});
useEffect(() => {
if (uniforms.current) {
uniforms.current.time.value = time;
}
}, [time]);
const vertexShader = `
uniform float time;
uniform float swayAmount;
uniform float swaySpeed;
uniform float baseFrequency;
attribute float instanceScale;
varying vec2 vUv;
varying float vHeight;
void main() {
vUv = uv;
vHeight = position.y;
// Normalize the height for easier calculations (0 at base, 1 at top)
float normalizedHeight = position.y / 10.0; // Divisor based on tree height, but honestly doesn't really matter too much
// Multi-frequency sway for more organic movement
float sway1 = sin(time * swaySpeed * 0.8 + position.x * baseFrequency) * 0.5;
float sway2 = cos(time * swaySpeed * 1.3 + position.z * baseFrequency * 1.7) * 0.3;
float sway3 = sin(time * swaySpeed * 0.5 + position.x * baseFrequency * 0.3) * 0.2;
// Combine sway effects with more influence at the top
float combinedSway = (sway1 + sway2 + sway3) * swayAmount;
float trunkStiffness = 1.0 - smoothstep(0.0, 0.3, normalizedHeight); // More stiff at bottom of tree
// Apply sway with height influence and trunk stiffness
vec3 swayedPosition = position;
swayedPosition.x += combinedSway * 0.3 * normalizedHeight * (1.0 - trunkStiffness);
swayedPosition.z += combinedSway * 0.4 * normalizedHeight * (1.0 - trunkStiffness);
// Add a slight vertical movement for leaf flutter
swayedPosition.y += sin(time * swaySpeed * 2.0 + position.x) * 0.02 * normalizedHeight;
// Some wind direction for variation
float windDirection = sin(time * 0.1) * 0.5 + 0.5;
swayedPosition.xz += windDirection * combinedSway * 0.1 * normalizedHeight;
// Adjust the position
vec4 modelPosition = instanceMatrix * vec4(swayedPosition, 1.0);
vec4 viewPosition = viewMatrix * modelPosition;
vec4 projectedPosition = projectionMatrix * viewPosition;
gl_Position = projectedPosition;
}
`;
const fragmentShader = `
uniform sampler2D map;
varying vec2 vUv;
varying float vHeight;
void main() {
// Use the texture with original colors
vec4 texColor = texture2D(map, vUv);
// Discard transparency pixels below threshold
if (texColor.a < 0.1) discard;
gl_FragColor = texColor;
}
`;
return (
);
});
export default function Model(props) {
const { nodes, materials } = useGLTFWithKTX2("/models/Eighth.glb");
const newMaterials = useMemo(
() => convertMaterialsToBasic(materials),
[materials]
);
const materialRef = useRef();
return (
);
}