Package Exports
- react-postprocessing
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (react-postprocessing) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
react-postprocessing
postprocessing wrapper for React.
Why
Instead of manually initializing the composer and adding required passes you can import the effects as components and put them inside <EffectComposer />.
Installation
yarn add postprocessing react-postprocessingEffects
For a list of effects, examples and props usage, check effects.md.
Getting Started
Effect composer
Passing effects
All effects are consumed by effect composer, EffectComposer, that creates passes and other things required for compositor to work.
You can pass effects using children:
import React, { useState } from 'react'
import { EffectComposer, Glitch } from 'react-postprocessing'
import { Canvas } from 'react-three-fiber'
const App = () => {
const [isTriggered, setTriggered] = useState(false)
return (
<Canvas>
<mesh onClick={() => setTriggered(!isTriggered)}>
<boxGeometry args={[1, 1, 1]} />
<meshBasicMaterial color="red" />
</mesh>
<Suspense>
<EffectComposer>
<Glitch active={isTriggered} />
</EffectComposer>
</Suspense>
</Canvas>
)
}SMAA
By default, SMAA is enabled in EffectComposer. When enabled, you can pass additional properties for configuring SMAA, such as edgeDetection, which sets edge detection threshold.
<Suspense fallback={null}>
<EffectComposer smaa edgeDetection={0.3}>
<Glitch />
</EffectComposer>
</Suspense>Adding effects
When you want to add a new effect your react-three-fiber component you first need to import the effect and then put it in children.
import React from 'react'
import { EffectComposer, Scanline } from 'react-postprocessing'
import { Canvas } from 'react-three-fiber'
const App = () => (
<Canvas>
<mesh>
<boxGeometry args={[1, 1, 1]} />
<meshBasicMaterial color="red" />
</mesh>
<Suspense>
<EffectComposer>
<Scanline />
</EffectComposer>
</Suspense>
</Canvas>
)Effects settings
Every effect inherits all the props from original postprocessing class, for example:
import React from 'react'
import { EffectComposer, Glitch } from 'react-postprocessing'
import { Canvas } from 'react-three-fiber'
const App = () => (
<Canvas>
<mesh>
<boxGeometry args={[1, 1, 1]} />
<meshBasicMaterial color="red" />
</mesh>
<Suspense>
<EffectComposer>
{/* min and max duration */}
<Glitch duration={[1, 2]} />
</EffectComposer>
</Suspense>
</Canvas>
)Custom effects
Currently not all of the effects are wrapped, so if you require some effects that isn't wrapped yet you cand add them manually.
Using wrapEffect
There is an utility function in react-postprocessing which wraps the postprocessing effect in React component. You can use it to quickly make a component out of effect:
import React from 'react'
import { EffectComposer, wrapEffect } from 'react-postprocessing'
import { NoiseEffect } from 'postprocessing'
import { Canvas } from 'react-three-fiber'
const Noise = wrapEffect(NoiseEffect)
const App = () => (
<Canvas>
<mesh>
<boxGeometry args={[1, 1, 1]} />
<meshBasicMaterial color="red" />
</mesh>
<Suspense>
<EffectComposer>
<Noise />
</EffectComposer>
</Suspense>
</Canvas>
)Currently types aren't being passed properly in
wrapEffect, it returnsRefWithExoticComponent<any>where instead of any should be the effect class. Feel free to submit a PR to fix it!
From scratch
If the effect doesn't use object literals for props, PixelationEffect for instance, you can wrap your own component using forwardRef and useImperativeHandle and define your own props:
import { forwardRef, useImperativeHandle, useMemo } from 'react'
import { PixelationEffect } from 'postprocessing'
export const Pixelation = forwardRef(({ granularity = 5 }, ref) => {
const effect = useMemo(() => new PixelationEffect(granularity), [granularity])
useImperativeHandle(ref, () => effect, [effect])
return null
})In case you want to do add a custom prop that isn't inherited from postprocessing you should watch this prop with useLayoutEffect:
import { forwardRef, useMemo, useImperativeHandle, useLayoutEffect } from 'react'
import { useThree, ReactThreeFiber } from 'react-three-fiber'
import { DepthOfFieldEffect } from 'postprocessing'
import { Texture } from 'three'
export const DepthOfField = forwardRef(({ target, depthTexture, ...props }, ref) => {
const { camera } = useThree()
const effect = useMemo(() => new DepthOfFieldEffect(camera, props), [props])
// custom `depthTexture` prop
useLayoutEffect(() => {
if (depthTexture) {
effect.setDepthTexture(depthTexture.texture, depthTexture.packing)
}
}, [depthTexture])
useImperativeHandle(ref, () => effect, [effect])
return null
})