0beqz / realism-effects

SSGI, Motion Blur, TRAA - Effects to enhance your three.js scene's realism
https://realism-effects-obeqz.vercel.app/
MIT License
1.4k stars 61 forks source link

React-three-fiber integration #5

Open klavinski opened 1 year ago

klavinski commented 1 year ago

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>
}
rolandpeelen commented 1 year ago

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

0beqz commented 1 year ago

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 commented 1 year ago

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.

Nek commented 1 year ago

@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!

0beqz commented 12 months ago

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

koutlita commented 6 months ago

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

klavinski commented 6 months ago

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 }/>
}
koutlita commented 6 months ago

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