realism-effects icon indicating copy to clipboard operation
realism-effects copied to clipboard

React-three-fiber integration

Open klavinski opened this issue 1 year ago • 8 comments

Is there a recommended way to integrate the SSGI with @react-three/fiber? I tried adapting your code like this, but it did not work:

const SSGI = () => {
    const { camera, composer, scene } = useContext( EffectComposerContext )
    const velocityDepthNormalPass = new VelocityDepthNormalPass( scene, camera )
    composer.addPass(velocityDepthNormalPass)
    const ssgiEffect = new SSGIEffect( scene, camera, velocityDepthNormalPass, options )
    const traaEffect = new TRAAEffect( scene, camera, velocityDepthNormalPass )
    const motionBlurEffect = new MotionBlurEffect( velocityDepthNormalPass )
    return <EffectComposer>
        <primitive object={motionBlurEffect}/>
        <primitive object={traaEffect}/>
        <primitive object={ssgiEffect}/>
    </EffectComposer>
}

klavinski avatar Mar 08 '23 07:03 klavinski

+1 ! I would love to see this work in react-tree-fiber :)

rolandpeelen avatar Mar 08 '23 22:03 rolandpeelen

Yes, there seems to be an issue when trying to use the effects in r3f, https://twitter.com/0beqz/status/1634313769357656064?t=FKjfhzkQdV8B99LwDcrSsQ&s=19.

I'll debug them when I have time to see what exactly causes the artifacts. Once that's resolved, they should become available in r3f.

0beqz avatar Mar 14 '23 02:03 0beqz

Although somewhat limited still, it should work now in r3f. Not all materials are supported yet (e.g. ShadowCatchers). I'll keep working on it but it should be supported now. Next step is having it added to react-postprocessing once everything is stable enough.

0beqz avatar Mar 20 '23 05:03 0beqz

@klavinski Relevant code from the project I'm working on.

import { extend, ReactThreeFiber, useFrame, useThree } from '@react-three/fiber'
//@ts-ignore
import { SSGIEffect, HBAOEffect, MotionBlurEffect, VelocityDepthNormalPass } from 'realism-effects'
import {
// Fixes type shadowing between "postprocessing" and "three"
  EffectComposer as PostEffectsComposer,
  EffectPass as PostEffectPass,
  RenderPass as PostRenderPass,
} from 'postprocessing'
import { useEffect, useRef } from 'react'

extend({
  PostRenderPass,
  PostEffectPass,
  SSGIEffect,
  VelocityDepthNormalPass,
  PostEffectsComposer,
})

declare module '@react-three/fiber' {
  interface ThreeElements {
    velocityDepthNormalPass: ReactThreeFiber.Node<VelocityDepthNormalPass, typeof VelocityDepthNormalPass>
    sSGIEffect: ReactThreeFiber.Node<SSGIEffect, typeof SSGIEffect>
    postEffectsComposer: ReactThreeFiber.Node<PostEffectsComposer, typeof PostEffectsComposer>
    postRenderPass: ReactThreeFiber.Node<PostRenderPass, typeof PostRenderPass>
    postEffectPass: ReactThreeFiber.Node<PostEffectPass, typeof PostEffectPass>
  }
}

export function PostEffectComposer() {
  const { camera, scene, size } = useThree()
  const composerRef = useRef<PostEffectsComposer>(null!)
  const velocityDepthNormalPassRef = useRef(null!)

  useEffect(() => {
    if (composerRef.current) {
      composerRef.current.setSize(size.width, size.height)
    }
  }, [composerRef.current, size])
// This kills the automatic rendering. Don't forget to add a call to gl.render somewhere else.
  useFrame((_, delta) => {
    composerRef.current && composerRef.current.render(delta)
  }, 2)
  const gl = useThree(({ gl }) => gl)
  return (
    <postEffectsComposer ref={composerRef} args={[gl]}>
      <postRenderPass args={[scene, camera]} attach={(parent, self) => parent.addPass(self)} />
      <velocityDepthNormalPass
        ref={velocityDepthNormalPassRef}
        args={[scene, camera]}
        attach={(parent, self) => parent.addPass(self)}
      />
      {velocityDepthNormalPassRef.current && (
        <postEffectPass
          args={[camera, new SSGIEffect(scene, camera, velocityDepthNormalPassRef.current)]}
          attach={(parent, self) => parent.addPass(self)}
        />
      )}
      {velocityDepthNormalPassRef.current && composerRef.current && (
        <postEffectPass
          args={[
            camera,
            new HBAOEffect(composerRef.current, camera, scene),
            new MotionBlurEffect(velocityDepthNormalPassRef.current),
          ]}
          attach={(parent, self) => parent.addPass(self)}
        />
      )}
    </postEffectsComposer>
  )
}

Add somewhere else:

  useFrame(({ scene, camera , gl}) => {
    gl.render(scene, camera)
  }, 1)

I hope this helps!

Nek avatar Aug 06 '23 08:08 Nek

Thx, yeah I'm planning to add codesandboxes for SSGI + R3F after releasing the new version.

0beqz avatar Aug 29 '23 18:08 0beqz

Hiiii,good.job!!!! have you find a solution for R3F integration?

koutlita avatar Feb 07 '24 08:02 koutlita

In my case, it was actually quite simple. This is how I use it on my blog:

import { EffectComposer, EffectComposerContext, SMAA } from "@react-three/postprocessing"

// In your R3F Canvas
<Canvas>
    ...
    <EffectComposer>
        <RealismEffects/>
        <SMAA/> // Or any other effect you would like to add
    </EffectComposer>
</Canvas>

// How <RealismEffects/> is made
const RealismEffects = () => {
    const { scene, camera, composer } = useContext( EffectComposerContext )
    const velocityDepthNormalPass = useMemo( () => new VelocityDepthNormalPass( scene, camera ), [ scene, camera ] )
    useLayoutEffect( () => {
        composer.addPass( velocityDepthNormalPass )
        return () => {
            composer.removePass( velocityDepthNormalPass )
        }
    }, [ velocityDepthNormalPass, composer ] )
    const ssgiEffect = useMemo( () => new SSGIEffect( scene, camera, velocityDepthNormalPass ), [ scene, camera, velocityDepthNormalPass ] )
    return <primitive object={ ssgiEffect }/>
}

klavinski avatar Feb 07 '24 15:02 klavinski

The probleme is we cant see our rectangulaire light....

koutlita avatar Feb 07 '24 20:02 koutlita