Chaining effect composers (render targets) #389
Replies: 3 comments 3 replies
-
i would do it imperatively: https://codesandbox.io/s/r3f-selective-bloom-1bult in react declarative elements shouldn't rely on anything but their parent, and even that relation should be pure, in that the child wont mutate or access the parent. being able to declare elements is great, but in those cases where you can't you still benefit from react because you can still make it re-usable. btw you have side effects in your render function, offscreenTarget is going to be re-created on every render. the resize stuff can be in a single useEffect, you also dont need two useFrames. |
Beta Was this translation helpful? Give feedback.
-
Much cleaner. For the record: import { WebGLRenderTarget } from 'three';
import { useEffect, useMemo } from 'react';
import { extend, useFrame, useThree } from 'react-three-fiber';
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer';
import { ShaderPass } from 'three/examples/jsm/postprocessing/ShaderPass';
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass';
import { RadialBlurShader } from '../../shaders/RadialBlurShader';
import { GaussianBlurShader } from '../../shaders/GaussianBlurShader';
extend({ EffectComposer, ShaderPass, RenderPass });
function Effect() {
const { gl, scene, camera, size } = useThree()
const [base, final] = useMemo(() => {
const renderScene = new RenderPass(scene, camera);
const offscreenTarget = new WebGLRenderTarget(size.width, size.height);
const comp = new EffectComposer(gl, offscreenTarget);
comp.renderToScreen = false;
comp.addPass(renderScene);
const finalComposer = new EffectComposer(gl);
const radialBlurShader = new RadialBlurShader();
radialBlurShader.uniforms.strength.value = 0.08;
const radialPass = new ShaderPass(radialBlurShader);
const finalPass = new ShaderPass(new GaussianBlurShader());
finalPass.needsSwap = true;
finalComposer.addPass(renderScene);
finalComposer.addPass(radialPass);
finalComposer.addPass(finalPass);
/* const fxaa = new ShaderPass(FXAAShader)
fxaa.material.uniforms['resolution'].value.x = 1 / size.width
fxaa.material.uniforms['resolution'].value.y = 1 / size.height
finalComposer.addPass(fxaa) */
return [comp, finalComposer];
}, []);
useEffect(() => {
base.setSize(size.width, size.height);
final.setSize(size.width, size.height);
}, [base, final, size])
useFrame(() => {
base.render();
final.render();
}, 1);
return null;
};
export default Effect; This also lets me conveniently use TypeScript. For future reference, the following article also discusses the type of effect I am looking at: |
Beta Was this translation helpful? Give feedback.
-
looking good. you can save two more lines by doing return useFrame(() => {
base.render();
final.render();
}, 1); :-P |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Hello,
I am trying to chain effect composer pipelines, if possible in declarative fashion, such as:
It compiles, it runs, but it basically doesn't display anything.
How should I go about that?
Beta Was this translation helpful? Give feedback.
All reactions