Skip to content

perf: optimize canvas rendering loops and options change checks - #17

Merged
DavidHDev merged 1 commit into
DavidHDev:mainfrom
phh235:perf/optimize-canvas-render-loops
Jul 26, 2026
Merged

perf: optimize canvas rendering loops and options change checks#17
DavidHDev merged 1 commit into
DavidHDev:mainfrom
phh235:perf/optimize-canvas-render-loops

Conversation

@phh235

@phh235 phh235 commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

This PR implements performance optimizations to reduce idle CPU/GPU consumption and avoid redundant calculations/re-renders during parent component updates:

Dynamic Animation Loop Control (Viewport & Tab Visibility):

  • Landing Page Loops: Optimized HeroReel (hero-reel.tsx) and HeroReveal (hero-reveal.tsx) to pause their requestAnimationFrame loops when the components scroll out of the viewport (using IntersectionObserver) or when the browser tab is hidden (using the document visibilitychange event).
  • WebGL/Three.js Loops: Refactored rendering loop lifecycle in GlassObjectVanilla, DitheredObjectVanilla, and ParticleObjectVanilla. Instead of running an empty animation loop inside renderer.setAnimationLoop when out of view, the loop is completely halted (setAnimationLoop(null)) and resumed dynamically.

Redundant Options Updates Elimination (Shallow Parameter Checks):

  • Modified setOptions(next) inside WebGL vanilla files to perform shallow parameter checks on primitive properties (filtering out React callback functions like onLoad or onError).
  • If none of the configuration options have changed, the method returns early and updates only the callbacks. This avoids running expensive WebGL updates, Three.js environment updates, WebGLRenderTarget resizing, and asset re-loading pipelines on every parent component re-render.

Performance Comparison

Measurements were taken using Chrome DevTools (Performance Monitor) on idle state (scrolled down below the fold, rendering elements out of view):

Metric Before Optimization (main) After Optimization (this branch) Improvement
Idle CPU Usage ~15% - 25% ~0% - 1% ~95% Reduction
Idle Frame Rate (FPS) 60 FPS / 120 FPS 0 FPS (Idle) 100% GPU Rest
Animation Loop Overhead Continuously runs requestAnimationFrame Loops completely paused Zero idle loop execution

Verification Steps (How to review)

  1. Checkout to this branch and run npm run dev.
  2. Open Chrome DevTools (F12), click More Tools -> Performance monitor.
  3. Go to the Home Page (/) and scroll down to the bottom.
  4. Observe CPU Usage and FPS Meter:
    • Notice that CPU drops to 0% and canvas renders stop when out of view.
  5. Go to the Playground (/playground), open the controls drawer, and change any option.
    • Using React DevTools Profiler, observe that intermediate re-renders do not trigger expensive Three.js geometry/material reconstructions unless the relevant parameter actually changes.

No CSS or styling classes were altered.

Type of change

  • Component improvement
  • Performance Optimization

Checklist

  • npx tsc --noEmit passes
  • npm run lint passes
  • npm run build passes
  • Tested the WebGL overlay fallback (flag off / Safari / Firefox), if a component changed

- Pause requestAnimationFrame loops in hero-reel and hero-reveal when scrolled out of view or tab is hidden
- Dynamically toggle WebGL setAnimationLoop (start/stop) on visibility changes for GlassObject, DitheredObject, and ParticleObject
- Add shallow comparison for primitive configuration properties in setOptions to prevent redundant WebGL/Three.js updates on re-render
@DavidHDev

Copy link
Copy Markdown
Owner

Really nice, thanks for the improvements.

@DavidHDev
DavidHDev merged commit bcaa9cb into DavidHDev:main Jul 26, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants