| 271 | const frameTime = 1000 / targetFPS; |
| 272 | |
| 273 | const animate = (currentTime: number) => { |
| 274 | if ( |
| 275 | !materialRef.current || |
| 276 | !rendererRef.current || |
| 277 | !sceneRef.current || |
| 278 | !cameraRef.current |
| 279 | ) |
| 280 | return; |
| 281 | |
| 282 | const deltaTime = currentTime - lastTime; |
| 283 | |
| 284 | if (deltaTime >= frameTime) { |
| 285 | timeRef.current += 0.016 * rotationSpeed; |
| 286 | materialRef.current.uniforms.uTime.value = timeRef.current; |
| 287 | rendererRef.current.render(sceneRef.current, cameraRef.current); |
| 288 | lastTime = currentTime - (deltaTime % frameTime); |
| 289 | } |
| 290 | |
| 291 | rafRef.current = requestAnimationFrame(animate); |
| 292 | }; |
| 293 | rafRef.current = requestAnimationFrame(animate); |
| 294 | |
| 295 | // Handle resize with debouncing |