r3f-performance-optimization
Use when optimizing React Three Fiber scenes, experiencing frame drops, high draw calls, or implementing 3D performance features - ensures systematic performance analysis and applies proven optimization patterns for smooth 60fps rendering
- License 许可
- MIT
- 最近更新
- 2026-03-19
- Stars
- ★ 1
- Forks
- 0
01 前言 Front Matter
- name
- r3f-performance-optimization
- description
- Use when optimizing React Three Fiber scenes, experiencing frame drops, high draw calls, or implementing 3D performance features - ensures systematic performance analysis and applies proven optimization patterns for smooth 60fps rendering
02 资源文件 5
- 参考文档agents/openai.yaml308 B
- 参考文档evals/evals.json4.6 KB
- 参考文档evals/trigger-queries.json1.4 KB
- 参考文档references/edge-cases.md892 B
- 参考文档references/examples.md952 B
03 SKILL.md 正文
R3F Performance Optimization Skill
When This Skill Applies
Use this skill when:
- Frame rates drop below 60fps in R3F scenes
- Draw call count exceeds 500-1000
- Implementing new 3D features that may impact performance
- Scene contains many similar objects (>50 meshes)
- Static scenes render continuously
- Performance varies significantly across devices
- Memory usage grows during scene interaction
Performance Optimization Checklist
When optimizing R3F performance, complete each step systematically:
☐ 1. Measure Current Performance
Required before any optimization:
import { Stats } from '@react-three/drei'
// or
import { Perf } from 'r3f-perf'
<Canvas>
<Stats /> {/* Basic FPS/memory */}
<Perf position="top-left" /> {/* Advanced: calls, triangles, textures */}
<Scene />
</Canvas>
Record baseline metrics:
- Current FPS (target: 60fps)
- Draw call count (target: <500, max: 1000)
- Triangle/vertex count
- Memory usage patterns
☐ 2. Enable On-Demand Rendering
For static or mostly-static scenes:
<Canvas frameloop="demand">
{/* Only renders when props change or invalidate() called */}
</Canvas>
With manual control:
const { invalidate } = useThree()
// Before animation starts
invalidate()
requestAnimationFrame(() => {
// Synchronous animation
})
Impact: Can reduce CPU/GPU usage by 90%+ for static scenes.
☐ 3. Apply Instancing for Repeated Objects
When drawing >50 similar objects:
Replace individual meshes:
// BEFORE: 1000 draw calls
{objects.map(obj => <mesh key={obj.id} geometry={...} material={...} />)}
With InstancedMesh:
// AFTER: 1 draw call
<instancedMesh args={[geometry, material, 1000]}>
{/* Manage transforms programmatically */}
</instancedMesh>
Impact: 100-1000x draw call reduction.
☐ 4. Implement Level of Detail (LOD)
For objects at varying distances:
import { Detailed } from '@react-three/drei'
<Detailed distances={[0, 10, 20]}>
<HighPolyMesh /> {/* 0-10 units from camera */}
<MediumPolyMesh /> {/* 10-20 units */}
<LowPolyMesh /> {/* 20+ units */}
</Detailed>
Impact: Reduces vertex processing for distant objects without visible quality loss.
☐ 5. Reuse Geometries and Materials
Create once, reference many times:
// WRONG: Creates new geometry/material per mesh
function Cubes() {
return cubes.map(cube => (
<mesh>
<boxGeometry />
<meshStandardMaterial />
</mesh>
))
}
// CORRECT: Shared resources
const sharedGeometry = new THREE.BoxGeometry()
const sharedMaterial = new THREE.MeshStandardMaterial()
function Cubes() {
return cubes.map(cube => (
<mesh geometry={sharedGeometry} material={sharedMaterial} />
))
}
Critical: Each unique geometry/material requires GPU compilation.
☐ 6. Use Delta-Based Animations
Ensure refresh-rate independence:
useFrame((state, delta) => {
// WRONG: Fixed speed, varies by refresh rate
mesh.current.rotation.x += 0.01
// CORRECT: Same speed everywhere
mesh.current.rotation.x += delta * rotationSpeed
})
Best Practice: Mutate directly in useFrame, don't trigger React re-renders.
☐ 7. Implement Movement Regression
For dynamic quality scaling:
const { performance } = useThree()
useFrame(() => {
// Scale quality based on interaction
const pixelRatio = performance.current * 2 // 0-1 range
gl.setPixelRatio(pixelRatio)
})
// Trigger during interaction
const onInteraction = () => {
performance.regress()
}
Impact: Maintains smoothness during movement, restores quality when static.
☐ 8. Add Adaptive Quality Monitoring
For device-specific optimization:
import { PerformanceMonitor } from '@react-three/drei'
<PerformanceMonitor
onIncline={() => setQuality(q => Math.min(q + 1, 3))}
onDecline={() => setQuality(q => Math.max(q - 1, 1))}
>
<Scene quality={quality} />
</PerformanceMonitor>
Pattern: Adjust shadows, textures, effects, or instance counts based on FPS.
☐ 9. Optimize Asset Loading
Progressive loading strategy:
// Preload in background
useGLTF.preload('/heavy-model.glb')
// Nested Suspense for quality transitions
<Suspense fallback={<Placeholder />}>
<Suspense fallback={<LowQualityModel />}>
<HighQualityModel />
</Suspense>
</Suspense>
Key: useLoader automatically caches identical URLs.
☐ 10. Use React 18 Concurrent Features
For heavy synchronous operations:
import { startTransition } from 'react'
startTransition(() => {
// Heavy state updates distributed across frames
setMassiveDataset(computeExpensiveValue())
})
Benchmark: Maintains ~60fps vs ~5fps without transition.
Common Performance Anti-Patterns
When reviewing code, actively look for and fix:
❌ Creating resources in render
// WRONG
<mesh>
<boxGeometry args={[1, 1, 1]} /> {/* Creates new geometry every render */}
</boxGeometry>
❌ Excessive draw calls
- More than 1000 individual meshes
- Not using instancing for repeated objects
❌ Continuous rendering for static scenes
- No frameloop="demand" when scene is mostly static
❌ Fixed animation values
useFrame(() => {
mesh.rotation.x += 0.01 // WRONG: refresh-rate dependent
})
❌ Missing LOD for varied distances
- Same detail level for near and far objects
❌ Blocking heavy operations
- Synchronous operations without startTransition
Verification Steps
After applying optimizations, verify:
- FPS: Stable 60fps on target devices
- Draw calls: <500 (optimal), <1000 (max)
- Memory: No leaks during interaction
- Smoothness: No visible frame drops during animation
- Consistency: Performance across different refresh rates
When Optimizations Are Complete
Only mark optimization complete when:
- ✅ Baseline metrics recorded
- ✅ All applicable checklist items addressed
- ✅ Verification shows stable 60fps
- ✅ No performance anti-patterns remain
- ✅ Monitoring tools (Stats/Perf) integrated
Additional Resources
For advanced patterns, consult:
- Advanced Reference:
docs/r3f-jotai-advanced-reference.md - Scaling Performance: https://r3f.docs.pmnd.rs/advanced/scaling-performance
- Performance Pitfalls: https://docs.pmnd.rs/react-three-fiber/advanced/pitfalls
04 同仓库更多 Skills
writing-skills
Use when creating new skills, editing existing skills, or verifying skills work before deployment
writing-plans
Use when you have a spec or requirements for a multi-step task, before touching code
writing good code
use this skill whenever you write code. it provides a process for creating good, composable apis.
write-review-elixir
Review Elixir code. ALWAYS use this skill before or after you added code written in elixir to ensure high code quality. Also use use this when asked to review existing elixir code.
whats-next
Answers what to do next, what to work on next, where we're at
verification-before-completion
Use when about to claim work is complete, fixed, or passing, before committing or creating PRs - requires running verification commands and confirming output before making any success claims; evidence before assertions always