如何在react-three-fiber中使用自定义后期处理着色器通道?
在react-three-fiber中使用自定义后期处理着色器通道
问题背景
我正在使用react-three,为我的Three.js项目创建了一个自定义后期处理着色器,以下代码在常规HTML和JS文件中可正常运行:
自定义着色器代码
const CustomShader = { uniforms: { 'tDiffuse': { value: null }, }, vertexShader: /* glsl */` varying vec2 vUv; void main() { vUv = uv; gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); }`, fragmentShader: /* glsl */` uniform sampler2D tDiffuse; varying vec2 vUv; void main() { // my glsl code... vec4 finalRGBA = texture2D(tDiffuse, vUv); gl_FragColor = finalRGBA; }` }; export { CustomShader };
原生Three.js中的使用方式
const composer = new EffectComposer(renderer); composer.addPass(new RenderPass(scene, camera)); const customPass = new ShaderPass(CustomShader); composer.addPass(customPass);
现在我想在react-three-fiber中使用上述着色器通道,但无法通过useRef或useEffect将我的着色器加入EffectComposer,请问该如何实现?
解决方案
方式一:使用@react-three/postprocessing库(推荐)
react-three-fiber生态中有专门封装后期处理的库@react-three/postprocessing,它完全贴合R3F的组件化思想,无需手动管理渲染生命周期。
- 安装依赖
npm install @react-three/postprocessing three
- 组件中集成
直接在Canvas内用组件化的方式添加EffectComposer和ShaderPass:
import { Canvas } from '@react-three/fiber'; import { EffectComposer, ShaderPass } from '@react-three/postprocessing'; import { CustomShader } from './CustomShader'; function App() { return ( <Canvas> {/* 你的场景内容:相机、模型、灯光等 */} <ambientLight /> <pointLight position={[10, 10, 10]} /> <mesh> <boxGeometry /> <meshStandardMaterial /> </mesh> {/* 后期处理模块 */} <EffectComposer> <ShaderPass shader={CustomShader} /> </EffectComposer> </Canvas> ); } export default App;
方式二:手动创建EffectComposer(原生方式适配)
如果需要完全自定义EffectComposer的配置,可以通过useThree钩子获取场景、相机和渲染器,再结合useEffect手动构建:
import { useRef, useEffect } from 'react'; import { Canvas, useThree } from '@react-three/fiber'; import { EffectComposer, RenderPass, ShaderPass } from 'three/addons/postprocessing/EffectComposer.js'; import { CustomShader } from './CustomShader'; // 自定义后期处理组件 function PostProcessing() { const { scene, camera, gl } = useThree(); const composerRef = useRef(null); useEffect(() => { // 创建EffectComposer实例 const composer = new EffectComposer(gl); // 添加渲染通道和自定义着色器通道 composer.addPass(new RenderPass(scene, camera)); composer.addPass(new ShaderPass(CustomShader)); composerRef.current = composer; // 替换R3F默认的渲染函数,改用composer渲染 const originalRender = gl.render; gl.render = () => { composer.render(); }; // 组件卸载时清理资源 return () => { gl.render = originalRender; composer.dispose(); }; }, [scene, camera, gl]); return null; } function App() { return ( <Canvas> {/* 场景内容 */} <ambientLight /> <pointLight position={[10, 10, 10]} /> <mesh> <boxGeometry /> <meshStandardMaterial /> </mesh> {/* 挂载后期处理组件 */} <PostProcessing /> </Canvas> ); } export default App;
内容的提问来源于stack exchange,提问作者TomFan
相关产品推荐
相关产品推荐

