{"version":3,"file":"EffectComposer.cjs","sources":["../src/EffectComposer.tsx"],"sourcesContent":["import type { Camera, Scene, TextureDataType } from 'three'\nimport { HalfFloatType, NoToneMapping } from 'three'\nimport React, {\n  forwardRef,\n  useMemo,\n  useEffect,\n  useLayoutEffect,\n  createContext,\n  useRef,\n  useImperativeHandle,\n} from 'react'\nimport { useThree, useFrame } from '@react-three/fiber'\nimport {\n  EffectComposer as EffectComposerImpl,\n  RenderPass,\n  EffectPass,\n  NormalPass,\n  // @ts-ignore\n  DepthDownsamplingPass,\n  Effect,\n  Pass,\n  EffectAttribute,\n} from 'postprocessing'\nimport { isWebGL2Available } from 'three-stdlib'\n\nexport const EffectComposerContext = createContext<{\n  composer: EffectComposerImpl\n  normalPass: NormalPass | null\n  downSamplingPass: DepthDownsamplingPass | null\n  camera: Camera\n  scene: Scene\n  resolutionScale?: number\n}>(null!)\n\nexport type EffectComposerProps = {\n  enabled?: boolean\n  children: JSX.Element | JSX.Element[]\n  depthBuffer?: boolean\n  /** Only used for SSGI currently, leave it disabled for everything else unless it's needed */\n  enableNormalPass?: boolean\n  stencilBuffer?: boolean\n  autoClear?: boolean\n  resolutionScale?: number\n  multisampling?: number\n  frameBufferType?: TextureDataType\n  renderPriority?: number\n  camera?: Camera\n  scene?: Scene\n}\n\nconst isConvolution = (effect: Effect): boolean =>\n  (effect.getAttributes() & EffectAttribute.CONVOLUTION) === EffectAttribute.CONVOLUTION\n\nexport const EffectComposer = React.memo(\n  forwardRef<EffectComposerImpl, EffectComposerProps>(\n    (\n      {\n        children,\n        camera: _camera,\n        scene: _scene,\n        resolutionScale,\n        enabled = true,\n        renderPriority = 1,\n        autoClear = true,\n        depthBuffer,\n        enableNormalPass,\n        stencilBuffer,\n        multisampling = 8,\n        frameBufferType = HalfFloatType,\n      },\n      ref\n    ) => {\n      const { gl, scene: defaultScene, camera: defaultCamera, size } = useThree()\n      const scene = _scene || defaultScene\n      const camera = _camera || defaultCamera\n\n      const [composer, normalPass, downSamplingPass] = useMemo(() => {\n        const webGL2Available = isWebGL2Available()\n        // Initialize composer\n        const effectComposer = new EffectComposerImpl(gl, {\n          depthBuffer,\n          stencilBuffer,\n          multisampling: multisampling > 0 && webGL2Available ? multisampling : 0,\n          frameBufferType,\n        })\n\n        // Add render pass\n        effectComposer.addPass(new RenderPass(scene, camera))\n\n        // Create normal pass\n        let downSamplingPass = null\n        let normalPass = null\n        if (enableNormalPass) {\n          normalPass = new NormalPass(scene, camera)\n          normalPass.enabled = false\n          effectComposer.addPass(normalPass)\n          if (resolutionScale !== undefined && webGL2Available) {\n            downSamplingPass = new DepthDownsamplingPass({ normalBuffer: normalPass.texture, resolutionScale })\n            downSamplingPass.enabled = false\n            effectComposer.addPass(downSamplingPass)\n          }\n        }\n\n        return [effectComposer, normalPass, downSamplingPass]\n      }, [\n        camera,\n        gl,\n        depthBuffer,\n        stencilBuffer,\n        multisampling,\n        frameBufferType,\n        scene,\n        enableNormalPass,\n        resolutionScale,\n      ])\n\n      useEffect(() => composer?.setSize(size.width, size.height), [composer, size])\n      useFrame(\n        (_, delta) => {\n          if (enabled) {\n            const currentAutoClear = gl.autoClear\n            gl.autoClear = autoClear\n            if (stencilBuffer && !autoClear) gl.clearStencil()\n            composer.render(delta)\n            gl.autoClear = currentAutoClear\n          }\n        },\n        enabled ? renderPriority : 0\n      )\n\n      const group = useRef(null)\n      useLayoutEffect(() => {\n        const passes: Pass[] = []\n\n        // TODO: rewrite all of this with R3F v9\n        const groupInstance = (group.current as any)?.__r3f as { objects: unknown[] }\n\n        if (groupInstance && composer) {\n          const children = groupInstance.objects\n\n          for (let i = 0; i < children.length; i++) {\n            const child = children[i]\n\n            if (child instanceof Effect) {\n              const effects: Effect[] = [child]\n\n              if (!isConvolution(child)) {\n                let next: unknown = null\n                while ((next = children[i + 1]) instanceof Effect) {\n                  if (isConvolution(next)) break\n                  effects.push(next)\n                  i++\n                }\n              }\n\n              const pass = new EffectPass(camera, ...effects)\n              passes.push(pass)\n            } else if (child instanceof Pass) {\n              passes.push(child)\n            }\n          }\n\n          for (const pass of passes) composer?.addPass(pass)\n\n          if (normalPass) normalPass.enabled = true\n          if (downSamplingPass) downSamplingPass.enabled = true\n        }\n\n        return () => {\n          for (const pass of passes) composer?.removePass(pass)\n          if (normalPass) normalPass.enabled = false\n          if (downSamplingPass) downSamplingPass.enabled = false\n        }\n      }, [composer, children, camera, normalPass, downSamplingPass])\n\n      // Disable tone mapping because threejs disallows tonemapping on render targets\n      useEffect(() => {\n        const currentTonemapping = gl.toneMapping\n        gl.toneMapping = NoToneMapping\n        return () => {\n          gl.toneMapping = currentTonemapping\n        }\n      }, [gl])\n\n      // Memoize state, otherwise it would trigger all consumers on every render\n      const state = useMemo(\n        () => ({ composer, normalPass, downSamplingPass, resolutionScale, camera, scene }),\n        [composer, normalPass, downSamplingPass, resolutionScale, camera, scene]\n      )\n\n      // Expose the composer\n      useImperativeHandle(ref, () => composer, [composer])\n\n      return (\n        <EffectComposerContext.Provider value={state}>\n          <group ref={group}>{children}</group>\n        </EffectComposerContext.Provider>\n      )\n    }\n  )\n)\n"],"names":["createContext","EffectAttribute","forwardRef","HalfFloatType","useThree","useMemo","isWebGL2Available","EffectComposerImpl","RenderPass","downSamplingPass","normalPass","NormalPass","DepthDownsamplingPass","useEffect","useFrame","useRef","useLayoutEffect","children","Effect","EffectPass","Pass","NoToneMapping","useImperativeHandle","jsx"],"mappings":"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"}