Skip to content

Commit 050b15a

Browse files
authored
feat(Fbo): ref component support (#2477)
* Fbo ref + doc + better props inheritance * doc
1 parent 4ae523a commit 050b15a

File tree

2 files changed

+56
-38
lines changed

2 files changed

+56
-38
lines changed

docs/misc/fbo-use-fbo.mdx

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,17 @@ sourcecode: src/core/Fbo.tsx
55

66
[![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.vercel.app/?path=/story/misc-fbo)
77

8-
Creates a `THREE.WebGLRenderTarget`.
8+
<Intro>Creates a `THREE.WebGLRenderTarget`.</Intro>
99

1010
```tsx
11-
type FBOSettings = {
12-
/** Defines the count of MSAA samples. Can only be used with WebGL 2. Default: 0 */
13-
samples?: number
14-
/** If set, the scene depth will be rendered into buffer.depthTexture. Default: false */
15-
depth?: boolean
16-
} & THREE.RenderTargetOptions
11+
type FBOSettings = Omit<FboProps, 'width' | 'height' | 'children'>
1712

1813
export function useFBO(
1914
/** Width in pixels, or settings (will render fullscreen by default) */
2015
width?: number | FBOSettings,
2116
/** Height in pixels */
2217
height?: number,
23-
/**Settings */
18+
/** Settings, see constructor's `options`: https://threejs.org/docs/#api/en/renderers/WebGLRenderTarget */
2419
settings?: FBOSettings
2520
): THREE.WebGLRenderTarget {
2621
```
@@ -30,3 +25,32 @@ const target = useFBO({ stencilBuffer: false })
3025
```
3126
3227
The rendertarget is automatically disposed when unmounted.
28+
29+
## `<Fbo>` Component
30+
31+
```tsx
32+
export type FboProps = {
33+
children?: (renderTarget: Fbo) => React.ReactNode
34+
width: UseFBOParams[0]
35+
height: UseFBOParams[1]
36+
} & FBOSettings
37+
```
38+
39+
You can access the renderTarget via children's render prop:
40+
41+
```jsx
42+
<Fbo width={1024} height={1024} stencilBuffer={false}>
43+
{(renderTarget) => (
44+
<mesh>
45+
<planeGeometry />
46+
<meshBasicMaterial map={renderTarget.texture} />
47+
</mesh>
48+
)}
49+
```
50+
51+
or exposed via `ref`:
52+
53+
```jsx
54+
const renderTargetRef = useRef()
55+
<Fbo ref={renderTargetRef} />
56+
```

src/core/Fbo.tsx

Lines changed: 24 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,15 @@
11
import * as React from 'react'
22
import * as THREE from 'three'
33
import { useThree } from '@react-three/fiber'
4+
import { forwardRef } from 'react'
5+
6+
type WebGLRenderTargetCtorParams = ConstructorParameters<typeof THREE.WebGLRenderTarget>
7+
type WebGLRenderTargetOptions = WebGLRenderTargetCtorParams[2]
48

59
type FBOSettings = {
6-
/** Defines the count of MSAA samples. Can only be used with WebGL 2. Default: 0 */
7-
samples?: number
8-
/** If set, the scene depth will be rendered into buffer.depthTexture. Default: false */
10+
/** @deprecated use `depthBuffer` instead. If set, the scene depth will be rendered into buffer.depthTexture. Default: false */
911
depth?: boolean
10-
11-
// WebGLRenderTargetOptions => RenderTargetOptions
12-
wrapS?: THREE.Wrapping | undefined
13-
wrapT?: THREE.Wrapping | undefined
14-
magFilter?: THREE.MagnificationTextureFilter | undefined
15-
minFilter?: THREE.MinificationTextureFilter | undefined
16-
format?: number | undefined // RGBAFormat;
17-
type?: THREE.TextureDataType | undefined // UnsignedByteType;
18-
anisotropy?: number | undefined // 1;
19-
depthBuffer?: boolean | undefined // true;
20-
stencilBuffer?: boolean | undefined // false;
21-
generateMipmaps?: boolean | undefined // true;
22-
depthTexture?: THREE.DepthTexture | undefined
23-
colorSpace?: THREE.ColorSpace | undefined
24-
}
12+
} & WebGLRenderTargetOptions
2513

2614
// 👇 uncomment when TS version supports function overloads
2715
// export function useFBO(settings?: FBOSettings)
@@ -40,6 +28,8 @@ export function useFBO(
4028
const _settings = (typeof width === 'number' ? settings : (width as FBOSettings)) || {}
4129
const { samples = 0, depth, ...targetSettings } = _settings
4230

31+
const depthBuffer = depth ?? _settings.depthBuffer // backwards compatibility for deprecated `depth` prop
32+
4333
const target = React.useMemo(() => {
4434
const target = new THREE.WebGLRenderTarget(_width, _height, {
4535
minFilter: THREE.LinearFilter,
@@ -48,7 +38,7 @@ export function useFBO(
4838
...targetSettings,
4939
})
5040

51-
if (depth) {
41+
if (depthBuffer) {
5242
target.depthTexture = new THREE.DepthTexture(_width, _height, THREE.FloatType)
5343
}
5444

@@ -68,17 +58,21 @@ export function useFBO(
6858
return target
6959
}
7060

71-
export const Fbo = ({
72-
children,
73-
width,
74-
height,
75-
...settings
76-
}: {
77-
children?: (target: ReturnType<typeof useFBO>) => React.ReactNode
78-
width: Parameters<typeof useFBO>[0]
79-
height: Parameters<typeof useFBO>[1]
80-
} & FBOSettings) => {
61+
//
62+
// Fbo component
63+
//
64+
65+
type UseFBOParams = Parameters<typeof useFBO>
66+
type Fbo = ReturnType<typeof useFBO>
67+
68+
export type FboProps = {
69+
children?: (target: Fbo) => React.ReactNode
70+
width: UseFBOParams[0]
71+
height: UseFBOParams[1]
72+
} & FBOSettings
73+
74+
export const Fbo = /* @__PURE__ */ forwardRef<Fbo, FboProps>(({ children, width, height, ...settings }, fref) => {
8175
const target = useFBO(width, height, settings)
8276

8377
return <>{children?.(target)}</>
84-
}
78+
})

0 commit comments

Comments
 (0)