import * as React from 'react' import { RGBAFormat, HalfFloatType, WebGLRenderTarget, UnsignedByteType, TextureDataType } from 'three' import { ReactThreeFiber, extend, useThree, useFrame } from '@react-three/fiber' import { EffectComposer, RenderPass, ShaderPass, GammaCorrectionShader } from 'three-stdlib' import { ForwardRefComponent } from '../helpers/ts-utils' import { TextureEncoding } from '../helpers/deprecated' type Props = ReactThreeFiber.Node & { multisamping?: number encoding?: TextureEncoding type?: TextureDataType renderIndex?: number disableGamma?: boolean disableRenderPass?: boolean disableRender?: boolean depthBuffer?: boolean stencilBuffer?: boolean anisotropy?: number } declare global { namespace JSX { interface IntrinsicElements { effectComposer: ReactThreeFiber.Node renderPass: ReactThreeFiber.Node shaderPass: ReactThreeFiber.Node } } } export const isWebGL2Available = () => { try { var canvas = document.createElement('canvas') return !!(window.WebGL2RenderingContext && canvas.getContext('webgl2')) } catch (e) { return false } } export const Effects: ForwardRefComponent = /* @__PURE__ */ React.forwardRef( ( { children, multisamping = 8, renderIndex = 1, disableRender, disableGamma, disableRenderPass, depthBuffer = true, stencilBuffer = false, anisotropy = 1, encoding, type, ...props }: Props, ref ) => { React.useMemo(() => extend({ EffectComposer, RenderPass, ShaderPass }), []) const composer = React.useRef(null!) React.useImperativeHandle(ref, () => composer.current, []) const { scene, camera, gl, size, viewport } = useThree() const [target] = React.useState(() => { const t = new WebGLRenderTarget(size.width, size.height, { type: type || HalfFloatType, format: RGBAFormat, depthBuffer, stencilBuffer, anisotropy, }) // sRGB textures must be RGBA8 since r137 https://github.com/mrdoob/three.js/pull/23129 if (type === UnsignedByteType && encoding != null) { if ('colorSpace' in t) (t.texture as any).colorSpace = encoding else t.texture.encoding = encoding } t.samples = multisamping return t }) React.useEffect(() => { composer.current?.setSize(size.width, size.height) composer.current?.setPixelRatio(viewport.dpr) }, [gl, size, viewport.dpr]) useFrame(() => { if (!disableRender) composer.current?.render() }, renderIndex) const passes: React.ReactNode[] = [] if (!disableRenderPass) passes.push() if (!disableGamma) passes.push() React.Children.forEach(children, (el: any) => { el && passes.push(React.cloneElement(el, { key: passes.length, attach: `passes-${passes.length}` })) }) return ( {passes} ) } )