@takram/three-geospatial-effects 0.0.1-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/README.md +15 -0
  2. package/build/index.cjs +1 -0
  3. package/build/index.js +25 -0
  4. package/build/r3f.cjs +748 -0
  5. package/build/r3f.js +1645 -0
  6. package/build/shared.cjs +315 -0
  7. package/build/shared.js +741 -0
  8. package/package.json +52 -0
  9. package/src/DepthEffect.ts +81 -0
  10. package/src/DitheringEffect.ts +28 -0
  11. package/src/DownsampleThresholdMaterial.ts +83 -0
  12. package/src/GeometryEffect.ts +79 -0
  13. package/src/GeometryPass.ts +53 -0
  14. package/src/LensFlareEffect.ts +185 -0
  15. package/src/LensFlareFeaturesMaterial.ts +96 -0
  16. package/src/NormalEffect.ts +135 -0
  17. package/src/createHaldLookupTexture.ts +20 -0
  18. package/src/index.ts +7 -0
  19. package/src/r3f/Depth.tsx +8 -0
  20. package/src/r3f/Dithering.tsx +5 -0
  21. package/src/r3f/EffectComposer.tsx +189 -0
  22. package/src/r3f/Geometry.tsx +45 -0
  23. package/src/r3f/LensFlare.tsx +30 -0
  24. package/src/r3f/Normal.tsx +49 -0
  25. package/src/r3f/SSAO.tsx +123 -0
  26. package/src/r3f/index.ts +8 -0
  27. package/src/r3f/types.ts +12 -0
  28. package/src/setupMaterialsForGeometryPass.ts +131 -0
  29. package/src/shaders/depthEffect.frag +26 -0
  30. package/src/shaders/ditheringEffect.frag +7 -0
  31. package/src/shaders/downsampleThreshold.frag +73 -0
  32. package/src/shaders/downsampleThreshold.vert +34 -0
  33. package/src/shaders/geometryEffect.frag +17 -0
  34. package/src/shaders/lensFlareEffect.frag +12 -0
  35. package/src/shaders/lensFlareFeatures.frag +73 -0
  36. package/src/shaders/lensFlareFeatures.vert +10 -0
  37. package/src/shaders/normalEffect.frag +37 -0
  38. package/src/shaders/ssr.frag +381 -0
  39. package/src/shaders/ssr.vert +6 -0
  40. package/src/shaders/ssrEffect.frag +6 -0
  41. package/types/DepthEffect.d.ts +23 -0
  42. package/types/DitheringEffect.d.ts +11 -0
  43. package/types/DownsampleThresholdMaterial.d.ts +21 -0
  44. package/types/GeometryEffect.d.ts +20 -0
  45. package/types/GeometryPass.d.ts +9 -0
  46. package/types/LensFlareEffect.d.ts +43 -0
  47. package/types/LensFlareFeaturesMaterial.d.ts +26 -0
  48. package/types/NormalEffect.d.ts +27 -0
  49. package/types/createHaldLookupTexture.d.ts +4 -0
  50. package/types/index.d.ts +7 -0
  51. package/types/r3f/Depth.d.ts +8 -0
  52. package/types/r3f/Dithering.d.ts +6 -0
  53. package/types/r3f/EffectComposer.d.ts +25 -0
  54. package/types/r3f/Geometry.d.ts +6 -0
  55. package/types/r3f/LensFlare.d.ts +6 -0
  56. package/types/r3f/Normal.d.ts +6 -0
  57. package/types/r3f/SSAO.d.ts +26 -0
  58. package/types/r3f/index.d.ts +8 -0
  59. package/types/r3f/types.d.ts +8 -0
  60. package/types/setupMaterialsForGeometryPass.d.ts +8 -0
@@ -0,0 +1,135 @@
1
+ /* eslint-disable @typescript-eslint/no-non-null-assertion */
2
+
3
+ /// <reference types="vite-plugin-glsl/ext" />
4
+
5
+ import { BlendFunction, Effect, EffectAttribute } from 'postprocessing'
6
+ import {
7
+ Matrix4,
8
+ Uniform,
9
+ type Camera,
10
+ type Texture,
11
+ type WebGLRenderer,
12
+ type WebGLRenderTarget
13
+ } from 'three'
14
+
15
+ import {
16
+ depthShader,
17
+ packingShader,
18
+ transformShader
19
+ } from '@takram/three-geospatial'
20
+
21
+ import fragmentShader from './shaders/normalEffect.frag'
22
+
23
+ export interface NormalEffectOptions {
24
+ blendFunction?: BlendFunction
25
+ normalBuffer?: Texture | null
26
+ octEncoded?: boolean
27
+ reconstructFromDepth?: boolean
28
+ }
29
+
30
+ export const normalEffectOptionsDefaults = {
31
+ blendFunction: BlendFunction.SRC,
32
+ octEncoded: false,
33
+ reconstructFromDepth: false
34
+ } satisfies NormalEffectOptions
35
+
36
+ export class NormalEffect extends Effect {
37
+ constructor(
38
+ private camera: Camera,
39
+ options?: NormalEffectOptions
40
+ ) {
41
+ const {
42
+ blendFunction,
43
+ normalBuffer = null,
44
+ octEncoded,
45
+ reconstructFromDepth
46
+ } = {
47
+ ...normalEffectOptionsDefaults,
48
+ ...options
49
+ }
50
+ super(
51
+ 'NormalEffect',
52
+ /* glsl */ `
53
+ ${depthShader}
54
+ ${packingShader}
55
+ ${transformShader}
56
+ ${fragmentShader}
57
+ `,
58
+ {
59
+ blendFunction,
60
+ attributes: EffectAttribute.DEPTH,
61
+ uniforms: new Map<string, Uniform>([
62
+ ['normalBuffer', new Uniform(normalBuffer)],
63
+ ['projectionMatrix', new Uniform(new Matrix4())],
64
+ ['inverseProjectionMatrix', new Uniform(new Matrix4())]
65
+ ])
66
+ }
67
+ )
68
+ if (camera != null) {
69
+ this.mainCamera = camera
70
+ }
71
+ this.octEncoded = octEncoded
72
+ this.reconstructFromDepth = reconstructFromDepth
73
+ }
74
+
75
+ get mainCamera(): Camera {
76
+ return this.camera
77
+ }
78
+
79
+ override set mainCamera(value: Camera) {
80
+ this.camera = value
81
+ }
82
+
83
+ update(
84
+ renderer: WebGLRenderer,
85
+ inputBuffer: WebGLRenderTarget,
86
+ deltaTime?: number
87
+ ): void {
88
+ const uniforms = this.uniforms
89
+ const projectionMatrix = uniforms.get('projectionMatrix')!
90
+ const inverseProjectionMatrix = uniforms.get('inverseProjectionMatrix')!
91
+ const camera = this.camera
92
+ if (camera != null) {
93
+ projectionMatrix.value.copy(camera.projectionMatrix)
94
+ inverseProjectionMatrix.value.copy(camera.projectionMatrixInverse)
95
+ }
96
+ }
97
+
98
+ get normalBuffer(): Texture | null {
99
+ return this.uniforms.get('normalBuffer')!.value
100
+ }
101
+
102
+ set normalBuffer(value: Texture | null) {
103
+ this.uniforms.get('normalBuffer')!.value = value
104
+ }
105
+
106
+ get octEncoded(): boolean {
107
+ return this.defines.has('OCT_ENCODED')
108
+ }
109
+
110
+ set octEncoded(value: boolean) {
111
+ if (value !== this.octEncoded) {
112
+ if (value) {
113
+ this.defines.set('OCT_ENCODED', '1')
114
+ } else {
115
+ this.defines.delete('OCT_ENCODED')
116
+ }
117
+ this.setChanged()
118
+ }
119
+ }
120
+
121
+ get reconstructFromDepth(): boolean {
122
+ return this.defines.has('RECONSTRUCT_FROM_DEPTH')
123
+ }
124
+
125
+ set reconstructFromDepth(value: boolean) {
126
+ if (value !== this.reconstructFromDepth) {
127
+ if (value) {
128
+ this.defines.set('RECONSTRUCT_FROM_DEPTH', '1')
129
+ } else {
130
+ this.defines.delete('RECONSTRUCT_FROM_DEPTH')
131
+ }
132
+ this.setChanged()
133
+ }
134
+ }
135
+ }
@@ -0,0 +1,20 @@
1
+ import { LookupTexture, RawImageData } from 'postprocessing'
2
+ import { type Texture } from 'three'
3
+
4
+ export function createHaldLookupTexture(texture: Texture): LookupTexture {
5
+ const { image } = texture
6
+ const { width, height } = image
7
+ if (width !== height) {
8
+ throw new Error('Hald CLUT image must be square.')
9
+ }
10
+ const size = Math.cbrt(width * height)
11
+ if (size % 1 !== 0) {
12
+ throw new Error('Hald CLUT image must be cubic.')
13
+ }
14
+ const { data } = RawImageData.from(image)
15
+ const lut = new LookupTexture(data, size)
16
+ lut.name = texture.name
17
+ lut.type = texture.type
18
+ texture.colorSpace = lut.colorSpace
19
+ return lut
20
+ }
package/src/index.ts ADDED
@@ -0,0 +1,7 @@
1
+ export * from './createHaldLookupTexture'
2
+ export * from './DepthEffect'
3
+ export * from './DitheringEffect'
4
+ export * from './GeometryPass'
5
+ export * from './LensFlareEffect'
6
+ export * from './NormalEffect'
7
+ export * from './setupMaterialsForGeometryPass'
@@ -0,0 +1,8 @@
1
+ import { wrapEffect } from '@react-three/postprocessing'
2
+ import { type ComponentPropsWithoutRef } from 'react'
3
+
4
+ import { DepthEffect } from '../DepthEffect'
5
+
6
+ export const Depth = wrapEffect(DepthEffect)
7
+
8
+ export type DepthProps = ComponentPropsWithoutRef<typeof Depth>
@@ -0,0 +1,5 @@
1
+ import { wrapEffect } from '@react-three/postprocessing'
2
+
3
+ import { DitheringEffect } from '../DitheringEffect'
4
+
5
+ export const Dithering = wrapEffect(DitheringEffect)
@@ -0,0 +1,189 @@
1
+ import { useFrame, useInstanceHandle, useThree } from '@react-three/fiber'
2
+ import { EffectComposerContext } from '@react-three/postprocessing'
3
+ import {
4
+ Effect,
5
+ EffectAttribute,
6
+ EffectComposer as EffectComposerImpl,
7
+ EffectPass,
8
+ Pass
9
+ } from 'postprocessing'
10
+ import {
11
+ forwardRef,
12
+ useEffect,
13
+ useImperativeHandle,
14
+ useLayoutEffect,
15
+ useMemo,
16
+ useRef,
17
+ type Context,
18
+ type ReactNode
19
+ } from 'react'
20
+ import {
21
+ HalfFloatType,
22
+ NoToneMapping,
23
+ type Camera,
24
+ type Scene,
25
+ type TextureDataType
26
+ } from 'three'
27
+
28
+ import { GeometryPass } from '../GeometryPass'
29
+
30
+ type InferContextValue<T> = T extends Context<infer U> ? U : never
31
+
32
+ export interface EffectComposerContextValue
33
+ extends InferContextValue<typeof EffectComposerContext> {
34
+ geometryPass?: GeometryPass
35
+ }
36
+
37
+ export interface EffectComposerProps {
38
+ enabled?: boolean
39
+ depthBuffer?: boolean
40
+ stencilBuffer?: boolean
41
+ autoClear?: boolean
42
+ resolutionScale?: number
43
+ multisampling?: number
44
+ frameBufferType?: TextureDataType
45
+ renderPriority?: number
46
+ camera?: Camera
47
+ scene?: Scene
48
+ children?: ReactNode
49
+ }
50
+
51
+ function isConvolution(effect: Effect): boolean {
52
+ return (
53
+ (effect.getAttributes() & EffectAttribute.CONVOLUTION) ===
54
+ EffectAttribute.CONVOLUTION
55
+ )
56
+ }
57
+
58
+ export const EffectComposer = /*#__PURE__*/ forwardRef<
59
+ EffectComposerImpl,
60
+ EffectComposerProps
61
+ >(function EffectComposer(
62
+ {
63
+ children,
64
+ camera: cameraProp,
65
+ scene: sceneProp,
66
+ enabled = true,
67
+ renderPriority = 1,
68
+ autoClear = true,
69
+ resolutionScale,
70
+ depthBuffer,
71
+ stencilBuffer = false,
72
+ multisampling = 8,
73
+ frameBufferType = HalfFloatType
74
+ },
75
+ forwardedRef
76
+ ) {
77
+ const gl = useThree(({ gl }) => gl)
78
+ const defaultScene = useThree(({ scene }) => scene)
79
+ const defaultCamera = useThree(({ camera }) => camera)
80
+ const scene = sceneProp ?? defaultScene
81
+ const camera = cameraProp ?? defaultCamera
82
+
83
+ const [composer, geometryPass] = useMemo(() => {
84
+ const composer = new EffectComposerImpl(gl, {
85
+ depthBuffer,
86
+ stencilBuffer,
87
+ multisampling,
88
+ frameBufferType
89
+ })
90
+ const geometryPass = new GeometryPass(composer.inputBuffer, scene, camera)
91
+ composer.addPass(geometryPass)
92
+ return [composer, geometryPass]
93
+ }, [
94
+ gl,
95
+ scene,
96
+ camera,
97
+ depthBuffer,
98
+ stencilBuffer,
99
+ multisampling,
100
+ frameBufferType
101
+ ])
102
+
103
+ const size = useThree(({ size }) => size)
104
+ useEffect(() => {
105
+ composer?.setSize(size.width, size.height)
106
+ }, [composer, size])
107
+
108
+ useFrame(
109
+ (state, delta) => {
110
+ if (enabled) {
111
+ const currentAutoClear = gl.autoClear
112
+ gl.autoClear = autoClear
113
+ if (stencilBuffer && !autoClear) {
114
+ gl.clearStencil()
115
+ }
116
+ composer.render(delta)
117
+ gl.autoClear = currentAutoClear
118
+ }
119
+ },
120
+ enabled ? renderPriority : 0
121
+ )
122
+
123
+ const group = useRef(null)
124
+ const instance = useInstanceHandle(group)
125
+ useLayoutEffect(() => {
126
+ const passes: Pass[] = []
127
+ if (group.current != null && instance.current != null && composer != null) {
128
+ const children = instance.current.objects as unknown[]
129
+ for (let i = 0; i < children.length; ++i) {
130
+ const child = children[i]
131
+ if (child instanceof Effect) {
132
+ const effects: Effect[] = [child]
133
+ if (!isConvolution(child)) {
134
+ let next: unknown = null
135
+ while ((next = children[i + 1]) instanceof Effect) {
136
+ if (isConvolution(next)) {
137
+ break
138
+ }
139
+ effects.push(next)
140
+ ++i
141
+ }
142
+ }
143
+ const pass = new EffectPass(camera, ...effects)
144
+ passes.push(pass)
145
+ } else if (child instanceof Pass) {
146
+ passes.push(child)
147
+ }
148
+ }
149
+ for (const pass of passes) {
150
+ composer?.addPass(pass)
151
+ }
152
+ }
153
+
154
+ return () => {
155
+ for (const pass of passes) {
156
+ composer?.removePass(pass)
157
+ }
158
+ }
159
+ }, [composer, children, camera, instance])
160
+
161
+ useEffect(() => {
162
+ const currentToneMapping = gl.toneMapping
163
+ gl.toneMapping = NoToneMapping
164
+ return () => {
165
+ gl.toneMapping = currentToneMapping
166
+ }
167
+ }, [gl])
168
+
169
+ const context = useMemo(
170
+ (): EffectComposerContextValue => ({
171
+ composer,
172
+ camera,
173
+ scene,
174
+ geometryPass,
175
+ normalPass: null,
176
+ downSamplingPass: null,
177
+ resolutionScale
178
+ }),
179
+ [composer, camera, scene, geometryPass, resolutionScale]
180
+ )
181
+
182
+ useImperativeHandle(forwardedRef, () => composer, [composer])
183
+
184
+ return (
185
+ <EffectComposerContext.Provider value={context}>
186
+ <group ref={group}>{children}</group>
187
+ </EffectComposerContext.Provider>
188
+ )
189
+ })
@@ -0,0 +1,45 @@
1
+ import { EffectComposerContext } from '@react-three/postprocessing'
2
+ import { forwardRef, useContext, useEffect, useMemo } from 'react'
3
+
4
+ import {
5
+ GeometryEffect,
6
+ geometryEffectOptionsDefaults,
7
+ type GeometryEffectOptions
8
+ } from '../GeometryEffect'
9
+ import { type EffectComposerContextValue } from './EffectComposer'
10
+ import { type EffectProps } from './types'
11
+
12
+ export interface GeometryProps
13
+ extends EffectProps<typeof GeometryEffect, GeometryEffectOptions> {}
14
+
15
+ export const Geometry = /*#__PURE__*/ forwardRef<GeometryEffect, GeometryProps>(
16
+ function Geometry(props, forwardedRef) {
17
+ const { blendFunction, ...others } = {
18
+ ...geometryEffectOptionsDefaults,
19
+ ...props
20
+ }
21
+
22
+ const { geometryPass } = useContext(
23
+ EffectComposerContext
24
+ ) as EffectComposerContextValue
25
+
26
+ const effect = useMemo(
27
+ () => new GeometryEffect({ blendFunction }),
28
+ [blendFunction]
29
+ )
30
+ useEffect(() => {
31
+ return () => {
32
+ effect.dispose()
33
+ }
34
+ }, [effect])
35
+
36
+ return (
37
+ <primitive
38
+ ref={forwardedRef}
39
+ object={effect}
40
+ geometryBuffer={geometryPass?.geometryTexture}
41
+ {...others}
42
+ />
43
+ )
44
+ }
45
+ )
@@ -0,0 +1,30 @@
1
+ import { forwardRef, useEffect, useMemo } from 'react'
2
+
3
+ import {
4
+ LensFlareEffect,
5
+ lensFlareEffectOptionsDefaults,
6
+ type LensFlareEffectOptions
7
+ } from '../LensFlareEffect'
8
+ import { type EffectProps } from './types'
9
+
10
+ export interface LensFlareProps
11
+ extends EffectProps<typeof LensFlareEffect, LensFlareEffectOptions> {}
12
+
13
+ export const LensFlare = /*#__PURE__*/ forwardRef<
14
+ LensFlareEffect,
15
+ LensFlareProps
16
+ >(function LensFlare(props, forwardedRef) {
17
+ const { blendFunction, ...others } = {
18
+ ...lensFlareEffectOptionsDefaults,
19
+ ...props
20
+ }
21
+
22
+ const effect = useMemo(() => new LensFlareEffect(), [])
23
+ useEffect(() => {
24
+ return () => {
25
+ effect.dispose()
26
+ }
27
+ }, [effect])
28
+
29
+ return <primitive ref={forwardedRef} object={effect} {...others} />
30
+ })
@@ -0,0 +1,49 @@
1
+ import { EffectComposerContext } from '@react-three/postprocessing'
2
+ import { forwardRef, useContext, useEffect, useMemo } from 'react'
3
+
4
+ import {
5
+ NormalEffect,
6
+ normalEffectOptionsDefaults,
7
+ type NormalEffectOptions
8
+ } from '../NormalEffect'
9
+ import { type EffectComposerContextValue } from './EffectComposer'
10
+ import { type EffectProps } from './types'
11
+
12
+ export interface NormalProps
13
+ extends EffectProps<typeof NormalEffect, NormalEffectOptions> {}
14
+
15
+ export const Normal = /*#__PURE__*/ forwardRef<NormalEffect, NormalProps>(
16
+ function Normal(props, forwardedRef) {
17
+ const { blendFunction, ...others } = {
18
+ ...normalEffectOptionsDefaults,
19
+ ...props
20
+ }
21
+
22
+ const { geometryPass, normalPass, camera } = useContext(
23
+ EffectComposerContext
24
+ ) as EffectComposerContextValue
25
+
26
+ const effect = useMemo(
27
+ () => new NormalEffect(camera, { blendFunction }),
28
+ [camera, blendFunction]
29
+ )
30
+ useEffect(() => {
31
+ return () => {
32
+ effect.dispose()
33
+ }
34
+ }, [effect])
35
+
36
+ return (
37
+ <primitive
38
+ ref={forwardedRef}
39
+ object={effect}
40
+ mainCamera={camera}
41
+ normalBuffer={
42
+ geometryPass?.geometryTexture ?? normalPass?.texture ?? null
43
+ }
44
+ {...others}
45
+ octEncoded={geometryPass?.geometryTexture != null}
46
+ />
47
+ )
48
+ }
49
+ )
@@ -0,0 +1,123 @@
1
+ import { applyProps, useThree } from '@react-three/fiber'
2
+ import { N8AOPostPass } from 'n8ao'
3
+ import { type Effect } from 'postprocessing'
4
+ import { forwardRef, useEffect, useLayoutEffect, useMemo, useRef } from 'react'
5
+ import { Color } from 'three'
6
+
7
+ export interface SSAOProps {
8
+ aoSamples?: number
9
+ aoRadius?: number
10
+ aoTones?: number
11
+ denoiseSamples?: number
12
+ denoiseRadius?: number
13
+ distanceFalloff?: number
14
+ intensity?: number
15
+ denoiseIterations?: number
16
+ renderMode?: number
17
+ biasOffset?: number
18
+ biasMultiplier?: number
19
+ color?: Color
20
+ gammaCorrection?: boolean
21
+ logarithmicDepthBuffer?: boolean
22
+ screenSpaceRadius?: boolean
23
+ halfRes?: boolean
24
+ depthAwareUpsampling?: boolean
25
+ colorMultiply?: boolean
26
+ transparencyAware?: boolean
27
+ accumulate?: boolean
28
+ }
29
+
30
+ export const SSAO = /*#__PURE__*/ forwardRef<Effect, SSAOProps>(function SSAO(
31
+ {
32
+ aoSamples = 16,
33
+ aoRadius = 5,
34
+ aoTones = 0,
35
+ denoiseSamples = 8,
36
+ denoiseRadius = 12,
37
+ distanceFalloff = 1,
38
+ intensity = 1, // Changed
39
+ denoiseIterations = 2,
40
+ renderMode = 0,
41
+ biasOffset = 0,
42
+ biasMultiplier = 0,
43
+ color = new Color(0, 0, 0),
44
+ gammaCorrection = false, // Changed
45
+ logarithmicDepthBuffer = false,
46
+ screenSpaceRadius = false,
47
+ halfRes = false,
48
+ depthAwareUpsampling = true,
49
+ colorMultiply = true,
50
+ transparencyAware = false,
51
+ accumulate = false
52
+ },
53
+ forwardedRef
54
+ ) {
55
+ const { camera, scene, size } = useThree()
56
+ const effect = useMemo(
57
+ () => new N8AOPostPass(scene, camera, size.width, size.height),
58
+ // TODO: Change of scene and camera break the pass.
59
+ // eslint-disable-next-line react-hooks/exhaustive-deps
60
+ []
61
+ )
62
+
63
+ const effectRef = useRef(effect)
64
+ effectRef.current = effect
65
+
66
+ useLayoutEffect(() => {
67
+ effectRef.current.setSize(size.width, size.height)
68
+ }, [size.width, size.height])
69
+
70
+ useLayoutEffect(() => {
71
+ applyProps(effectRef.current.configuration, {
72
+ aoSamples,
73
+ aoRadius,
74
+ aoTones,
75
+ denoiseSamples,
76
+ denoiseRadius,
77
+ distanceFalloff,
78
+ intensity,
79
+ denoiseIterations,
80
+ renderMode,
81
+ biasOffset,
82
+ biasMultiplier,
83
+ color,
84
+ gammaCorrection,
85
+ logarithmicDepthBuffer,
86
+ screenSpaceRadius,
87
+ halfRes,
88
+ depthAwareUpsampling,
89
+ colorMultiply,
90
+ transparencyAware,
91
+ accumulate
92
+ })
93
+ }, [
94
+ aoSamples,
95
+ aoRadius,
96
+ aoTones,
97
+ denoiseSamples,
98
+ denoiseRadius,
99
+ distanceFalloff,
100
+ intensity,
101
+ denoiseIterations,
102
+ renderMode,
103
+ biasOffset,
104
+ biasMultiplier,
105
+ color,
106
+ gammaCorrection,
107
+ logarithmicDepthBuffer,
108
+ screenSpaceRadius,
109
+ halfRes,
110
+ depthAwareUpsampling,
111
+ colorMultiply,
112
+ transparencyAware,
113
+ accumulate
114
+ ])
115
+
116
+ useEffect(() => {
117
+ return () => {
118
+ effect.dispose()
119
+ }
120
+ }, [effect])
121
+
122
+ return <primitive ref={forwardedRef} object={effect} />
123
+ })
@@ -0,0 +1,8 @@
1
+ export * from './Depth'
2
+ export * from './Dithering'
3
+ export * from './EffectComposer'
4
+ export * from './Geometry'
5
+ export * from './LensFlare'
6
+ export * from './Normal'
7
+ export * from './SSAO'
8
+ export * from './types'
@@ -0,0 +1,12 @@
1
+ import { type Node } from '@react-three/fiber'
2
+ import { type EffectConstructor } from '@react-three/postprocessing'
3
+ import { type BlendFunction } from 'postprocessing'
4
+
5
+ export type EffectProps<T extends EffectConstructor, Options = {}> = Node<
6
+ InstanceType<T>,
7
+ T
8
+ > &
9
+ Options & {
10
+ blendFunction?: BlendFunction
11
+ opacity?: number
12
+ }