mcpField
R
r3f-fundamentals

r3f-fundamentals

github.com/enzed开发1312.2k 次安装8 周前更新
代码仓库

关于 r3f-fundamentals

面向 React Three Fiber 开发者的基础技能,涵盖场景结构、渲染循环、类型和资源管理。内容强调根据项目已安装的版本选择 API,并检查渲染与清理行为。

主要功能

  1. 01场景与 Canvas 结构
  2. 02Fiber Hooks 和类型边界
  3. 03渲染循环与按需渲染
  4. 04渲染器设置注意事项
  5. 05资源所有权与清理

适用场景

  1. 01搭建基础 R3F 场景
  2. 02排查版本相关的 API 用法
  3. 03实现按需渲染的场景
  4. 04检查资源释放及组件卸载

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/enzed/r3f-skills --skill r3f-fundamentals

安装后在 Claude Code 中输入/r3f-fundamentals确认已加载。

附带文件references/renderers.md

详细介绍

React Three Fiber 基础知识

选择合适的基准版本

  • 选择 API 前,先检查项目的清单文件和锁文件。这些示例针对 Fiber 9 / React 19;Fiber 8 与 React 18 配套。不要仅为匹配示例而升级项目。
  • 同时检查已安装的 Three.js 和 Drei 版本。使用与这些版本匹配的已发布文档;如果找不到,请说明不确定之处,不要凭空编造属性。
  • 除非任务要求更改,否则保留现有渲染器。对于 WebGPU,请阅读渲染器选择;Fiber 10 alpha API 并非 Fiber 9 API。

最小场景

此示例拥有自己的 Canvas。其父元素的高度必须非零。

import { useRef } from 'react'
import { Canvas, useFrame, type ThreeElements } from '@react-three/fiber'
import type { Mesh } from 'three'

function RotatingBox(props: ThreeElements['mesh']) {
  const mesh = useRef<Mesh>(null)
  useFrame((_, delta) => {
    if (mesh.current) mesh.current.rotation.y += delta * 0.5
  })
  return (
    <mesh {...props} ref={mesh}>
      <boxGeometry args={[1, 1, 1]} />
      <meshStandardMaterial color="coral" />
    </mesh>
  )
}

export default function Example() {
  return (
    <Canvas camera={{ position: [0, 0, 5] }} dpr={[1, 2]}>
      <ambientLight intensity={0.5} />
      <directionalLight position={[3, 4, 5]} intensity={2} />
      <RotatingBox />
    </Canvas>
  )
}

场景和类型边界

  • 在 Canvas 下方的组件中调用 useThree、useFrame 和加载器 Hook;绝不要在创建该 Canvas 的组件中或事件回调中调用。
  • Canvas 的子元素是 Three.js 对象。将 DOM UI 放在 Canvas 外部,或使用 Drei Html。Canvas 内部的 Suspense 回退也必须遵守相同规则。
  • 网格属性使用 ThreeElements['mesh'],引用使用 useRef<Mesh>(null)。Fiber 9 对自定义元素使用 ThreeElement<typeof Class>;不要使用已移除的 Object3DNode 或全局 JSX.IntrinsicElements 扩展。
  • 在 Fiber 9 中,extend(Class) 会创建本地类型化组件。只有确实需要共享的小写 JSX 元素时,才使用 extend({ Class }) 并扩展 @react-three/fiber 模块。
  • args 是构造函数参数:更改它们会重建对象。动画应更新普通属性或引用;如果输入未变,则保留开销较大的形状、数组和材质。
  • 几何体和材质子元素会自动附加。其他属性请使用显式的 attach,例如对缓冲属性使用 attach="attributes-position"。
  • Three.js 使用弧度和局部变换。将世界空间输入转换到对象的父级空间后,再赋值给 position。

渲染循环的选择

  • 离散的 UI 变化使用 React 状态;逐帧运动则改变自己拥有的引用。重复使用临时向量,并使用以秒为单位的 delta。不要为同一场景创建第二个动画循环。
  • useThree(state => state.camera) 会订阅相机替换,而不是 camera.position 的变化。在 useFrame 内读取瞬时值;命令式更改相机投影后,更新投影矩阵。
  • 默认的 frameloop="always" 适用于连续动画。对于可以静止的场景,使用 "demand":命令式更改需要调用 invalidate(),动画也必须持续触发失效,直到稳定。Drei 控件会自行处理失效。
  • 负的帧优先级用于排序更新,不会接管渲染。正的优先级会禁用自动渲染:其所属组件必须负责渲染,并与任何合成器协调。回调按优先级升序运行。
  • 不要在 JSX 中重置变换,又由另一个组件为相同的值制作动画。可见性变化不会自动停止回调或释放 GPU 资源。

渲染器与所有权陷阱

  • 默认 WebGL Canvas 使用 sRGB 输出和 ACES 胶片式色调映射。flat 会选择 NoToneMapping;linear 会更改输出色彩空间。两者都不是解决素材褪色问题的通用方法。
  • 在 Three.js r182 及更高版本中,使用 shadows="percentage" 启用 PCF 阴影。在此基线版本中,Fiber 9 中不带值的 shadows 会选择已弃用的 PCFSoftShadowMap。
  • 从默认设置开始;只有确有需求时才添加 preserveDrawingBuffer、提高 DPR 或增加额外渲染通道,并衡量其开销。
  • 卸载时,R3F 会释放以声明方式拥有的对象。<primitive object={...}> 不会释放所提供的对象。缓存的加载器素材和共享资源需要明确的所有者;只要还有其他使用者,就不要释放它们。
  • dispose={null} 会让子树不参与自动释放;它不是通用的性能开关。R3F 所有权之外手动分配的资源需要清理。
  • 效果、订阅和命令式注册必须能经受 Strict Mode 的设置与清理。在添加记忆化之前先进行性能分析;普通的 React 渲染本身不会重启 useFrame 动画。

验证

进行类型检查,在浏览器中渲染,检查控制台,调整窗口大小,并卸载后重新挂载。对于按需渲染,请验证它既能唤醒,也能恢复空闲状态。

来源

评论

支持 Markdown