Skip to content

Commit 49b082f

Browse files
authored
fix(DepthOfField): cleanup memory leak (#233)
1 parent 56e3687 commit 49b082f

File tree

1 file changed

+64
-17
lines changed

1 file changed

+64
-17
lines changed

src/effects/DepthOfField.tsx

Lines changed: 64 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { DepthOfFieldEffect, MaskFunction } from 'postprocessing'
2-
import { Ref, forwardRef, useMemo, useLayoutEffect, useContext } from 'react'
3-
import { ReactThreeFiber, useThree } from '@react-three/fiber'
2+
import { Ref, forwardRef, useMemo, useEffect, useContext } from 'react'
3+
import { ReactThreeFiber } from '@react-three/fiber'
44
import { type DepthPackingStrategies, type Texture, Vector3 } from 'three'
55
import { EffectComposerContext } from '../EffectComposer'
66

@@ -9,34 +9,81 @@ type DOFProps = ConstructorParameters<typeof DepthOfFieldEffect>[1] &
99
target: ReactThreeFiber.Vector3
1010
depthTexture: {
1111
texture: Texture
12+
// TODO: narrow to DepthPackingStrategies
1213
packing: number
1314
}
15+
// TODO: not used
1416
blur: number
1517
}>
1618

1719
export const DepthOfField = forwardRef(function DepthOfField(
18-
{ target, depthTexture, ...props }: DOFProps,
20+
{
21+
blendFunction,
22+
worldFocusDistance,
23+
worldFocusRange,
24+
focusDistance,
25+
focusRange,
26+
focalLength,
27+
bokehScale,
28+
resolutionScale,
29+
resolutionX,
30+
resolutionY,
31+
width,
32+
height,
33+
target,
34+
depthTexture,
35+
...props
36+
}: DOFProps,
1937
ref: Ref<DepthOfFieldEffect>
2038
) {
21-
const invalidate = useThree((state) => state.invalidate)
2239
const { camera } = useContext(EffectComposerContext)
40+
const autoFocus = target != null
2341
const effect = useMemo(() => {
24-
const effect = new DepthOfFieldEffect(camera, props)
42+
const effect = new DepthOfFieldEffect(camera, {
43+
blendFunction,
44+
worldFocusDistance,
45+
worldFocusRange,
46+
focusDistance,
47+
focusRange,
48+
focalLength,
49+
bokehScale,
50+
resolutionScale,
51+
resolutionX,
52+
resolutionY,
53+
width,
54+
height,
55+
})
56+
// Creating a target enables autofocus, R3F will set via props
57+
if (autoFocus) effect.target = new Vector3()
58+
// Depth texture for depth picking with optional packing strategy
59+
if (depthTexture) effect.setDepthTexture(depthTexture.texture, depthTexture.packing as DepthPackingStrategies)
2560
// Temporary fix that restores DOF 6.21.3 behavior, everything since then lets shapes leak through the blur
2661
const maskMaterial = (effect as any).maskPass.getFullscreenMaterial()
2762
maskMaterial.maskFunction = MaskFunction.MULTIPLY_RGB_SET_ALPHA
2863
return effect
29-
}, [camera, props])
30-
useLayoutEffect(() => {
31-
if (target && typeof target !== 'number') {
32-
const vec: Vector3 =
33-
target instanceof Vector3
34-
? new Vector3().set(target.x, target.y, target.z)
35-
: new Vector3().set(target[0], target[1], target[2])
36-
effect.target = vec
64+
}, [
65+
camera,
66+
blendFunction,
67+
worldFocusDistance,
68+
worldFocusRange,
69+
focusDistance,
70+
focusRange,
71+
focalLength,
72+
bokehScale,
73+
resolutionScale,
74+
resolutionX,
75+
resolutionY,
76+
width,
77+
height,
78+
autoFocus,
79+
depthTexture,
80+
])
81+
82+
useEffect(() => {
83+
return () => {
84+
effect.dispose()
3785
}
38-
if (depthTexture) effect.setDepthTexture(depthTexture.texture, depthTexture.packing as DepthPackingStrategies)
39-
invalidate()
40-
}, [target, depthTexture, effect])
41-
return <primitive ref={ref} object={effect} dispose={null} />
86+
}, [effect])
87+
88+
return <primitive {...props} ref={ref} object={effect} target={target} />
4289
})

0 commit comments

Comments
 (0)