Note: react-three-shader-passes
(R3SP
) is currently still in pre-release stages.
This library is designed for Three.js/React apps built on react-three-fiber (R3F). Check out and support the ecosystem and @pmndrs.
→ Easily chain shader passes, using the rendered texture from one scene as a uniform
type input to any other shader pass
→ Ideal for raw physics simulations and for effects, post processing, optimization, and complex shader-based logic
→ Use output textures of any scene or shader as an FBO input to another without cumbersome, hierarchical JSX code or complex ref
-based code design
→ Use chaining capabilities as a GPGPU solution that's fully hooked into your React app, or as a simple framework for modular shader logic
→ Fully declarative API and implementation for a turnkey R3F integration
→ Exports additional utilities and helpers for even more R3F syntactic sugar
→ Fully managed objects/components implemented on top of R3F ecosystem; you have full control of all objects but do not have to worry about memory if you don't need to
Use with react-three-fiber
to create chained, modular shader passes.
npm i [TODO]
ShaderPass
is just a wrapper of RenderTexture
under the hood. You place instances of it in a ShaderPassesTexture
to easily use the output texture of any other ShaderPass
render.
This is best illustrated with an example. The code below renders two scenes in a portal using RenderTexture
and accepts all props that RenderTexture
does.
In addition to accepting the same children
as RenderTexture
, ShaderPass
optionally takes as children
a function, (fbos) => children
. fbos
contains ref
s to each scene's FBO texture output, keyed by the name
prop of the corresponding ShaderPass
.
The code snippet below shows an invisible scene being rendered and its output being used as an input uniform
FBO texture to the fragment shader of a THREE.RawShaderMaterial
used in a second invisible scene. The output of the second scene is then attached as the map
to a material in a third, visible scene.
// Example
<mesh>
<Geometry />
<meshStandardMaterial>
<ShaderPassesTexture>
<ShaderPass name="firstPass">
<Camera />
<mesh>
<Geometry/>
<ShaderMaterial {...uniforms} />
</mesh>
</ShaderPass>
<ShaderPass name="secondPass" attach="map">
{(fbos) => (
<>
<Camera2 />
<mesh>
<Geometry/>
<ShaderMaterial2
{
...uniforms2,
inputFbo: fbos?.firstPass.current
}
/>
</mesh>
</>
)}
</ShaderPass>
</ShaderPassesTexture>
</meshStandardMaterial>
</mesh>
import { ShaderPassesTexture } from 'react-three-shader-passes'
Wraps any number of ShaderPass
components among its props.children
and registers their output textures to pass through to ShaderPass
instances that need to use them (e.g., as a shader uniform
input for further calculations).
prop | type | description |
---|---|---|
children |
React.ReactNode | React.ReactNode[] |
ShaderPass instances can be rendered at any level in the children tree.To benefit from this API, at least one of these ShaderPass instances should utilize the function-as-children pattern to access another ShaderPass 's output. Otherwise, use RenderTexture instead of ShaderPass and omit this component.
|
Behaves exactly as RenderTexture
, which it renders at the top level.
The only difference is that ShaderPass
must be rendered as a descendent of ShaderPassesTexture
and can, in addition to a React.ReactNode
, optionally take a single function (fbos) => React.ReactNode
as children.
import { ShaderPass } from 'react-three-shader-passes'
prop | type | description |
---|---|---|
children |
React.ReactNode | (fbos) => React.ReactNode |
As plain JSX, identical to @pmndrs/drei/RenderTexture 's props.children . Alternatively, a function that returns the above. It will be called with one argument: an object containing the textures from any other ShaderPass in the same ShaderPassesTexture , keyed by props.name .
<ShaderPass name="somePass"> ... </ShaderPass> <ShaderPass name="someOtherPass" /> { ({ somePass }) => <> ... <ShaderMaterial someUniform={somePass.current}/> ... </> } </ShaderPass> |
name |
string |
Required. In the object passed as argument to any props.children in function form, this will be used as a property name referencing the texture returned from the underlying RenderTexture
|
...RenderTextureProps |
Object |
Props that go into a RenderTexture . E.g., setting props.renderPriority allows you to control the rendering order of the shader passes.
|
import { getParent, withParent } from 'react-three-shader-passes'
An alternative to using instance.__r3f.parent
(see useInstanceHandle
here).
Provides a React ref
to the parent of non-Object3D
primitives (e.g. materials). Unlike Object3D
instances, these do not have a built-in (.parent
) reference to the containing object in the scene graph.
Using inside a component:
function MaterialWithParentInternal(props) {
const parent = useRef()
useEffect(() => {
console.log(parent.current), [parent]
})
return (
<>
<meshStandardMaterial {...props} />
<GetParent ref={parent} />
</>
)
}
Using inside the component and exposing to parent:
forwardRef(function MaterialWithParentInternalAndExternal(props, ref) {
const internal = useRef()
const parent = useRef()
useImperativeHandle(ref, () => ({ ...internal.current, parent: parent.current }))
return (
<>
<meshStandardMaterial ref={internal} {...props} />
<GetParent ref={parent} />
</>
)
})
Only exposing to parent (ref
will include added .parent
property):
const MyMaterialWithParentExternal = withParent(MyMaterial)
const Anscestor = () => {
const descendentParent = useRef()
useEffect(() => {
console.log(descendentParent.current.parent)
}, [])
return <MyMaterialWithParentExternal ref={descendentParent} />
}
Optional custom parent key:
const MyMaterialWithParentExternal = withParent(MyMaterial, 'parentKey')
const Anscestor = () => {
const descendentParent = useRef()
useEffect(() => {
console.log(descendentParent.current.parentKey)
}, [])
return <MyMaterialWithParentExternal ref={descendantParent} />
}