Skip to main content

Overview

Paper Shaders are designed for maximum performance, but understanding the optimization options helps you deliver smooth experiences across all devices.

Automatic Optimizations

Paper Shaders includes several automatic performance optimizations:

Automatic Pausing

Shaders automatically pause when the browser tab is hidden:

Smart Resolution Scaling

Shaders automatically adjust rendering resolution based on:
  • Device pixel ratio (retina displays)
  • Browser zoom level
  • Pinch zoom on mobile
  • Container size changes

Uniform Caching

Only changed uniforms trigger GPU updates:

Resolution Control

Min Pixel Ratio

Controls minimum rendering quality:
Impact:
  • minPixelRatio={1}: Matches CSS pixels, fastest
  • minPixelRatio={2}: 4x pixels, great quality/performance balance (default)
  • minPixelRatio={3}: 9x pixels, ultra-sharp but slower
On 1x displays, minPixelRatio={2} still renders at 2x for better antialiasing. On 2x displays (retina), it renders at actual device resolution.

Max Pixel Count

Limits total rendered pixels regardless of display size:
When to adjust:
  • Lower for mobile-first sites
  • Lower for complex shaders with many colors
  • Higher for desktop applications with large displays
  • Higher for simpler shaders on powerful hardware

Responsive Resolution

Adjust resolution based on device:

Animation Performance

Static Shaders

Static shaders (speed=0) have zero ongoing performance cost:
Best for:
  • Background textures
  • Hero sections that don’t need motion
  • Mobile devices
  • Battery-conscious applications

Reduced Animation Speed

Slower animations use less CPU:

Conditional Animation

Animate only when visible:
The browser’s Page Visibility API automatically pauses shaders in background tabs. This Intersection Observer pattern further optimizes for scrolled-out-of-view shaders.

Shader Complexity

Color Count

Fewer colors = better performance:
Performance impact:
  • Each color adds GPU calculations
  • 2-4 colors: minimal impact
  • 5-7 colors: noticeable on low-end devices
  • 8+ colors: avoid on mobile

Parameter Complexity

Some parameters are more expensive:
Optimization strategy:
  • Start with low/zero grain parameters
  • Increase only if needed visually
  • Test on target devices

Image-Based Shaders

Image Size

Larger images require more memory and processing:
Best practices:
  • Resize images to actual display size
  • Use WebP or AVIF for better compression
  • Aim for 1024×1024 or smaller for filters
  • Use 2048×2048 max for high-quality needs

Mipmaps

Enable mipmaps for better performance with large images:

Image Loading

Preload images to avoid stutters:

Multiple Shaders

Lazy Loading

Load shaders on demand:

Stagger Initialization

Initialize shaders one at a time:

Limit Active Shaders

Only render visible shaders:

Memory Management

Proper Cleanup

Always dispose shaders when unmounting:
Failing to dispose vanilla shaders causes memory leaks. Always call dispose() when removing shaders from the page.

Stable References

Avoid creating new arrays on every render:

WebGL Context

Context Limits

Browsers limit concurrent WebGL contexts (typically 8-16):
Best practices:
  • Limit to 3-5 simultaneous shaders per page
  • Dispose unused shaders to free contexts
  • Show fallback content if contexts exhausted

Context Attributes

Optimize context creation:

Monitoring Performance

FPS Monitoring

Chrome DevTools

Use Chrome’s Performance panel:
1

Open DevTools

Press F12 or Cmd+Option+I
2

Go to Performance tab

Enable “Screenshots” and “Web Vitals”
3

Record

Click record, interact with shaders, stop recording
4

Analyze

Look for long frames (>16ms for 60fps) and GPU activity

Memory Profiling

1

Open Memory tab in DevTools

Take heap snapshots before and after shader operations
2

Look for retained memory

Check if memory grows after disposing shaders
3

Find leaks

Compare snapshots to identify undisposed resources

Performance Checklist

  • Set speed={0} for static shaders
  • Use minPixelRatio={1} on mobile
  • Limit colors to 3-5 for mobile
  • Dispose shaders properly (vanilla only)
  • Optimize images to 2048×2048 or smaller
  • Reduce maxPixelCount on mobile
  • Pause shaders when out of viewport
  • Lazy load shader components
  • Use stable color references
  • Minimize grain parameters
  • Limit simultaneous shaders to 3-5
  • Test on actual mobile devices
  • Check FPS with DevTools
  • Monitor memory usage
  • Test on low-end devices
  • Verify battery impact

Performance Targets

Desktop

  • 60 FPS with 2-3 shaders
  • 2x pixel ratio
  • Full color complexity
  • Smooth animations

Mobile

  • 30-60 FPS with 1-2 shaders
  • 1-1.5x pixel ratio
  • Reduced color count
  • Consider static shaders

Low-End Devices

  • 30 FPS with 1 shader
  • 1x pixel ratio
  • Minimal colors (2-3)
  • Static shaders preferred

Troubleshooting

Low FPS

1

Reduce pixel ratio

Try minPixelRatio={1}
2

Lower max pixel count

Try maxPixelCount={1920 * 1080 * 2}
3

Simplify shader

Reduce colors, disable grain effects
4

Check other shaders

Limit to 1-2 simultaneous shaders

High Memory Usage

  • Dispose unused shaders
  • Optimize image sizes
  • Reduce number of simultaneous shaders
  • Check for memory leaks with DevTools

Stuttering

  • Preload images
  • Use stable prop references
  • Avoid creating new objects in render
  • Check browser’s Performance tab for long frames

Next Steps

Sizing & Fit

Optimize shader sizing for performance

Customization

Balance visual quality with performance

React Usage

React-specific performance patterns

Vanilla Usage

Vanilla JS performance control