diff --git a/src/effects/DepthOfField.tsx b/src/effects/DepthOfField.tsx index 9b8ca76..9a05ad3 100644 --- a/src/effects/DepthOfField.tsx +++ b/src/effects/DepthOfField.tsx @@ -1,6 +1,6 @@ import { DepthOfFieldEffect, MaskFunction } from 'postprocessing' -import { Ref, forwardRef, useMemo, useLayoutEffect, useContext } from 'react' -import { ReactThreeFiber, useThree } from '@react-three/fiber' +import { Ref, forwardRef, useMemo, useEffect, useContext } from 'react' +import { ReactThreeFiber } from '@react-three/fiber' import { type DepthPackingStrategies, type Texture, Vector3 } from 'three' import { EffectComposerContext } from '../EffectComposer' @@ -9,34 +9,81 @@ type DOFProps = ConstructorParameters[1] & target: ReactThreeFiber.Vector3 depthTexture: { texture: Texture + // TODO: narrow to DepthPackingStrategies packing: number } + // TODO: not used blur: number }> export const DepthOfField = forwardRef(function DepthOfField( - { target, depthTexture, ...props }: DOFProps, + { + blendFunction, + worldFocusDistance, + worldFocusRange, + focusDistance, + focusRange, + focalLength, + bokehScale, + resolutionScale, + resolutionX, + resolutionY, + width, + height, + target, + depthTexture, + ...props + }: DOFProps, ref: Ref ) { - const invalidate = useThree((state) => state.invalidate) const { camera } = useContext(EffectComposerContext) + const autoFocus = target != null const effect = useMemo(() => { - const effect = new DepthOfFieldEffect(camera, props) + const effect = new DepthOfFieldEffect(camera, { + blendFunction, + worldFocusDistance, + worldFocusRange, + focusDistance, + focusRange, + focalLength, + bokehScale, + resolutionScale, + resolutionX, + resolutionY, + width, + height, + }) + // Creating a target enables autofocus, R3F will set via props + if (autoFocus) effect.target = new Vector3() + // Depth texture for depth picking with optional packing strategy + if (depthTexture) effect.setDepthTexture(depthTexture.texture, depthTexture.packing as DepthPackingStrategies) // Temporary fix that restores DOF 6.21.3 behavior, everything since then lets shapes leak through the blur const maskMaterial = (effect as any).maskPass.getFullscreenMaterial() maskMaterial.maskFunction = MaskFunction.MULTIPLY_RGB_SET_ALPHA return effect - }, [camera, props]) - useLayoutEffect(() => { - if (target && typeof target !== 'number') { - const vec: Vector3 = - target instanceof Vector3 - ? new Vector3().set(target.x, target.y, target.z) - : new Vector3().set(target[0], target[1], target[2]) - effect.target = vec + }, [ + camera, + blendFunction, + worldFocusDistance, + worldFocusRange, + focusDistance, + focusRange, + focalLength, + bokehScale, + resolutionScale, + resolutionX, + resolutionY, + width, + height, + autoFocus, + depthTexture, + ]) + + useEffect(() => { + return () => { + effect.dispose() } - if (depthTexture) effect.setDepthTexture(depthTexture.texture, depthTexture.packing as DepthPackingStrategies) - invalidate() - }, [target, depthTexture, effect]) - return + }, [effect]) + + return })