react-postprocessing icon indicating copy to clipboard operation
react-postprocessing copied to clipboard

Updating effects via `useFrame`

Open robksawyer opened this issue 5 years ago • 4 comments

I've started a thread over in the react-three-fiber discussions (https://github.com/react-spring/react-three-fiber/discussions/595), but I'm wondering if you can add some insight. How should effects be updated after they're changed via useFrame? Sending these along to the EffectsComposer via state is not very efficient. And setting state inside of useFrame is really not a good idea.

robksawyer avatar Jul 29 '20 05:07 robksawyer

tbh I don't know, better ask @drcmda

if u want to update ur effect conditionally, use useLayoutEffect hook like here:

  useLayoutEffect(() => {
    if (depthTexture) {
      effect.setDepthTexture(depthTexture.texture, depthTexture.packing)
    }
  }, [depthTexture])

usage with useFrame - idk the best way to combine it w/ rpp

v1rtl avatar Jul 29 '20 11:07 v1rtl

i tried it out and it works, but you need to know postprocessing internals because the constructor parameters that you pass have are mapped to internals.

for instance this is how you fade Blooms luminianceThreshold:

  const ref = useRef()
  useFrame((state) => {
    if (ref.current) {
      ref.current.luminanceMaterial.threshold = (1 + Math.sin(state.clock.getElapsedTime() * 2)) / 2
    }
  }, [])
  return (
    <EffectComposer>
      <Bloom ref={ref} KernelSize={KernelSize.VERY_LARGE} height={400} opacity={2} />

demo: https://codesandbox.io/s/r3f-basic-demo-zvu4g?file=/src/App.js

now that's unfortunate. react-postprocessing could try to abstract this but it seems rather hacky, and pp could thrash that in any patch version. im going to ask upstream if this can be fixed by them.

drcmda avatar Aug 02 '20 13:08 drcmda

Wow, that's a process for sure. But, nice work hacking this together! I really appreciate it. Let me know if you'd like me to close this.

robksawyer avatar Aug 03 '20 13:08 robksawyer

for this btw we could really need help, but it would be easy to do:

import { BloomEffect as BloomEffectImpl } from 'postprocessing'

class BloomEffect extends BloomEffectImpl {
  set luminanceThreshold(v) { this.luminanceMaterial.threshold = v }
  get luminanceThreshold() { return this.luminanceMaterial.threshold }
  ...
}

the react-pp effects would then instanciate that instead of the original. and that's that, now effects could truly be changed by props, and refs. currently if you set props it re-instanciates the effect which is very bad, and - of course - props that you use with refs don't correspond to the constructor args.

if you want @robksawyer PR's welcome 🙂

drcmda avatar Aug 03 '20 14:08 drcmda

I think it's safe to close this

v1rtl avatar Jun 06 '23 09:06 v1rtl