mcpField
R
r3f-shaders

r3f-shaders

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

关于 r3f-shaders

面向 React Three Fiber 开发者的着色器编写技能,提供 WebGL 自定义材质及内置材质修改的实现指导,并涵盖版本、渲染管线与着色器常见问题。

主要功能

  1. 01选择 WebGL 或 WebGPU 着色器路径
  2. 02使用 Drei shaderMaterial 创建动画材质
  3. 03管理 uniform 与着色器编译
  4. 04处理坐标空间和颜色管理
  5. 05为变形几何体配置法线与阴影
  6. 06通过 onBeforeCompile 修改内置材质

适用场景

  1. 01为 React Three Fiber 场景编写动画材质
  2. 02排查 GLSL 编译及颜色输出问题
  3. 03让顶点变形与光照、阴影保持一致

安装

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

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

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

附带文件references/webgpu.md

详细介绍

React Three Fiber 着色器

选择着色器路径

先检查已安装的 Fiber、Drei、Three.js 和渲染器版本。此示例使用 Fiber 9 / React 19 和 WebGL。保留现有项目的版本。

  • 如果内置材质的属性能够表达所需效果,就使用内置材质。对于自定义 WebGL 着色,使用 Drei shaderMaterial 或原生 <shaderMaterial>。
  • WebGPU 使用节点材质和 TSL;GLSL ShaderMaterial 和 onBeforeCompile 无法移植到 WebGPU。只有在相关渲染器适用时,才阅读 WebGPU and TSL。
  • 着色器不会自动支持光照、阴影、雾效、实例化或蒙皮。替换内置材质前,先确定所需功能。

WebGL 动画材质

在 Canvas 下挂载。将材质类和 extend 调用放在渲染函数外;局部组件可避免全局 JSX 扩展。

import { useRef } from 'react'
import { extend, useFrame } from '@react-three/fiber'
import { shaderMaterial } from '@react-three/drei'
import { Color } from 'three'

const WaveMaterial = shaderMaterial(
  { uTime: 0, uColor: new Color('coral') },
  `uniform float uTime;
   varying vec2 vUv;
   void main() {
     vUv = uv;
     vec3 p = position;
     p.z += sin(p.x * 4.0 + uTime) * 0.15;
     gl_Position = projectionMatrix * modelViewMatrix * vec4(p, 1.0);
   }`,
  `uniform vec3 uColor;
   varying vec2 vUv;
   void main() {
     gl_FragColor = vec4(uColor * (0.4 + 0.6 * vUv.y), 1.0);
     #include <tonemapping_fragment>
     #include <colorspace_fragment>
   }`,
)
const Wave = extend(WaveMaterial)

export default function Example() {
  const material = useRef<InstanceType<typeof WaveMaterial>>(null)
  useFrame((_, delta) => {
    if (material.current) material.current.uTime += delta
  })
  return (
    <mesh>
      <planeGeometry args={[3, 3, 32, 32]} />
      <Wave ref={material} key={WaveMaterial.key} />
    </mesh>
  )
}

Uniform 和编译

  • Drei shaderMaterial 会创建 uniform 访问器:赋值给 material.uTime。原生 ShaderMaterial 使用 material.uniforms.uTime.value。
  • 保持 uniform 容器稳定;每帧只修改值,不要设置 React state。仅更改 uniform 值时,不要设置 material.needsUpdate。
  • 着色器源码、定义和功能变更可能需要重新编译。热重载时使用类的 key;动画期间不要更改 React key。
  • Fiber 9 提供 extend(Class)。对于小写的全局元素,使用 ThreeElement<typeof Class> 扩展 ThreeElements;已移除的 Object3DNode 不能替代材质类型定义。
  • TypeScript 不会检查 GLSL 字符串。请运行并渲染它们,检查着色器编译器错误,包括使用实际渲染器和效果的配置。
  • 着色器源码位于 JavaScript 模板字面量中,因此 GLSL 中任何位置(包括注释)出现反引号或 ${,都会悄无声息地结束字符串并破坏模块。编写着色器注释时不要使用反引号,并让类型检查器发现此类问题,而不是靠阅读查找。

空间、颜色和几何体

  • 法线、光照方向和视线方向必须处于相同坐标空间。normalMatrix * normal 是视图空间向量;不要将它与世界空间的相机方向点乘。
  • 通过 Color 传入的 CSS / 十六进制颜色会转换到线性工作空间。数值型 uniform 向量已经是线性的;避免重复转换。
  • 将颜色输入纹理标记为 SRGBColorSpace;数据纹理使用 NoColorSpace。纹理采样和输出转换必须与材质 / 渲染器管线匹配。
  • 对于直接向画布写入内容的 WebGL 着色器,请像示例一样应用色调映射和输出颜色转换。不要手动进行伽马校正后又应用输出代码块。通过合成器渲染时,应由合成器负责最终输出。
  • 顶点变形需要足够细分的几何体。若需要光照,应同步更新法线。若需要阴影,深度 / 距离材质中的变形必须保持一致;CPU 射线投射和边界不会自动跟随 GPU 变形。
  • 原生自定义实例化着色器必须处理 instanceMatrix 和所有逐实例属性。蒙皮和形态目标同样需要对应的着色器逻辑。

修补内置 WebGL 材质

只有在需要保留内置材质的光照时,才使用 onBeforeCompile。着色器代码块名称会随版本变化:检查已安装版本的源码,并在更新 Three.js 后进行渲染测试。

在首次编译前设置回调。如果配置变更会生成不同的 GLSL,请提供匹配的 customProgramCacheKey 并触发重新编译;动画值应保存在 uniform 中。不要假设 .clone() 或序列化会保留回调。如果任务本身面向 WebGPU,优先使用节点材质。

来源

评论

支持 Markdown